Showing preview only (2,856K chars total). Download the full file or copy to clipboard to get everything.
Repository: objcio/articles
Branch: master
Commit: ce8898e42548
Files: 150
Total size: 2.7 MB
Directory structure:
gitextract_pol5nsbk/
├── 2013-06-07-containment-view-controller.md
├── 2013-06-07-introduction.markdown
├── 2013-06-07-lighter-view-controllers.md
├── 2013-06-07-table-views.md
├── 2013-06-07-testing-view-controllers.md
├── 2013-07-07-async-testing.md
├── 2013-07-07-common-background-practices.md
├── 2013-07-07-concurrency-apis-and-pitfalls.md
├── 2013-07-07-editorial.markdown
├── 2013-07-07-low-level-concurrency-apis.md
├── 2013-07-07-thread-safe-class-design.md
├── 2013-08-07-advanced-auto-layout-toolbox.md
├── 2013-08-07-collection-view-layouts.md
├── 2013-08-07-custom-controls.markdown
├── 2013-08-07-editorial.md
├── 2013-08-07-moving-pixels-onto-the-screen.md
├── 2013-08-07-scroll-view.md
├── 2013-09-09-SQLite-instead-of-core-data.markdown
├── 2013-09-09-core-data-fetch-requests.md
├── 2013-09-09-core-data-migration.md
├── 2013-09-09-core-data-models-and-model-objects.md
├── 2013-09-09-core-data-overview.md
├── 2013-09-09-editorial.md
├── 2013-09-09-full-core-data-application.md
├── 2013-09-09-importing-large-data-sets-into-core-data.md
├── 2013-10-08-collection-views-and-uidynamics.md
├── 2013-10-08-editorial.md
├── 2013-10-08-from-nsurlconnection-to-nsurlsession.md
├── 2013-10-08-getting-to-know-textkit.md
├── 2013-10-08-iOS7-hidden-gems-and-workarounds.md
├── 2013-10-08-multitasking.md
├── 2013-10-08-redesigning-for-ios-7.md
├── 2013-10-08-view-controller-transitions.md
├── 2013-11-08-build-process.md
├── 2013-11-08-cocoapods-under-the-hood.md
├── 2013-11-08-compiler.markdown
├── 2013-11-08-editorial.md
├── 2013-11-08-mach-o-executables.md
├── 2013-11-08-travis-ci.markdown
├── 2013-12-07-collections.md
├── 2013-12-09-communication-patterns.md
├── 2013-12-09-editorial.md
├── 2013-12-09-key-value-coding-and-observing.md
├── 2013-12-09-linguistic-tagging.md
├── 2013-12-09-nsformatter.md
├── 2013-12-09-value-objects.md
├── 2014-01-08-communicating-with-the-quadcopter.md
├── 2014-01-08-editorial.md
├── 2014-01-08-the-quadcopter-client-app.md
├── 2014-01-08-the-quadcopter-navigator-app.md
├── 2014-01-08-the-quadcopter-project.md
├── 2014-02-10-editorial.md
├── 2014-02-10-string-localization.md
├── 2014-02-10-string-parsing.md
├── 2014-02-10-string-rendering.md
├── 2014-02-10-unicode.md
├── 2014-02-10-working-with-strings.md
├── 2014-03-07-data-synchronization.md
├── 2014-03-07-editorial.md
├── 2014-03-07-icloud-core-data.md
├── 2014-03-07-icloud-document-store.md
├── 2014-03-07-ip-tcp-http.markdown
├── 2014-03-07-networked-core-data-application.md
├── 2014-03-07-sync-case-study.md
├── 2014-04-01-android-intents.md
├── 2014-04-01-android-notifications.md
├── 2014-04-01-android_101_for_ios_developers.md
├── 2014-04-01-dependency-injection-in-java.md
├── 2014-04-01-editorial.md
├── 2014-04-01-responsive-android-applications.md
├── 2014-04-01-sqlite-database-support-in-android.md
├── 2014-05-08-animating-custom-layer-properties.md
├── 2014-05-08-animations-explained.md
├── 2014-05-08-collectionview-animations.md
├── 2014-05-08-custom-container-view-controller-transitions.md
├── 2014-05-08-editorial.md
├── 2014-05-08-interactive-animations.md
├── 2014-05-08-view-layer-synergy.md
├── 2014-06-09-behaviors.md
├── 2014-06-09-editorial.md
├── 2014-06-09-mvvm.md
├── 2014-06-09-singletons.md
├── 2014-06-09-subclassing.md
├── 2014-06-09-viper.md
├── 2014-07-11-appkit-for-uikit-developers.md
├── 2014-07-11-editorial.md
├── 2014-07-11-plugins.md
├── 2014-07-11-sandbox-scripting.md
├── 2014-07-11-scripting-data.md
├── 2014-07-11-xpc.markdown
├── 2014-08-11-bad-testing-practices.md
├── 2014-08-11-behavior-driven-development.md
├── 2014-08-11-dependency-injection.md
├── 2014-08-11-editorial.md
├── 2014-08-11-mocking-stubbing.md
├── 2014-08-11-snapshot-testing.md
├── 2014-08-11-user-interface-testing.md
├── 2014-08-11-xctest.markdown
├── 2014-09-10-editorial.md
├── 2014-09-10-functional-swift-apis.md
├── 2014-09-10-power-of-swift.md
├── 2014-09-10-rapid-prototyping-in-swift-playgrounds.md
├── 2014-09-10-swift-classes-vs-structs.md
├── 2014-09-10-swift-functions.md
├── 2014-10-10-editorial.md
├── 2014-10-10-inside-code-signing.md
├── 2014-10-10-receipt-validation.md
├── 2014-10-10-why-security.md
├── 2014-11-10-designing-elegant-mobile-games.md
├── 2014-11-10-editorial.md
├── 2014-11-10-metal.md
├── 2014-11-10-multipeer-connectivity-for-games.md
├── 2014-11-10-scenekit.md
├── 2014-11-10-sound-design.md
├── 2014-12-08-activity-tracing.md
├── 2014-12-08-debugging-case-study.md
├── 2014-12-08-debugging-checklist.md
├── 2014-12-08-dtrace.markdown
├── 2014-12-08-editorial.md
├── 2014-12-08-lldb-debugging.md
├── 2015-01-13-andy-matuschak.md
├── 2015-01-13-editorial.md
├── 2015-01-13-loren-brichter.md
├── 2015-01-13-natasha-murashev.md
├── 2015-02-10-camera-capture-on-ios.md
├── 2015-02-10-core-image-intro.md
├── 2015-02-10-editorial.md
├── 2015-02-10-face-recognition-with-opencv.md
├── 2015-02-10-gpu-accelerated-image-processing.md
├── 2015-02-10-gpu-accelerated-machine-vision.md
├── 2015-02-10-how-your-camera-works.md
├── 2015-02-10-image-formats.md
├── 2015-02-10-photo-extensions.md
├── 2015-02-10-the-photos-framework.md
├── 2015-03-10-artsy.md
├── 2015-03-10-dropbox.md
├── 2015-03-10-editorial.md
├── 2015-03-10-facebook.md
├── 2015-03-10-omni-group.md
├── 2015-03-10-square.md
├── 2015-04-13-capturing-video.md
├── 2015-04-13-core-image-video.md
├── 2015-04-13-editorial.md
├── 2015-04-13-videotoolbox.md
├── 2015-05-11-audio-api-overview.md
├── 2015-05-11-audio-dog-house.md
├── 2015-05-11-editorial.md
├── 2015-05-11-functional-signal-processing.md
├── 2015-05-11-sound-design.md
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: 2013-06-07-containment-view-controller.md
================================================
---
title: "View Controller Containment"
category: "1"
date: "2013-06-07 08:00:00"
author:
- name: Ricki Gregersen
url: https://twitter.com/rickigregersen
tags: article
---
Before iOS 5, view controller containers were a privilege for Apple only.
In fact, there was a passage in the view controller programming guide
stating that you should not use them.
The general advice from Apple on view controllers used to be that <q>a
view controller manages a screenful of content</q>.
This has since changed to <q>a view controller manages a self-contained
unit of content</q>.
Why didn't Apple want us to build our own tab bar controllers and
navigation controllers? Or put more precisely, what is the problem with:
```objc
[viewControllerA.view addSubView:viewControllerB.view]
```

The UIWindow, which serves as an app's root view, is where rotation and
initial layout messages originate from. In the
illustration above, the child view controller, whose view was inserted
in the root view controller view hierarchy, is excluded from those events.
View event methods like `viewWillAppear:` will not get called.
The custom view controller containers built before iOS 5 would keep a
reference to the child view controllers and manually relay all the
view event methods called on the parent view controller, which is
pretty difficult to get right.
## An Example
When you were a kid playing in the sand, did your parents ever tell you that if you kept digging with your little shovel you would end up in China?
Mine did, and I made a small demo app called *Tunnel* to test this claim.
You can clone the [GitHub
repo](https://github.com/objcio/issue-1-view-controller-containment) and run the
app, which will make it easier to understand the example code.
*(Spoiler: digging through the earth from western Denmark lands you somewhere in the South Pacific Ocean.)*

To find the antipode, as the opposite location is called, move the little guy with the shovel around and the map will tell you where your exit location is. Tap the radar button and the map will flip to reveal the name of the location.
There are two map view controllers on screen. Each of them has to deal with dragging, annotation, and updating the map.
Flipping these over reveals two new view controllers which reverse geocode the locations.
All the view controllers are contained inside a parent view controller, which holds their views, and ensures that layout and rotation behaves as expected.
The root view controller has two container views. These are added to
make it easier to layout and animate the views of child view
controllers, as we will see later on.
```objc
- (void)viewDidLoad
{
[super viewDidLoad];
//Setup controllers
_startMapViewController = [RGMapViewController new];
[_startMapViewController setAnnotationImagePath:@"man"];
[self addChildViewController:_startMapViewController]; // 1
[topContainer addSubview:_startMapViewController.view]; // 2
[_startMapViewController didMoveToParentViewController:self]; // 3
[_startMapViewController addObserver:self
forKeyPath:@"currentLocation"
options:NSKeyValueObservingOptionNew
context:NULL];
_startGeoViewController = [RGGeoInfoViewController new]; // 4
}
```
The `_startMapViewController`, which displays the starting position, is instantiated and set up with the annotation image.
1. The `_startMapViewController` is added as a child of the root view
controller. This automatically calls
the method `willMoveToParentViewController:` on the child.
2. The child's view is added as a subview of the first container view.
3. The child is notified that it now has a parent view controller.
4. The child view controller that does the geocoding is instantiated,
but not inserted in any view or controller hierarchy yet.
## Layout
The root view controller defines the two container views,
which determine the size of the child view controllers.
The child view controllers do not know which container they will be
added to, and therefore have to be flexible in size:
```objc
- (void) loadView
{
mapView = [MKMapView new];
mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
[mapView setDelegate:self];
[mapView setMapType:MKMapTypeHybrid];
self.view = mapView;
}
```
Now they will layout using the bounds of their super view. This increases the reusability of the child view controller; if we were to push it on the stack of a navigation controller, it would still layout correctly.
## Transitions
Apple has made the view controller containment API so fine-grained that
it is possible to construct and animate any containment scenario we can
think of.
Apple also provides a block-based convenience method for exchanging two controller views on the screen.
The method
`transitionFromViewController:toViewController:(...)`
takes care of a lot of the details for us:
```objc
- (void) flipFromViewController:(UIViewController*) fromController
toViewController:(UIViewController*) toController
withDirection:(UIViewAnimationOptions) direction
{
toController.view.frame = fromController.view.bounds; // 1
[self addChildViewController:toController]; //
[fromController willMoveToParentViewController:nil]; //
[self transitionFromViewController:fromController
toViewController:toController
duration:0.2
options:direction | UIViewAnimationOptionCurveEaseIn
animations:nil
completion:^(BOOL finished) {
[toController didMoveToParentViewController:self]; // 2
[fromController removeFromParentViewController]; // 3
}];
}
```
1. Before the animation we add the `toController` as a child and we
inform the `fromController` that it will be removed. If the fromController's view is part of the container's view hierarchy, this is where `viewWillDisappear:` is called.
2. `toController` is informed of its new parent, and appropriate view
event methods will be called.
3. The `fromController` is removed.
This convenience method for view controller transitions automatically swaps out the old view controller's view for the new one. However, if you implement your own transition and you wish to only display one view at a time, you have to call `removeFromSuperview` on the old view and `addSubview:` for the new view yourself. Getting the sequence of method calls wrong will most likely result in an `UIViewControllerHierarchyInconsistency` warning. For example, this will
happen if you call `didMoveToParentViewController:` before you added the view.
In order to be able to use the `UIViewAnimationOptionTransitionFlipFromTop` animation, we had to add the children's views to our view containers instead of to the root view controller's view. Otherwise the animation would result in the entire root view flipping over.
## Communication
View controllers should be reusable and self-contained entities. Child view controllers are no exception to this rule of thumb. In order to achieve this, the parent view controller should only be concerned with two tasks: laying out the child view controller's root view, and communicating with the child view controller through its exposed API. It should never modify the child's view tree or other internal state directly.
Child view controllers should contain the necessary logic to manage their view trees themselves -- don't treat them as dumb views. This will result in a clearer separation of concerns and better reusability.
In the Tunnel example app, the parent view controller observes a property called `currentLocation` on the map view controllers:
```objc
[_startMapViewController addObserver:self
forKeyPath:@"currentLocation"
options:NSKeyValueObservingOptionNew
context:NULL];
```
When this property changes in response to moving the little guy with the shovel around on the map, the parent view controller communicates the antipode of the new location to the other map:
```objc
[oppositeController updateAnnotationLocation:[newLocation antipode]];
```
Likewise, when you tap the radar button, the parent view controller sets the locations to be reverse geocoded on the new child view controllers:
```objc
[_startGeoViewController setLocation:_startMapViewController.currentLocation];
[_targetGeoViewController setLocation:_targetMapViewController.currentLocation];
```
Independent of the technique you choose to communicate from child to parent view controllers (KVO, notifications, or the delegate pattern), the goal always stays the same: the child view controllers should be independent and reusable. In our example we could push one of the child view controllers on a navigation stack, but the communication would still work through the same API.
================================================
FILE: 2013-06-07-introduction.markdown
================================================
---
title: "Introduction"
category: "1"
date: "2013-06-07 12:00"
tags: editorial
---
Welcome to the first edition of objc.io, a periodical about best practices and advanced techniques in Objective-C!
objc.io was founded in Berlin by [Chris Eidhof](https://twitter.com/chriseidhof), [Daniel Eggert](https://twitter.com/danielboedewadt), and [Florian Kugler](https://twitter.com/floriankugler). We started objc.io to create a regular platform for in-depth technical topics relevant to all iOS and OS X developers.
Each edition of objc.io has a focus on one particular subject, with multiple articles covering different aspects of that topic. The subject of this first edition is *Lighter View Controllers*, and it contains four articles – three from the founding team and one from [Ricki Gregersen](https://twitter.com/rickigregersen), whom we would like to welcome as our first guest writer!
It's a common problem in the code base of iOS apps that view controllers get out of hand, because they do too much. By factoring out reusable code, they are easier to understand, easier to maintain and easier to test. This issue will focus on best practices and techniques how you can keep view controllers clean.
We will look at how to make view controllers primarily coordinating objects by factoring out view and model code, as well as introducing other controller objects in addition to view controllers. Furthermore, we will look at splitting up view controllers using the view controller containment mechanism, and finally, discuss how to test clean view controllers.
In upcoming editions we will have more articles from great guest writers of the Objective-C community; [Loren Brichter](https://twitter.com/lorenb), [Peter Steinberger](https://twitter.com/steipete), [Brent Simmons](https://twitter.com/brentsimmons), and [Ole Begemann](https://twitter.com/olebegemann) have committed to writing in the future. [Contact us](mailto:mail@objc.io) if you have an idea for an interesting topic and you would like to contribute an article about it to objc.io.
Chris, Daniel, and Florian.
================================================
FILE: 2013-06-07-lighter-view-controllers.md
================================================
---
title: "Lighter View Controllers"
category: "1"
date: "2013-06-07 11:00:00"
author:
- name: Chris Eidhof
url: http://twitter.com/chriseidhof
tags: article
---
View controllers are often the biggest files in iOS
projects, and they often contain way more code than necessary. Almost always,
view controllers are the least reusable part of the code. We will look
at techniques to slim down your view controllers, make code reusable, and move code to more appropriate places.
The [example project](https://github.com/objcio/issue-1-lighter-view-controllers) for this issue is on GitHub.
## Separate Out Data Source and Other Protocols
One of the most powerful techniques to slim down your view controller is
to take the `UITableViewDataSource` part of your code, and move it to
its own class. If you do this more than once, you will start to see
patterns and create reusable classes for this.
For example, in our example project, there is a class
`PhotosViewController` which had the following methods:
```objc
# pragma mark Pragma
- (Photo*)photoAtIndexPath:(NSIndexPath*)indexPath {
return photos[(NSUInteger)indexPath.row];
}
- (NSInteger)tableView:(UITableView*)tableView
numberOfRowsInSection:(NSInteger)section {
return photos.count;
}
- (UITableViewCell*)tableView:(UITableView*)tableView
cellForRowAtIndexPath:(NSIndexPath*)indexPath {
PhotoCell* cell = [tableView dequeueReusableCellWithIdentifier:PhotoCellIdentifier
forIndexPath:indexPath];
Photo* photo = [self photoAtIndexPath:indexPath];
cell.label.text = photo.name;
return cell;
}
```
<a id="controllers"> </a>
A lot of this code has to do with arrays, and some of it is
specific to the photos that the view controller manages. So let's try to move the array-related code into its [own
class](https://github.com/objcio/issue-1-lighter-view-controllers/blob/master/PhotoData/ArrayDataSource.h).
We use a block for configuring the cell, but it might as well be
a delegate, depending on your use-case and taste.
```objc
@implementation ArrayDataSource
- (id)itemAtIndexPath:(NSIndexPath*)indexPath {
return items[(NSUInteger)indexPath.row];
}
- (NSInteger)tableView:(UITableView*)tableView
numberOfRowsInSection:(NSInteger)section {
return items.count;
}
- (UITableViewCell*)tableView:(UITableView*)tableView
cellForRowAtIndexPath:(NSIndexPath*)indexPath {
id cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier
forIndexPath:indexPath];
id item = [self itemAtIndexPath:indexPath];
configureCellBlock(cell,item);
return cell;
}
@end
```
The three methods that were in your view controller can go, and instead
you can create an instance of this object and set it as the table view's
data source.
```objc
void (^configureCell)(PhotoCell*, Photo*) = ^(PhotoCell* cell, Photo* photo) {
cell.label.text = photo.name;
};
photosArrayDataSource = [[ArrayDataSource alloc] initWithItems:photos
cellIdentifier:PhotoCellIdentifier
configureCellBlock:configureCell];
self.tableView.dataSource = photosArrayDataSource;
```
Now you don't have to worry about mapping an index path to a
position in the array, and every time you want to display an
array in a table view you can reuse this code. You can also implement
additional methods such as
`tableView:commitEditingStyle:forRowAtIndexPath:` and share that code among
all your table view controllers.
The nice thing is that we can [test this class](/issues/1-view-controllers/testing-view-controllers/#testing-a-data-source) separately,
and never have to worry about writing it again. The same principle
applies if you use something else other than arrays.
In one of the applications we were working on this year,
we made heavy use of Core Data. We created a similar class, but instead
of being backed by an array, it is backed by a
fetched results controller. It implements all the logic for
animating the updates, doing section headers, and deletion. You can
then create an instance of this object and feed it a fetch request and a
block for configuring the cell, and the rest will be taken care of.
Furthermore, this approach extends to other protocols as well. One
obvious candidate is `UICollectionViewDataSource`. This gives you
tremendous flexibility; if, at some point during the development, you
decide to have a `UICollectionView` instead of a `UITableView`, you
hardly have to change anything in your view controller. You could even
make your data source support both protocols.
## Move Domain Logic into the Model
Here is an example of code in view controller (from another project) that is supposed to find a list of active
priorities for a user:
```objc
- (void)loadPriorities {
NSDate* now = [NSDate date];
NSString* formatString = @"startDate <= %@ AND endDate >= %@";
NSPredicate* predicate = [NSPredicate predicateWithFormat:formatString, now, now];
NSSet* priorities = [self.user.priorities filteredSetUsingPredicate:predicate];
self.priorities = [priorities allObjects];
}
```
However, it is much cleaner to move this code to a category on the `User` class. Then
it looks like this in `View Controller.m`:
```objc
- (void)loadPriorities {
self.priorities = [self.user currentPriorities];
}
```
and in `User+Extensions.m`:
```objc
- (NSArray*)currentPriorities {
NSDate* now = [NSDate date];
NSString* formatString = @"startDate <= %@ AND endDate >= %@";
NSPredicate* predicate = [NSPredicate predicateWithFormat:formatString, now, now];
return [[self.priorities filteredSetUsingPredicate:predicate] allObjects];
}
```
Some code cannot be easily moved into a model object but is still
clearly associated with model code, and for this, we can use a `Store`:
## Creating the Store Class
In the first version of our example application, we had some code to
load data from a file and parse it. This code was in the view
controller:
```objc
- (void)readArchive {
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
NSURL *archiveURL = [bundle URLForResource:@"photodata"
withExtension:@"bin"];
NSAssert(archiveURL != nil, @"Unable to find archive in bundle.");
NSData *data = [NSData dataWithContentsOfURL:archiveURL
options:0
error:NULL];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
_users = [unarchiver decodeObjectOfClass:[NSArray class] forKey:@"users"];
_photos = [unarchiver decodeObjectOfClass:[NSArray class] forKey:@"photos"];
[unarchiver finishDecoding];
}
```
The view controller should not have to know about this.
We created a *Store* object that does just this. By separating it
out, we can reuse that code, test it separately and keep our view
controller small. The store can take care of data loading, caching,
and setting up the database stack. This store is also often called a
*service layer* or a *repository*.
## Move Web Service Logic to the Model Layer
This is very similar to the topic above: don't do web service logic in
your view controller. Instead, encapsulate this in a different class.
Your view controller can then call methods on this class with a callback
handler (for example, a completion block).
The nice thing is that you can do all your caching and error handling in
this class too.
## Move View Code into the View Layer
Building complicated view hierarchies shouldn't be done in view
controllers. Either use interface builder, or encapsulate views into
their own `UIView` subclasses. For example, if you build your own date
picker control, it makes more sense to put this into a
`DatePickerView` class than creating the whole thing in the view
controller. Again, this increases reusability and simplicity.
If you like Interface Builder, then you can also do this in
Interface Builder. Some people assume you can only use this for view
controllers, but you can also load separate nib files with your custom
views. In our example app, we created a [`PhotoCell.xib`](https://github.com/objcio/issue-1-lighter-view-controllers/blob/master/PhotoData/PhotoCell.xib) that
contains the layout for a photo cell:

As you can see, we created properties on the view (we don't use the
File's Owner object in this xib) and connect them to specific subviews.
This technique is also very handy for other custom views.
## Communication
One of the other things that happen a lot in view controllers is
communication with other view controllers, the model, and the views.
While this is exactly what a controller should do, it is also something
we'd like to achieve with as minimal code as possible.
There are a lot of well-explained techniques for communication between
your view controllers and your model objects (such as KVO and fetched
results controllers), however, communication between view controllers is
often a bit less clear.
We often have the problem where one view controller has some state and
communicates with multiple other view controllers. Often, it then makes
sense to put this state into a separate object and pass it around the
view controllers, which then all observe and modify that state. The
advantage is that it's all in one place, and we don't end up entangled
in nested delegate callbacks. This is a complex subject, and we might
dedicate a whole issue to this in the future.
## Conclusion
We've seen some techniques for creating smaller view controllers. We
don't strive to apply these techniques wherever possible, as we have only
one goal: to write maintainable code. By knowing these patterns, we have better
chances of taking unwieldy view controllers and making them clearer.
### Further Reading
* [View Controller Programming Guide for iOS](http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html)
* [Cocoa Core Competencies: Controller Object](http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/ControllerObject.html)
* [Writing high quality view controllers](http://subjective-objective-c.blogspot.de/2011/08/writing-high-quality-view-controller.html)
* [Programmers Stack Exchange: Model View Controller Store](http://programmers.stackexchange.com/questions/184396/mvcs-model-view-controller-store)
* [Unburdened View Controllers](https://speakerdeck.com/trianglecocoa/unburdened-viewcontrollers-by-jay-thrash)
* [Programmers Stack Exchange: How to avoid big and clumsy `UITableViewControllers` on iOS](http://programmers.stackexchange.com/questions/177668/how-to-avoid-big-and-clumsy-uitableviewcontroller-on-ios)
================================================
FILE: 2013-06-07-table-views.md
================================================
---
title: "Clean Table View Code"
category: "1"
date: "2013-06-07 10:00:00"
author:
- name: Florian Kugler
url: http://twitter.com/floriankugler
tags: article
---
Table views are an extremely versatile building block for iOS apps. Therefore, a lot of code is directly or indirectly related to table view tasks, including supplying data, updating the table view, controlling its behavior, and reacting to selections, to name just a few. In this article, we will present techniques to keep this code clean and well-structured.
## UITableViewController vs. UIViewController
Apple provides `UITableViewController` as dedicated view controller class for table views. Table view controllers implement a handful of very useful features which can help you to avoid writing the same boilerplate code over and over. On the flip side, table view controllers are restricted to managing exactly one table view, which is presented full screen. However, in many cases, this is all you need, and if it's not, there are ways to work around this, as we will show below.
### Features of Table View Controllers
Table view controllers help you with loading the table view's data
when it is shown for the first time. More specifically, it helps with toggling the table view's
editing mode, with reacting to the keyboard notifications, and
with a few small tasks like flashing the scroll indicator and clearing
the selection. In order for these features to work, it is important that
you call super on any view event methods (such as `viewWillAppear:` and `viewDidAppear:`) that you may override in your custom subclass.
Table view controllers have one unique selling point over standard view controllers, and that's the support for Apple's implementation for "pull to refresh." At the moment, the only documented way of using `UIRefreshControl` is within a table view controller. There are ways to make it work in other contexts, but these could easily not work with the next iOS update.
The sum of all these elements provides much of the standard table view interface behavior as Apple has defined it. If your app conforms to these standards, it is a good idea to stick with table view controllers in order to avoid writing boilerplate code.
### Limitations of Table View Controllers
The view property of table view controllers always has to be set to a table view. If you decide later on that you want to show something else on the screen aside from the table view (e.g. a map), you are out of luck if you don't want to rely on awkward hacks.
If you have defined your interface in code or using a .xib file, then it is pretty easy to transition to a standard view controller. If you're using storyboards, then this process involves a few more steps. With storyboards, you cannot change a table view controller to a standard view controller without recreating it. This means you have to copy all the contents over to the new view controller and wire everything up again.
Finally, you need to add back the features of table view controller that you lost in this transition. Most of them are simple single-line statements in `viewWillAppear` or `viewDidAppear`. Toggling the editing state requires implementing an action method which flips the table view's `editing` property. The most work lies in recreating the keyboard support.
Before you go down this route though, here is an easy alternative that has the additional benefit of separating concerns:
### Child View Controllers
Instead of getting rid of the table view controller entirely, you could
also add it as a child view controller to another view controller (see
the [article about view controller containment](/issues/1-view-controllers/containment-view-controller/) in this issue). Then the table view controller continues to manage only the table view and the parent view controller can take care of whatever additional interface elements you might need.
```objc
- (void)addPhotoDetailsTableView
{
DetailsViewController *details = [[DetailsViewController alloc] init];
details.photo = self.photo;
details.delegate = self;
[self addChildViewController:details];
CGRect frame = self.view.bounds;
frame.origin.y = 110;
details.view.frame = frame;
[self.view addSubview:details.view];
[details didMoveToParentViewController:self];
}
```
If you use this solution you have to create a communication channel from
the child to the parent view controller. For example, if the user selects a cell in the table view, the parent view controller needs to know about this in order to push another view controller. Depending on the use case, often the cleanest way to do this is to define a delegate protocol for the table view controller, which you then implement on the parent view controller.
```objc
@protocol DetailsViewControllerDelegate
- (void)didSelectPhotoAttributeWithKey:(NSString *)key;
@end
@interface PhotoViewController () <DetailsViewControllerDelegate>
@end
@implementation PhotoViewController
// ...
- (void)didSelectPhotoAttributeWithKey:(NSString *)key
{
DetailViewController *controller = [[DetailViewController alloc] init];
controller.key = key;
[self.navigationController pushViewController:controller animated:YES];
}
@end
```
As you can see, this construction comes with the price of some overhead to communicate between the view controllers in return for a clean separation of concerns and better reusability. Depending on the specific use case, this can either end up making things more simple or more complex than necessary. That's for you to consider and decide.
## Separating Concerns
When dealing with table views there are a variety of different tasks involved which cross the borders between models, controllers, and views. In order to prevent view controllers from becoming the place for all these tasks, we will try to isolate as many of these tasks as possible in more appropriate places. This helps readability, maintainability, and testability.
The techniques described here extend and elaborate upon the concepts
demonstrated in the article [Lighter view controllers](/issues/1-view-controllers/lighter-view-controllers/). Please refer to this article for how to factor our data source and model logic. In the context of table views, we will specifically look at how to separate concerns between view controllers and views.
### Bridging the Gap Between Model Objects and Cells
At some point we have to hand over the data we want to display into the view layer. Since we still want to maintain a clear separation between the model and the view, we often offload this task to the table view's data source:
```objc
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PhotoCell"];
Photo *photo = [self itemAtIndexPath:indexPath];
cell.photoTitleLabel.text = photo.name;
NSString* date = [self.dateFormatter stringFromDate:photo.creationDate];
cell.photoDateLabel.text = date;
}
```
This kind of code clutters the data source with specific knowledge about the design of the cell. We are better off factoring this out into a category of the cell class:
```objc
@implementation PhotoCell (ConfigureForPhoto)
- (void)configureForPhoto:(Photo *)photo
{
self.photoTitleLabel.text = photo.name;
NSString* date = [self.dateFormatter stringFromDate:photo.creationDate];
self.photoDateLabel.text = date;
}
@end
```
With this in place, our data source method becomes very simple.
```objc
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView dequeueReusableCellWithIdentifier:PhotoCellIdentifier];
[cell configureForPhoto:[self itemAtIndexPath:indexPath]];
return cell;
}
```
In our example code, the data source for this table view is [factored
out into its own controller object](/issues/1-view-controllers/lighter-view-controllers/#separate-out-data-source-and-other-protocols), which gets initialized with a cell configuration block. In this case, the block becomes as simple as this:
```objc
TableViewCellConfigureBlock block = ^(PhotoCell *cell, Photo *photo) {
[cell configureForPhoto:photo];
};
```
### Making Cells Reusable
In cases where we have multiple model objects that can be presented using the same cell type, we can even go one step further to gain reusability of the cell. First, we define a protocol on the cell to which an object must conform in order to be displayed by this cell type. Then we simply change the configure method in the cell category to accept any object conforming to this protocol. These simple steps decouple the cell from any specific model object and make it applicable to different data types.
### Handling Cell State Within the Cell
If we want to do something beyond the standard highlighting or selection behavior of table views, we could implement two delegate methods, which modify the tapped cell in the way we want. For example:
```objc
- (void)tableView:(UITableView *)tableView
didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.photoTitleLabel.shadowColor = [UIColor darkGrayColor];
cell.photoTitleLabel.shadowOffset = CGSizeMake(3, 3);
}
- (void)tableView:(UITableView *)tableView
didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.photoTitleLabel.shadowColor = nil;
}
```
However, the implementation of these two delegate methods relies again on specific knowledge about how the cell is implemented. If we want to swap out the cell or redesign it in a different way, we also have to adapt the delegate code. The implementation details of the view are complected with the implementation of the delegate. Instead, we should move this logic into the cell itself.
```objc
@implementation PhotoCell
// ...
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
if (highlighted) {
self.photoTitleLabel.shadowColor = [UIColor darkGrayColor];
self.photoTitleLabel.shadowOffset = CGSizeMake(3, 3);
} else {
self.photoTitleLabel.shadowColor = nil;
}
}
@end
```
Generally speaking, we strive to separate the implementation details of the view layer from the implementation details of the controller layer. A delegate has to know about the different states a view can be in, but it shouldn't have to know how to modify the view tree or which attributes to set on some subviews in order to get it into the right state. All this logic should be encapsulated within the view, which then provides a simple API to the outside.
### Handling Multiple Cell Types
If you have multiple different cell types within one table view, the data source methods can quickly get out of hand. In our example app we have two different cell types for the photo details table: one cell to display a star rating, and a generic cell to display a key-value pair. In order to separate the code dealing with these different cell types, the data source method simply dispatches the request to specialized methods for each cell type.
```objc
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *key = self.keys[(NSUInteger) indexPath.row];
id value = [self.photo valueForKey:key];
UITableViewCell *cell;
if ([key isEqual:PhotoRatingKey]) {
cell = [self cellForRating:value indexPath:indexPath];
} else {
cell = [self detailCellForKey:key value:value];
}
return cell;
}
- (RatingCell *)cellForRating:(NSNumber *)rating
indexPath:(NSIndexPath *)indexPath
{
// ...
}
- (UITableViewCell *)detailCellForKey:(NSString *)key
value:(id)value
{
// ...
}
```
### Table View Editing
Table views provide easy-to-use editing features, which allow for
reordering and deletion of cells. In case of these events, the table
view's data source gets notified via [delegate methods](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDataSource/tableView:commitEditingStyle:forRowAtIndexPath:). Therefore, we often see domain logic in these delegate methods that performs the actual modification on the data.
Modifying data is a task that clearly belongs in the model layer. The model should expose an API for things like deletion and reordering, which we can then call from the data source methods. This way, the controller plays the role of a coordinator between the view and the model, but does not have to know about the implementation details of the model layer. As an added benefit, the model logic also becomes easier to test, because it is not interweaved with other tasks of view controllers anymore.
## Conclusion
Table view controllers (and other controller objects!) should mostly have a [coordinating and mediating role](http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/ControllerObject.html) between model and view objects. They should not be concerned with tasks that clearly belong to the view or the model layer. If you keep this in mind, the delegate and data source methods will become much smaller and mostly contain simple boilerplate code.
This not only reduces the size and complexity of table view controllers, but it puts the domain logic and view logic in much more appropriate places. Implementation details below and above the controller layer are encapsulated behind a simple API, which ultimately makes it much easier to understand the code and to work on it collaboratively.
### Further Reading
* [Blog: Skinnier Controllers using View Categories](https://web.archive.org/web/20160423142402/http://www.sebastianrehnby.com/blog/2013/01/01/skinnier-controllers-using-view-categories/)
* [Table View Programming Guide](http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/tableview_iphone/AboutTableViewsiPhone/AboutTableViewsiPhone.html)
* [Cocoa Core Competencies: Controller Object](http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/ControllerObject.html)
================================================
FILE: 2013-06-07-testing-view-controllers.md
================================================
---
title: "Testing View Controllers"
category: "1"
date: "2013-06-07 09:00"
author:
- name: Daniel Eggert
url: https://twitter.com/danielboedewadt
tags: article
---
Let's not be religious about testing. It should help us speed up development and make things more fun.
## Keeping Things Simple
Testing simple things is simple, and testing complex things is complex. As we point out in the other articles, keeping things small and simple is good in general. And as a side effect, it also helps testing. It's a win-win. Take a look at [test-driven development](https://en.wikipedia.org/wiki/Test-driven_development) (known as TDD among friends) -- some people love it, some don't. We won't go into detail about it here, but we will say that with TDD, you write the test for your code before you write the code. Check out the Wikipedia article if you’re curious. We would also like to note that refactoring and testing go very well together.
Testing UI components is often tricky because there are too many moving parts involved. More often than not, the view controller interacts with a lot of classes from both the model and the view layer. In order to be able to test the view controller, we need things to work in isolation.
There's hope, though: The techniques we describe to make [lighter view controllers](/issues/1-view-controllers/lighter-view-controllers/) also make testing easier. Generally, if you find something difficult to test, that's a hint that your design may be broken and that you should refactor some of it. Again, refer to the article about [lighter view controllers](/issues/1-view-controllers/lighter-view-controllers/) for some hints. An overall design goal is to have clear separation of concerns. Each class should do only one thing, and do that one thing well. That will then allow for testing of that one thing.
Remember: You'll get diminishing returns as you add more tests. First and foremost, add simple tests. Branch into more sophisticated territory as you start to feel comfortable with it.
## Mocking
When we break things up into small components (i.e. small classes), we can test each class on its own. The class that we're testing interacts with other classes. We get around this by using a so-called *mock* or *stub*. Think of a *mock object* as a placeholder. The class we’re testing will interact with placeholders instead of real objects. That way, we focus our test and ensure that it doesn’t depend on other parts of our app.
The example app has an array data source that we'll test. The data source will at some point dequeue a cell from a table view. During testing, we don't have a table view, but by passing a *mock* table view, we can test the data source without a *real* table view, as you'll see below. It's a bit confusing at first, but very powerful and straightforward once you've seen it a few times.
The power tool for mocking in Objective-C is called [OCMock](http://ocmock.org). It's a very mature project that leverages the power and flexibility of the Objective-C runtime. It pulls some cool tricks to make testing with mock objects fun.
The data source test below shows, in more detail, how all of this plays out together.
## SenTestKit
The other tool we'll use is the test framework that comes as part of the developer tools: SenTestingKit by [Sente](http://www.sente.ch). This dinosaur has been around for Objective-C developers since 1997 -- ten years before the iPhone was released. Today, it's built into Xcode.
SenTestingKit is what will run your tests. With SenTestingKit, you organize tests into classes. You create one test class for each class you want to test. This class will have a name ending in `Tests`, and the name reflects what the class is about.
The methods inside each of these *tests* classes will do the actual testing. The method name has to start with `test`, as that's what triggers it to get run as a test. There are special `-setUp` and `-tearDown` methods you can override to set up each test. Remember that your test class is just a class: If it helps you structure your tests, feel free to add properties and helper methods.
A nice pattern when testing is to create a custom base class for the
tests. We then put convenience logic in there to make our tests easier
and more focused. Check out the [example project](https://github.com/objcio/issue-1-lighter-view-controllers/blob/master/PhotoDataTests/PhotoDataTestCase.h) for some samples of when this might be useful. We’re also not using the Xcode templates for tests -- we’re going for something simpler and more efficient: We add a single `.m` file. By convention the tests class have a name ending in `Tests`. The name should reflect what we're testing.
## Integration with Xcode
Tests are built into a bundle of a dynamic library plus resources of your choice. If you need particular resource files for your testing, add them to the test target, and Xcode will put them inside the bundle. You can then locate them with `NSBundle`. The example project implements a `-URLForResource:withExtension:` method to make it easy to use.
Each *scheme* in Xcode defines what the corresponding test bundle should be. While ⌘-R runs your app, ⌘-U will run your tests.
The way the tests are run, your app is actually launched, and the test bundle is *injected*. You probably don't want your app to do much, as it may interfere with the testing. Put something like this into your app delegate:
```objc
static BOOL isRunningTests(void) __attribute__((const));
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (isRunningTests()) {
return YES;
}
//
// Normal logic goes here
//
return YES;
}
static BOOL isRunningTests(void)
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* injectBundle = environment[@"XCInjectBundle"];
return [[injectBundle pathExtension] isEqualToString:@"octest"];
}
```
Editing your scheme in Xcode gives you a great deal of flexibility. You can run scripts before and after the tests, and you can have multiple test bundles. This can be useful for larger projects. Most importantly, you can turn on and off individual tests. This can be useful for debugging tests -- just remember to turn them all back on.
Also remember that you can set breakpoints in your code and in test cases and the debugger will stop there as the tests are executed.
## Testing a Data Source
Let's get started. We've made testing easier by splitting up the view controller. Now we'll test the `ArrayDataSource`. First, we create a new and empty basic setup. We put both the interface and implementation into the same file; no one needs to include the `@interface` anywhere else, as it's all nice and tidy inside one file:
```objc
#import "PhotoDataTestCase.h"
@interface ArrayDataSourceTest : PhotoDataTestCase
@end
@implementation ArrayDataSourceTest
- (void)testNothing;
{
STAssertTrue(YES, @"");
}
@end
```
This will not do much. It shows the basic test setup. When we run the tests, the `-testNothing` method will run. The special `STAssert` macro will do its trivial check. Note that `ST` originates from SenTestingKit. These macros integrate with Xcode and will make failures show up in the *Issues* navigator.
## Our First Test
We'll now replace the `testNothing` method with a simple, but real test:
```objc
- (void)testInitializing;
{
STAssertNil([[ArrayDataSource alloc] init], @"Should not be allowed.");
TableViewCellConfigureBlock block = ^(UITableViewCell *a, id b){};
id obj1 = [[ArrayDataSource alloc] initWithItems:@[]
cellIdentifier:@"foo"
configureCellBlock:block];
STAssertNotNil(obj1, @"");
}
```
## Putting Mocking into Practice
Next, we want to test the
```objc
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath;
```
method that the ArrayDataSource implements. For that we create a
```objc
- (void)testCellConfiguration;
```
test method.
First we create a data source:
```objc
__block UITableViewCell *configuredCell = nil;
__block id configuredObject = nil;
TableViewCellConfigureBlock block = ^(UITableViewCell *a, id b){
configuredCell = a;
configuredObject = b;
};
ArrayDataSource *dataSource = [[ArrayDataSource alloc] initWithItems:@[@"a", @"b"]
cellIdentifier:@"foo"
configureCellBlock:block];
```
Note that the `configureCellBlock` doesn't do anything except store the objects that it was called with. This allows us to easily test it.
Next, we'll create a *mock object* for a table view:
```objc
id mockTableView = [OCMockObject mockForClass:[UITableView class]];
```
The data source is going to call `-dequeueReusableCellWithIdentifier:forIndexPath:` on the passed-in table view. We'll tell the mock object what to do when it gets this message. We first create a `cell` and then set up the *mock*:
```objc
UITableViewCell *cell = [[UITableViewCell alloc] init];
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[[[mockTableView expect] andReturn:cell]
dequeueReusableCellWithIdentifier:@"foo"
forIndexPath:indexPath];
```
This will look a bit confusing at first. What's going on here, is that the mock is *recording* this particular call. The mock is not a table view; we're just pretending that it is. The special `-expect` method allows us to set up the mock so that it knows what to do when this method gets called on it.
In addition, the `-expect` method tells the mock that this call *must* happen. When we later call `-verify` on the mock, the test will fail if the method didn't get called. The corresponding `-stub` method also sets up the mock object, but doesn’t care if the method will get called.
Now we'll trigger the code to get run. We'll call the method we want to test:
```objc
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
id result = [dataSource tableView:mockTableView
cellForRowAtIndexPath:indexPath];
```
and then we'll test that things went well:
```objc
STAssertEquals(result, cell, @"Should return the dummy cell.");
STAssertEquals(configuredCell, cell, @"This should have been passed to the block.");
STAssertEqualObjects(configuredObject, @"a", @"This should have been passed to the block.");
[mockTableView verify];
```
The `STAssert` macros test that the values are identical. Note that we use pointer comparison for the first two tests; we don't want to use `-isEqual:`. We actually want to test that `result` and `cell` and `configuredCell` all are the very same object. The third test uses `-isEqual:`, and finally we call `-verify` on our mock.
Note that in the example, we're setting up the mock with
```objc
id mockTableView = [self autoVerifiedMockForClass:[UITableView class]];
```
This is a convenience wrapper in our base test class which automatically calls `-verify` at the end of the test.
## Testing a UITableViewController
Next, we turn toward the `PhotosViewController`. It's a `UITableViewController` subclass and it uses the data source we've just tested. The code that remains in the view controller is pretty simple.
We want to test that tapping on a cell takes us to the detail view, i.e. an instance of `PhotoViewController` is pushed onto the navigation controller. We'll again use mocking to make the test depend as little as possible on other parts.
First we create a `UINavigationController` mock:
```objc
id mockNavController = [OCMockObject mockForClass:[UINavigationController class]];
```
Next up, we'll use *partial mocking*. We want our `PhotosViewController` instance to return the `mockNavController` as its `navigationController`. We can't set the navigation controller directly, so we'll simply stub only that method to return our `mockNavController` and forward everything else to the `PhotosViewController` instance:
```objc
PhotosViewController *photosViewController = [[PhotosViewController alloc] init];
id photosViewControllerMock = [OCMockObject partialMockForObject:photosViewController];
[[[photosViewControllerMock stub] andReturn:mockNavController] navigationController];
```
Now, whenever the `-navigationController` method is called on `photosViewController`, it will return the `mockNavController`. This is a very powerful trick that OCMock has up its sleeve.
We now tell the navigation controller mock what we expect to be called, i.e. a detail view controller with `photo` set to a non-nil value:
```objc
UIViewController* viewController = [OCMArg checkWithBlock:^BOOL(id obj) {
PhotoViewController *vc = obj;
return ([vc isKindOfClass:[PhotoViewController class]] &&
(vc.photo != nil));
}];
[[mockNavController expect] pushViewController:viewController animated:YES];
```
Now we trigger the view to be loaded and simulate the row to be tapped:
```objc
UIView *view = photosViewController.view;
STAssertNotNil(view, @"");
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[photosViewController tableView:photosViewController.tableView
didSelectRowAtIndexPath:indexPath];
```
Finally we verify that the expected method was called on the mocks:
```objc
[mockNavController verify];
[photosViewControllerMock verify];
```
We now have a test that tests interaction with the navigation controller and creation of the correct view controller.
Again, in the example project, we're using our own convenience methods
```objc
- (id)autoVerifiedMockForClass:(Class)aClass;
- (id)autoVerifiedPartialMockForObject:(id)object;
```
and hence we don't have to remember to call `-verify`.
## Further Possibilities
As you've seen above, *partial mocking* is extremely powerful. If you take a look at the source code of the `-[PhotosViewController setupTableView]` method, you'll see how it gets the model objects through the app delegate:
```objc
NSArray *photos = [AppDelegate sharedDelegate].store.sortedPhotos;
```
The above test depends on this. One way to break this dependency would be to again use *partial mocking* to make the app delegate return predefined data like so:
```objc
id storeMock; // assume we've set this up
id appDelegate = [AppDelegate sharedDelegate]
id appDelegateMock = [OCMockObject partialMockForObject:appDelegate];
[[[appDelegateMock stub] andReturn:storeMock] store];
```
Now whenever `[AppDelegate sharedDelegate].store` gets called, it will return the `storeMock`. This can be taken to extremes. Make sure to keep your tests as simple as possible and only as complex as needed.
## Things to Remember
Partial mocks alter the object they're mocking for as long as they're around. You can stop that behavior early by calling `[aMock stopMocking]`. Most of the time, you want the partial mock to stay active for the entire duration of the test. Make sure that happens by putting a `[aMock verify]` at the end of the test method. Otherwise ARC might dealloc the mock early. And you probably want that `-verify` anyway.
## Testing NIB Loading
The `PhotoCell` is setup in a NIB. We can write a simple test that checks that the outlets are set up correctly. Let's review the `PhotoCell` class:
```objc
@interface PhotoCell : UITableViewCell
+ (UINib *)nib;
@property (weak, nonatomic) IBOutlet UILabel* photoTitleLabel;
@property (weak, nonatomic) IBOutlet UILabel* photoDateLabel;
@end
```
Our simple test implementation looks like this
```objc
@implementation PhotoCellTests
- (void)testNibLoading;
{
UINib *nib = [PhotoCell nib];
STAssertNotNil(nib, @"");
NSArray *a = [nib instantiateWithOwner:nil options:@{}];
STAssertEquals([a count], (NSUInteger) 1, @"");
PhotoCell *cell = a[0];
STAssertTrue([cell isMemberOfClass:[PhotoCell class]], @"");
// Check that outlets are set up correctly:
STAssertNotNil(cell.photoTitleLabel, @"");
STAssertNotNil(cell.photoDateLabel, @"");
}
@end
```
Very basic, but it does its job.
One may argue that we now need to update both the test and the class / nib when we change things. That's true. We need to weigh this against the likelihood of breaking the outlets. If you've worked with `.xib` files, you've probably noticed that this is a commonly occurring thing.
## Side Note About Classes and Injection
As we noted under *Integration with Xcode* the test bundle gets injected into the app. Without getting into too much detail about how injection works (it's a huge topic in its own right): Injection adds the Objective-C classes from the injected bundle (our test bundle) to the running app. That's good, because it allows us to run our tests.
One thing that can be very confusing, though, is if we add a class to both the app and the test bundle. If we, in the above example, would (by accident) have added the `PhotoCell` class to both the test bundle and the app, then the call to `[PhotoCell class]` would return a different pointer when called from inside our test bundle - that from within the app. And hence our test
```objc
STAssertTrue([cell isMemberOfClass:[PhotoCell class]], @"");
```
would fail. Again: Injection is complex. Your take away should be: Don't add `.m` files from your app to your test target. You'll get unexpected behavior.
## Additional Thoughts
If you have a Continuous Integration solution, getting your tests up and running there is a great idea. Details are outside the scope of this article. The scripts are triggered by the `RunUnitTests` script, and there's a `TEST_AFTER_BUILD` environment variable.
Another interesting option is to create an independent test bundle for automated performance tests. You're free to do whatever you want inside your test methods. Timing certain calls and using `STAssert` to check that they're within a certain threshold would be one option.
### Further Reading
* [Test-driven development](https://en.wikipedia.org/wiki/Test-driven_development)
* [OCMock](http://ocmock.org)
* [Xcode Unit Testing Guide](https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/UnitTesting/)
* [Book: Test Driven Development: By Example](http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530)
* [Blog: Quality Coding](http://qualitycoding.org)
* [Blog: iOS Unit Testing](http://iosunittesting.com)
* [Blog: Secure Mac Programing](http://blog.securemacprogramming.com/?s=testing&searchsubmit=Search)
================================================
FILE: 2013-07-07-async-testing.md
================================================
---
title: "Testing Concurrent Applications"
category: "2"
tags: article
date: "2013-07-07 06:00:00"
author:
- name: Tobias Kräntzer
url: http://twitter.com/anagrom_ataf/
---
Testing is an important tool during the development process to create high quality applications. In the past, when concurrency was not such an important part of application architecture, testing was straightforward. Over the past few years it has become more and more important to use concurrent design patterns and we were challenged to develop new best practices to test them.
The main challenge of testing concurrent code is that the program or information flow is not reflected in the call stack any more. Functions do not return their result to the caller immediately, but deliver it later via callback functions, blocks, notifications, or similar mechanisms, which makes testing more difficult.
However, testing asynchronous code comes with the benefit of uncovering poor design decisions and facilitating clean implementations.
## The Problem with Asynchronous Testing
Let's first recall an example of a simple synchronous unit test. This method of a simple calculator should sum up two numbers:
```objc
+ (int)add:(int)a to:(int)b {
return a + b;
}
```
Testing this method is as simple as calling the method and comparing the result to the expected value. If the values don't match, the test fails.
```objc
- (void)testAddition {
int result = [Calculator add:2 to:2];
STAssertEquals(result, 4, nil);
}
```
Now let's change the method to return its result asynchronously via a completion block. We will also add a bug to the implementation, so that we can expect a failing test:
```objc
+ (int)add:(int)a to:(int)b block:(void(^)(int))block {
[[NSOperationQueue mainQueue] addOperationWithBlock^{
block(a - b); // Buggy implementation
}];
}
```
Of course this is a contrived example, but it reflects the general pattern you would use often if the operation would be more computationally intensive.
A naive approach to testing this method would just move the assertion into the completion block. However, such a test simply never fails, in spite of the bug in our implementation:
```objc
// don't use this code!
- (void)testAdditionAsync {
[Calculator add:2 to:2 block^(int result) {
STAssertEquals(result, 4, nil); // Never fails!
}];
}
```
Why doesn't this assertion fail?
## SenTestingKit Under the Hood
The testing framework used by Xcode 4 is based on [OCUnit][4], which allows us to have a closer look at the internals. To understand the problem with the asynchronous test, we need to have a look at the execution order of the different parts of the test suite. This diagram shows a simplified flow.

After the testing kit is started on the main run loop, it executes the following main steps:
1. It sets up a test suite containing all relevant tests (as specified e.g. in the project scheme).
2. It runs the suite, which internally invokes all methods of the test cases starting with _test_. This run returns an object, containing the results of each single test.
3. It exits the process by calling `exit()`.
The interesting part is how each individual test is invoked. During the asynchronous test, the completion block containing the assertion gets enqueued on the main run loop. Since the testing framework exits the process after all tests run, this block never gets executed and therefore never causes the test to fail.
There are several approaches to solve this problem. But all of them have to run the main run loop and handle the enqueued operations before the test method returns and the framework checks the result.
[Kiwi][5] uses a probe poller, which can be invoked within the test method. [GHUnit][6] provides a separate test class, which has to be prepared within the test method and which needs a notification at the end. In both cases we have to write some code, which ensures that the test method will not return until the test finishes.
## Async Extension to SenTestingKit
Our solution to this problem is an [extension][2] to the built-in testing kit, which winds up the synchronous execution on the stack and enqueues each part as a block on the main queue. As you can see in the diagram below, the block that reports the success or failure of the asynchronous test is enqueued before the results of the entire suite are checked. This execution order allows us to fire up a test and wait for its result.

To give the framework a hint that a test should be treated as asynchronous, the method name has to end with __Async__. Furthermore, in asynchronous tests, we have to report the success of the test case manually and include a timeout, in case the completion block never gets called. We can rewrite our faulty test from above like this:
```objc
- (void)testAdditionAsync {
[Calculator add:2 to:2 block^(int result) {
STAssertEquals(result, 4, nil);
STSuccess(); // Calling this macro reports success
}];
STFailAfter(2.0, @"Timeout");
}
```
## Designing Asynchronous Tests
As with their synchronous counterparts, asynchronous tests should always be a magnitude simpler than the implementation they are testing. Complex tests don't promote better code quality, because the possibility of bugs in the tests increases. In a test-driven development process, simple tests let us think more clearly about the borders of components, their interfaces, and the expected behavior of the architecture.
### Example Project
To put all this into practice, we create an example framework called [PinacotecaCore][3], which requests information of images from a hypothetical server. It has a resource manager, which is the developer-facing interface, providing a method to get an image object with an image id. In the background, the resource manager fetches the information from the server and updates the properties in the database.
Although this is only an example project for the sake of demonstration, it shares the pattern we use in several of our apps.

With this high level overview of the architecture we can dive into the tests of the framework. In general there are three components which should be tested:
1. the model layer
2. the server API controller, which abstracts the requests to the server
3. the resource manager, which manages the core data stack and ties the model layer and the API controller together
### Model Layer
Tests should be synchronous whenever possible, and the model layer is a good example. As long as there are no complicated dependencies between different managed object contexts, the test cases should set up their own core data stack with a context on the main thread in which to execute their operations.
In this example, the [test case][7] sets up the core data stack in `setUp`, checks if the entity description for `PCImage` is present, creates an object with the constructor, and updates its values. As this has nothing to do with asynchronous testing, we won't go into further details here.
### Server API Controller
The second building block of the architecture is the server API controller. It contains the logic to manage the mapping of the server API to the model and handles the requests. In general, we want to evaluate the behavior of the following method:
```objc
- [PCServerAPIController fetchImageWithId:queue:completionHandler:]
```
It should be called with the id of an image and call the completion handler on the given queue.
Because the server doesn't exist yet, and because it's a good habit, we will stub the network request with [OHHTTPStubs][8]. With the newest version, the project can contain a bundle with example responses, which will be delivered to the client.
To stub a request, OHHTTPStubs has to be configured either in our test setup or in the test itself. First we have to load the bundle containing the responses:
```objc
NSURL *url = [[NSBundle bundleForClass:[self class]]
URLForResource:@"ServerAPIResponses"
withExtension:@"bundle"];
NSBundle *bundle = [NSBundle url];
```
Then we can load the response from the bundle and specify for which request it should be returned:
```objc
OHHTTPStubsResponse *response;
response = [OHHTTPStubsResponse responseNamed:@"images/123"
fromBundle:responsesBundle
responseTime:0.1];
[OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
return YES /* true, if it's the expected request */;
} withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
return response;
}];
```
With this setup, the simplified version of the [API controller test][9] looks like this:
```objc
- (void)testFetchImageAsync
{
[self.server
fetchImageWithId:@"123"
queue:[NSOperationQueue mainQueue]
completionHandler:^(id imageData, NSError *error) {
STAssertEqualObjects([NSOperationQueue currentQueue], queue, nil);
STAssertNil(error, [error localizedDescription]);
STAssertTrue([imageData isKindOfClass:[NSDictionary class]], nil);
// Check the values of the returned dictionary.
STSuccess();
}];
STFailAfter(2.0, nil);
}
```
### Resource Manager
The last component is the resource manager, which ties the model layer and the API controller together and manages the core data stack. Here we want to test the method to get an image object:
```objc
-[PCResourceManager imageWithId:usingManagedObjectContext:queue:updateHandler:]
```
This method should return an image object for the given id. If this image is not in the database, it will return a new object containing only the id and call the API controller to request the detailed information.
Since the test of the resource manager should not depend on the API controller, we will stub it with [OCMock][10], which is ideal for partial stubs of methods. This is done in the [resource manager test][11]:
```objc
OCMockObject *mo;
mo = [OCMockObject partialMockForObject:self.resourceManager.server];
id exp = [[serverMock expect]
andCall:@selector(fetchImageWithId:queue:completionHandler:)
onObject:self];
[exp fetchImageWithId:OCMOCK_ANY queue:OCMOCK_ANY completionHandler:OCMOCK_ANY];
```
Instead of calling the real method of the API controller, the test will use the method implemented in the test case itself.
With this in place, the test of the resource manager is straightforward. It calls the manager to get a resource, which internally will call the stubbed method on the API controller. There we can check if the controller is called with the correct parameters. After invoking the result handler, the resource manager updates the model and will call the result handler of our test.
```objc
- (void)testGetImageAsync
{
NSManagedObjectContext *ctx = self.resourceManager.mainManagedObjectContext;
__block PCImage *img;
img = [self.resourceManager imageWithId:@"123"
usingManagedObjectContext:ctx
queue:[NSOperationQueue mainQueue]
updateHandler:^(NSError *error) {
// Check if the error is nil and
// if the image has been updated.
STSuccess();
}];
STAssertNotNil(img, nil);
STFailAfter(2.0, @"Timeout");
}
```
## Conclusion
Testing applications using concurrent design patterns can be challenging at first, but once you understand the differences and establish best practices, it is easy and a lot of fun.
At [nxtbgthng][1] we are using the process described, [SenTestingKitAsync][2], on a daily basis. But the other approaches, like [Kiwi][5] or [GHUnit][6], are also good ways of doing asynchronous testing. You should try them all, find your preferred tool, and start testing asynchronously.
[1]: http://nxtbgthng.com "nxtbgthng"
[2]: https://github.com/nxtbgthng/SenTestingKitAsync "SenTestingKitAsync"
[3]: https://github.com/objcio/issue-2-async-testing "Pinacoteca Core: Cocoa Framework for an Imaginary Image Service"
[4]: http://www.sente.ch/software/ocunit/ "OCUnit"
[5]: https://github.com/allending/Kiwi "Kiwi"
[6]: https://github.com/gabriel/gh-unit/ "GHUnit"
[7]: https://github.com/objcio/issue-2-async-testing/blob/master/PinacotecaCore/PinacotecaCoreTests/PCModelLayerTests.m "Pinacoteca Core Model Layer Tests"
[8]: https://github.com/AliSoftware/OHHTTPStubs "OHHTTPStubs"
[9]: https://github.com/objcio/issue-2-async-testing/blob/master/PinacotecaCore/PinacotecaCoreTests/PCServerAPIControllerTests.m "Pinacoteca Core Server API Controller Tests"
[10]: http://ocmock.org "OCMock"
[11]: https://github.com/objcio/issue-2-async-testing/blob/master/PinacotecaCore/PinacotecaCoreTests/PCResourceManagerTests.m "Pinacoteca Core Resource Manager Tests"
================================================
FILE: 2013-07-07-common-background-practices.md
================================================
---
title: "Common Background Practices"
category: "2"
date: "2013-07-07 09:00:00"
author:
- name: Chris Eidhof
url: http://twitter.com/chriseidhof
tags: article
---
In this article we will describe best practices for doing common
tasks in the background. We will look at how to use Core Data concurrently,
how to draw concurrently, and how to do asynchronous networking. Finally,
we'll look at how to process large files asynchronously while keeping a
low memory profile.
With asynchronous programming it is very easy to make mistakes. Therefore, all
examples in this article will use a very simple approach. Using
simple structures helps us to think through our code and to maintain an overview.
If you end up with complicated nested callbacks, you should probably revise some of your design decisions.
## Operation Queues vs. Grand Central Dispatch
Currently, there are two main modern concurrency APIs available on iOS and OS X:
[operation queues](http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html)
and [Grand Central Dispatch](https://developer.apple.com/library/ios/#documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html) (GCD).
GCD is a low-level C API, whereas operation queues are implemented
on top of GCD and provide an Objective-C API. For a more comprehensive
overview of available concurrency APIs see the [concurrency APIs and challenges][100]
article in this issue.
Operation queues offer some useful convenience features not easily
reproducible with GCD. In practice, one of the most important ones is
the possibility to cancel operations in the queue, as we will demonstrate below.
Operation queues also make it a bit easier to manage dependencies between operations.
On the flip side, GCD gives you more control and low-level functionality that
is not available with operation queues. Please refer to the
[low level concurrency APIs][300] article for more details.
Further reading:
* [StackOverflow: NSOperation vs. Grand Central Dispatch](http://stackoverflow.com/questions/10373331/nsoperation-vs-grand-central-dispatch)
* [Blog: When to use NSOperation vs. GCD](http://eschatologist.net/blog/?p=232)
### Core Data in the Background
**Update March 2015**: This is based off of older recommendations in the now outdated Core Data Concurrency Guide.
Before doing anything concurrent with Core Data, it is important to get
the basics right. We strongly recommend reading through Apple's [Concurrency
with Core Data](https://developer.apple.com/library/mac/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html) guide.
This document lays down the ground rules, such as never passing managed objects between
threads. This doesn't just mean that you should never modify a managed object on another
thread, but also that you should never read any properties from it. To pass around
an object, pass its object ID and retrieve the object from the context associated to the
other thread.
Doing concurrent programming with Core Data is simple when you stick to those rules
and use the method described in this article.
The standard setup for Core Data in the Xcode templates is one
persistent store coordinator with one managed object context that runs
on the main thread. For many use cases, this is just fine.
Creating some new objects and modifying existing objects is very cheap and can
be done on the main thread without problems.
However, if you want to do big chunks of work, then it makes sense to do this
in a background context. A prime example for this is importing large data sets
into Core Data.
Our approach is very simple, and well-covered in existing literature:
1. We create a separate operation for the import work
2. We create a managed object context with the same persistent store
coordinator as the main managed object context
3. Once the import context saves, we notify the main managed object
context and merge the changes
In the [example application](https://github.com/objcio/issue-2-background-core-data), we will import a big set of transit data for
the city of Berlin.
During the import, we show a progress indicator, and we'd like to be able
to cancel the current
import if it's taking too long. Also, we show a table view with all the
data available so far, which automatically updates when new data comes in.
The example data set is publicly available under the Creative
Commons license, and you can download it [here](http://stg.daten.berlin.de/datensaetze/vbb-fahrplan-2013). It conforms to the [General Transit
Feed](https://developers.google.com/transit/gtfs/reference) format, an
open standard for transit data.
We create an `ImportOperation` as a subclass of `NSOperation`, which will handle
the import. We override the `main` method, which is
the method that will do all the work. Here we create a separate
managed object context with the private queue concurrency type. This means that
this context will manage its own queue, and all operations on it
need to be performed using `performBlock` or `performBlockAndWait`.
This is crucial to make sure that they will be executed on the right thread.
```objc
NSManagedObjectContext* context = [[NSManagedObjectContext alloc]
initWithConcurrencyType:NSPrivateQueueConcurrencyType];
context.persistentStoreCoordinator = self.persistentStoreCoordinator;
context.undoManager = nil;
[self.context performBlockAndWait:^
{
[self import];
}];
```
Note that we reuse the existing persistent store coordinator.
In modern code, you should initialize managed object contexts with either
the `NSPrivateQueueConcurrencyType` or the `NSMainQueueConcurrencyType`.
The third concurrency type constant, `NSConfinementConcurrencyType`, is for
legacy code, and our advice is to not use it anymore.
To do the import, we iterate over the lines in our file and create a
managed object for each line that we can parse:
```objc
[lines enumerateObjectsUsingBlock:
^(NSString* line, NSUInteger idx, BOOL* shouldStop)
{
NSArray* components = [line csvComponents];
if(components.count < 5) {
NSLog(@"couldn't parse: %@", components);
return;
}
[Stop importCSVComponents:components intoContext:context];
}];
```
To start this operation, we perform the following code from our view
controller:
```objc
ImportOperation* operation = [[ImportOperation alloc]
initWithStore:self.store fileName:fileName];
[self.operationQueue addOperation:operation];
```
For importing in the background, that's all you have to do. Now, we will add
support for cancelation, and luckily, it's as simple as adding one check
inside the enumeration block:
```objc
if(self.isCancelled) {
*shouldStop = YES;
return;
}
```
Finally, to support progress indication, we create a `progressCallback`
property on our operation. It is vital that we update our progress indicator on the main thread, otherwise UIKit will crash.
```objc
operation.progressCallback = ^(float progress)
{
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
self.progressIndicator.progress = progress;
}];
};
```
To call the progress block, we add the following line in the enumeration block:
```objc
self.progressCallback(idx / (float) count);
```
However, if you run this code, you will see that everything slows down
enormously. Also, it looks like the operation doesn't cancel
immediately. The reason for this is that the main operation queue fills up with
blocks that want to update the progress indicator. A simple solution is to decrease
the granularity of updates, i.e. we only call the progress callback for
one percent of the lines imported:
```objc
NSInteger progressGranularity = lines.count / 100;
if (idx % progressGranularity == 0) {
self.progressCallback(idx / (float) count);
}
```
### Updating the Main Context
The table view in our app is backed by a fetched results controller
on the main thread. During and after the import, we'd like
to show the results of the import in our table view.
There is one missing piece to make this work; the data imported into the
background context will not propagate to the main context unless we explicitly
tell it to do so. We add the following line to the `init` method of the `Store` class where we set up the Core Data stack:
```objc
[[NSNotificationCenter defaultCenter]
addObserverForName:NSManagedObjectContextDidSaveNotification
object:nil
queue:nil
usingBlock:^(NSNotification* note)
{
NSManagedObjectContext *moc = self.mainManagedObjectContext;
if (note.object != moc)
[moc performBlock:^(){
[moc mergeChangesFromContextDidSaveNotification:note];
}];
}];
}];
```
Note that by calling `performBlock:` on the main managed object context, the block will be called on the main thread.
If you now start the app, you will notice that the table view reloads
its data at the end of the import. However, this blocks the user interface
for a couple of seconds.
To fix this, we need to do something that we should have
done anyway: save in batches. When doing large imports, you want to
ensure that you save regularly, otherwise you might run out of memory, and
performance generally will get worse. Furthermore, saving regularly
spreads out the work on the main thread to update the table view over time.
How often you save is a matter of trial and
error. Save too often, and you'll spend too much time doing I/O. Save too
little, and the app will become unresponsive. We set the batch
size to 250 after trying out some different numbers. Now the import is
smooth, updates the table view, and doesn't block the main context for
too long.
### Other Considerations
In the import operation, we read the entire file into a string and then
split that into lines. This will work for relatively small files,
but for larger files, it makes sense to lazily read the file line by line.
The last example in this article will do exactly that by using input streams.
There's also an excellent [write-up on
StackOverflow](http://stackoverflow.com/questions/3707427/how-to-read-data-from-nsfilehandle-line-by-line/3711079#3711079)
by Dave DeLong that shows how to do this.
Instead of importing a large data set into core data when the app first runs,
you could also ship an sqlite file within your app bundle, or download it
from a server, where you could even generate it dynamically.
If your particular use case works
with this solution, it will be a lot faster and save processing time on the device.
Finally, there is a lot of noise about child contexts these days. Our
advice is not to use them for background operations. If you create a
background context as a child of the main context, saving the background
context [will still block the main thread](http://floriankugler.com/blog/2013/4/29/concurrent-core-data-stack-performance-shootout) a lot. If you create
the main context as a child of a background context, you actually don't
gain anything compared to a more traditional setup with two independent
contexts, because you still have to merge the changes from the background to
the main context manually.
The setup with one persistent store coordinator and
two independent contexts is the proven way of doing core data in the background. Stick with it unless you have really good reasons not to.
Further reading:
* [Core Data Programming Guide: Efficiently importing data](http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CoreData/Articles/cdImporting.html)
* [Core Data Programming Guide: Concurrency with Core Data](http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CoreData/Articles/cdConcurrency.html#//apple_ref/doc/uid/TP40003385-SW1j)
* [StackOverflow: Rules for working with Core Data](http://stackoverflow.com/questions/2138252/core-data-multi-thread-application/2138332#2138332)
* [WWDC 2012 Video: Core Data Best Practices](https://developer.apple.com/videos/wwdc/2012/?id=214)
* [Book: Core Data by Marcus Zarra](http://pragprog.com/book/mzcd/core-data)
## UI Code in the Background
First of all: UIKit only works on the main thread. That said,
there are some parts of UI code which are not directly related to UIKit
and which can take a significant amount of time. These tasks can be moved
to the background to not block the main thread for too long.
But before you start moving parts of your UI code into background queues,
it's important to measure which part of your code really is the problem.
This is vital, otherwise you might be optimizing the wrong thing.
If you have identified an expensive operation that you can isolate,
put it in an operation queue:
```objc
__weak id weakSelf = self;
[self.operationQueue addOperationWithBlock:^{
NSNumber* result = findLargestMersennePrime();
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
MyClass* strongSelf = weakSelf;
strongSelf.textLabel.text = [result stringValue];
}];
}];
```
As you can see, this is not completely straightforward; we need to make
a weak reference to self, otherwise we create a retain cycle (the block
retains self, the private operation queue retains the block, and self
retains the operation queue). Within the block we convert it
back to a strong reference to make sure it doesn't get deallocated while
running the block.
### Drawing in the Background
If your measurements show that `drawRect`: is your performance bottleneck,
you can move this drawing code to the background. Before
you do that though, check if there are other ways to achieve the same effect,
e.g. by using core animation layers or pre-rendered images instead of plain
Core Graphics drawing. See [this
post](http://floriankugler.com/blog/2013/5/24/layer-trees-vs-flat-drawing-graphics-performance-across-ios-device-generations)
by Florian for graphic performance measurements on current devices, or
[this comment](https://lobste.rs/s/ckm4uw/a_performance-minded_take_on_ios_design/comments/itdkfh)
by Andy Matuschak, a UIKit engineer, to get a good feel for all the
subtleties involved.
If you do decide that your best option is to execute the drawing code
in the background, the solution is quite simple. Take the code in your
`drawRect:` method and put it in an operation. Then replace the
original view with an image view that gets updated once the operation has
completed. In your drawing method, use
`UIGraphicsBeginImageContextWithOptions` instead of `UIGraphicsGetCurrentContext`:
```objc
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
// drawing code here
UIImage *i = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return i;
```
By passing in 0 as the third parameter, the scale of the device's main screen
will be automatically filled in, and the image will look great on both
retina and non-retina devices.
If you do custom drawing in table view or collection view cells, it makes sense to put
all that into operation subclasses. You can add them to a background operation queue, and
cancel them when the user scrolls cells out of bounds from the `didEndDisplayingCell`
delegate method. All of this is explained in detail in [WWDC 2012 Session 211 -- Building Concurrent User Interfaces on iOS](https://developer.apple.com/videos/wwdc/2012/).
Instead of scheduling the drawing code in the background yourself, you should
also experiment with the `drawsAsynchronously` property of `CALayer`. However, make sure to measure the effect of this. Sometimes it speeds things up, and sometimes
it's counterproductive.
## Asynchronous Networking
All your networking should be done asynchronously.
However, with Grand Central Dispatch, you sometimes see code like this:
```objc
// Warning: please don't use this code.
dispatch_async(backgroundQueue, ^{
NSData* contents = [NSData dataWithContentsOfURL:url]
dispatch_async(dispatch_get_main_queue(), ^{
// do something with the data.
});
});
```
This might look quite smart, but there is a big problem with this code: there
is no way to cancel this synchronous network call. It will block the
thread until it's done. In case the operation times out, this might take a
very long time (e.g. `dataWithContentsOfURL` has a timeout of 30 seconds).
If the queue is a serial queue, then it will be blocked for the whole time. If the queue is concurrent, then GCD has to spin up a new thread in order to make up for the thread which you are blocking. Both cases are not good. It's best to avoid blocking altogether.
To improve upon this situation, we will use the asynchronous methods of
`NSURLConnection` and wrap everything up in an operation. This way we get the
full power and convenience of operation queues; we can easily control
the number of concurrent operations, add dependencies, and cancel
operations.
However, there is something to watch out for when doing this: URL
connections deliver their events in a run loop. It is easiest to just
use the main run loop for this, as the data delivery doesn't take much
time. Then we can dispatch the processing of the incoming data onto
a background thread.
Another possibility is the approach that libraries like [AFNetworking](http://afnetworking.com) take:
create a separate thread, set up a run loop on this thread, and schedule
the url connection there. But you probably wouldn't want to do this yourself.
To kick off the URL connection, we override the `start` method in our custom operation subclass:
```objc
- (void)start
{
NSURLRequest* request = [NSURLRequest requestWithURL:self.url];
self.isExecuting = YES;
self.isFinished = NO;
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
self.connection = [NSURLConnection connectionWithRequest:request
delegate:self];
}];
}
```
Since we overrode the `start` method, we now must manage the
operation's state properties, `isExecuting` and `isFinished`, ourselves.
To cancel an operation, we need to cancel the connection and then set
the right flags so the operation queue knows the operation is done.
```objc
- (void)cancel
{
[super cancel];
[self.connection cancel];
self.isFinished = YES;
self.isExecuting = NO;
}
```
When the connection finishes loading, it sends a delegate callback:
```objc
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.data = self.buffer;
self.buffer = nil;
self.isExecuting = NO;
self.isFinished = YES;
}
```
And that's all there is to it. Check the [example project on GitHub](https://github.com/objcio/issue-2-background-networking)
for the full source code.
To conclude, we would like to recommend either taking your time to do this
right, or to use a library like
[AFNetworking](http://afnetworking.com). They
provide handy utilities like a category on `UIImageView` that asynchronously loads an image from a URL.
Using this in your table view code will automatically take care of
canceling image loading operations.
Further reading:
* [Concurrency Programming Guide](http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008091-CH1-SW1)
* [NSOperation Class Reference: Concurrent vs. Non-Concurrent Operations](http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html%23http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html%23//apple_ref/doc/uid/TP40004591-RH2-SW15)
* [Blog: synchronous vs. asynchronous NSURLConnection](http://www.cocoaintheshell.com/2011/04/nsurlconnection-synchronous-asynchronous/)
* [GitHub: `SDWebImageDownloaderOperation.m`](https://github.com/rs/SDWebImage/blob/master/SDWebImage/SDWebImageDownloaderOperation.m)
* [Blog: Progressive image download with ImageIO](http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/)
* [WWDC 2012 Session 211: Building Concurrent User Interfaces on iOS](https://developer.apple.com/videos/wwdc/2012/)
## Advanced: File I/O in the Background
In our core data background example, we read the entire file
that is to be imported into memory.
This works for smaller files, but for larger files this is not
feasible, because memory is limited on iOS devices.
To resolve this problem, we will build a class that does two things:
it reads a file line by line without having the entire file in
memory, and process the file on a background queue so the app stays
responsive.
For this purpose we use `NSInputStream`, which will let us do asynchronous
processing of a file. As [the documentation](http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/FileSystemProgrammingGUide/TechniquesforReadingandWritingCustomFiles/TechniquesforReadingandWritingCustomFiles.html)
says: <q>If you always read or write a file’s contents from start to
finish, streams provide a simple interface for doing so
asynchronously.</q>.
Whether you use streams or not, the general pattern for reading a file
line-by-line is as follows:
1. Have an intermediate buffer that you append to while not finding a newline
2. Read a chunk from the stream
3. For each newline found in the chunk, take the intermediate buffer,
append data from the stream up to (and including) the newline, and output that
4. Append the remaining bytes to the intermediate buffer
5. Go back to 2 until the stream closes
To put this into practice, we created a [sample application](https://github.com/objcio/issue-2-background-file-io) with a
`Reader` class that does just this. The interface is very simple:
```objc
@interface Reader : NSObject
- (void)enumerateLines:(void (^)(NSString*))block
completion:(void (^)())completion;
- (id)initWithFileAtPath:(NSString*)path;
@end
```
Note that this is not a subclass of `NSOperation`. Like URL connections,
input streams deliver
their events using a run loop. Therefore, we will use the main run loop
again for event delivery, and then dispatch the processing of the data
onto a background operation queue.
```objc
- (void)enumerateLines:(void (^)(NSString*))block
completion:(void (^)())completion
{
if (self.queue == nil) {
self.queue = [[NSOperationQueue alloc] init];
self.queue.maxConcurrentOperationCount = 1;
}
self.callback = block;
self.completion = completion;
self.inputStream = [NSInputStream inputStreamWithURL:self.fileURL];
self.inputStream.delegate = self;
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.inputStream open];
}
```
Now the input stream will send us delegate messages (on the main
thread), and we do the processing on the operation
queue by adding a block operation:
```objc
- (void)stream:(NSStream*)stream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
...
case NSStreamEventHasBytesAvailable: {
NSMutableData *buffer = [NSMutableData dataWithLength:4 * 1024];
NSUInteger length = [self.inputStream read:[buffer mutableBytes]
maxLength:[buffer length]];
if (0 < length) {
[buffer setLength:length];
__weak id weakSelf = self;
[self.queue addOperationWithBlock:^{
[weakSelf processDataChunk:buffer];
}];
}
break;
}
...
}
}
```
Processing a data chunk looks at the current buffered data and appends
the newly streamed chunk. It then breaks that into components, separated
by newlines, and emits each line. The remainder gets stored again:
```objc
- (void)processDataChunk:(NSMutableData *)buffer;
{
if (self.remainder != nil) {
[self.remainder appendData:buffer];
} else {
self.remainder = buffer;
}
[self.remainder obj_enumerateComponentsSeparatedBy:self.delimiter
usingBlock:^(NSData* component, BOOL last) {
if (!last) {
[self emitLineWithData:component];
} else if (0 < [component length]) {
self.remainder = [component mutableCopy];
} else {
self.remainder = nil;
}
}];
}
```
If you run the sample app, you will see that the app stays very
responsive, and the memory stays very low (in our test runs, the heap
size stayed under 800 KB, regardless of the file size). For processing
large files chunk by chunk, this technique is probably what you want.
Further reading:
* [File System Programming Guide: Techniques for Reading and Writing Files Without File Coordinators](http://developer.apple.com/library/ios/#documentation/FileManagement/Conceptual/FileSystemProgrammingGUide/TechniquesforReadingandWritingCustomFiles/TechniquesforReadingandWritingCustomFiles.html)
* [StackOverflow: How to read data from NSFileHandle line by line?](http://stackoverflow.com/questions/3707427/how-to-read-data-from-nsfilehandle-line-by-line)
## Conclusion
In the examples above we demonstrated how to perform common tasks
asynchronously in the background. In all of these solutions, we tried
to keep our code simple, because it's very easy to make mistakes with
concurrent programming without noticing.
Oftentimes you might get away with just doing your work on the main thread,
and when you can, it'll make your life a lot easier. But if you find performance bottlenecks, put these tasks into the background using the
simplest approach possible.
The pattern we showed in the examples above is a safe choice for other
tasks as well. Receive events or data on the main queue, then
use a background operation queue to perform the actual work before getting
back onto the main queue to deliver the results.
[90]: /issues/2-concurrency/editorial/
[100]: /issues/2-concurrency/concurrency-apis-and-pitfalls/
[101]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#challenges
[102]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#priority_inversion
[103]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#shared_resources
[104]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#dead_locks
[200]: /issues/2-concurrency/common-background-practices/
[300]: /issues/2-concurrency/low-level-concurrency-apis/
[301]: /issues/2-concurrency/low-level-concurrency-apis/#async
[302]: /issues/2-concurrency/low-level-concurrency-apis/#multiple-readers-single-writer
[400]: /issues/2-concurrency/thread-safe-class-design/
================================================
FILE: 2013-07-07-concurrency-apis-and-pitfalls.md
================================================
---
title: "Concurrent Programming: APIs and Challenges"
category: "2"
date: "2013-07-07 10:00:00"
author:
- name: Florian Kugler
url: http://twitter.com/floriankugler
tags: article
---
[Concurrency](http://en.wikipedia.org/wiki/Concurrency_%28computer_science%29) describes the concept of running several tasks at the same time. This can either happen in a [time-shared](http://en.wikipedia.org/wiki/Preemption_%28computing%29) manner on a single CPU core, or truly in parallel if multiple CPU cores are available.
OS X and iOS provide several different APIs to enable concurrent programming. Each of these APIs has different capabilities and limitations, making them suitable for different tasks. They also sit on very different levels of abstraction. We have the possibility to operate very close to the metal, but this also comes with great responsibility to get things right.
Concurrent programming is a very difficult subject with many intricate problems and pitfalls, and it's easy to forget this while using APIs like Grand Central Dispatch or `NSOperationQueue`. This article will first give an overview of the different concurrency APIs on OS X and iOS, and then dive deeper into the inherent challenges of concurrent programming, which are independent of the specific API you use.
## Concurrency APIs on OS X and iOS
Apple's mobile and desktop operating systems provide the same APIs for concurrent programming. In this article we are going to take a look at `pthread` and `NSThread`, Grand Central Dispatch, `NSOperationQueue`, and `NSRunLoop`. Technically, run loops are the odd ones out in this list, because they don't enable true parallelism. But they are related closely enough to the topic that it's worth having a closer look.
We'll start with the lower-level APIs and move our way up to the higher-level ones. We chose this route because the higher-level APIs are built on top of the lower-level APIs. However, when choosing an API for your use case, you should consider them in the exact opposite order: choose the highest level abstraction that gets the job done and keep your concurrency model very simple.
If you're wondering why we are so persistent recommending high-level abstractions and very simple concurrency code, you should read the second part of this article, [challenges of concurrent programming](#challenges-of-concurrent-programming), as well as [Peter Steinberger's thread safety article][400].
### Threads
[Threads](http://en.wikipedia.org/wiki/Thread_%28computing%29) are subunits of processes, which can be scheduled independently by the operating system scheduler. Virtually all concurrency APIs are built on top of threads under the hood -- that's true for both Grand Central Dispatch and operation queues.
Multiple threads can be executed at the same time on a single CPU core (or at least perceived as at the same time). The operating system assigns small slices of computing time to each thread, so that it seems to the user as if multiple tasks are executed at the same time. If multiple CPU cores are available, then multiple threads can be executed truly in parallel, therefore lessening the total time needed for a certain workload.
You can use the [CPU strategy view](http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/AnalysingCPUUsageinYourOSXApp/AnalysingCPUUsageinYourOSXApp.html) in Instruments to get some insight of how your code or the framework code you're using gets scheduled for execution on multiple CPU cores.
The important thing to keep in mind is that you have no control over where and when your code gets scheduled, and when and for how long its execution will be paused in order for other tasks to take their turn. This kind of thread scheduling is a very powerful technique. However, it also comes with great complexity, which we will investigate later on.
Leaving this complexity aside for a moment, you can either use the [POSIX thread](http://en.wikipedia.org/wiki/POSIX_Threads) API, or the Objective-C wrapper around this API, `NSThread`, to create your own threads. Here's a small sample that finds the minimum and maximum in a set of 1 million numbers using `pthread`. It spawns off 4 threads that run in parallel. It should be obvious from this example why you wouldn't want to use pthreads directly.
```objc
#import <pthread.h>
struct threadInfo {
uint32_t * inputValues;
size_t count;
};
struct threadResult {
uint32_t min;
uint32_t max;
};
void * findMinAndMax(void *arg)
{
struct threadInfo const * const info = (struct threadInfo *) arg;
uint32_t min = UINT32_MAX;
uint32_t max = 0;
for (size_t i = 0; i < info->count; ++i) {
uint32_t v = info->inputValues[i];
min = MIN(min, v);
max = MAX(max, v);
}
free(arg);
struct threadResult * const result = (struct threadResult *) malloc(sizeof(*result));
result->min = min;
result->max = max;
return result;
}
int main(int argc, const char * argv[])
{
size_t const count = 1000000;
uint32_t inputValues[count];
// Fill input values with random numbers:
for (size_t i = 0; i < count; ++i) {
inputValues[i] = arc4random();
}
// Spawn 4 threads to find the minimum and maximum:
size_t const threadCount = 4;
pthread_t tid[threadCount];
for (size_t i = 0; i < threadCount; ++i) {
struct threadInfo * const info = (struct threadInfo *) malloc(sizeof(*info));
size_t offset = (count / threadCount) * i;
info->inputValues = inputValues + offset;
info->count = MIN(count - offset, count / threadCount);
int err = pthread_create(tid + i, NULL, &findMinAndMax, info);
NSCAssert(err == 0, @"pthread_create() failed: %d", err);
}
// Wait for the threads to exit:
struct threadResult * results[threadCount];
for (size_t i = 0; i < threadCount; ++i) {
int err = pthread_join(tid[i], (void **) &(results[i]));
NSCAssert(err == 0, @"pthread_join() failed: %d", err);
}
// Find the min and max:
uint32_t min = UINT32_MAX;
uint32_t max = 0;
for (size_t i = 0; i < threadCount; ++i) {
min = MIN(min, results[i]->min);
max = MAX(max, results[i]->max);
free(results[i]);
results[i] = NULL;
}
NSLog(@"min = %u", min);
NSLog(@"max = %u", max);
return 0;
}
```
`NSThread` is a simple Objective-C wrapper around pthreads. This makes the code look more familiar in a Cocoa environment. For example, you can define a thread as a subclass of NSThread, which encapsulates the code you want to run in the background. For the previous example, we could define an `NSThread` subclass like this:
```objc
@interface FindMinMaxThread : NSThread
@property (nonatomic) NSUInteger min;
@property (nonatomic) NSUInteger max;
- (instancetype)initWithNumbers:(NSArray *)numbers;
@end
@implementation FindMinMaxThread {
NSArray *_numbers;
}
- (instancetype)initWithNumbers:(NSArray *)numbers
{
self = [super init];
if (self) {
_numbers = numbers;
}
return self;
}
- (void)main
{
NSUInteger min;
NSUInteger max;
// process the data
self.min = min;
self.max = max;
}
@end
```
To start new threads, we need to create new thread objects and call their `start` methods:
```objc
NSMutableSet *threads = [NSMutableSet set];
NSUInteger numberCount = self.numbers.count;
NSUInteger threadCount = 4;
for (NSUInteger i = 0; i < threadCount; i++) {
NSUInteger offset = (numberCount / threadCount) * i;
NSUInteger count = MIN(numberCount - offset, numberCount / threadCount);
NSRange range = NSMakeRange(offset, count);
NSArray *subset = [self.numbers subarrayWithRange:range];
FindMinMaxThread *thread = [[FindMinMaxThread alloc] initWithNumbers:subset];
[threads addObject:thread];
[thread start];
}
```
Now we could observe the threads' `isFinished` property to detect when all our newly spawned threads have finished before evaluating the result. We will leave this exercise to the interested reader though. The main point is that working directly with threads, using either the `pthread` or the `NSThread` APIs, is a relatively clunky experience and doesn't fit our mental model of coding very well.
One problem that can arise from directly using threads is that the number of active threads increases exponentially if both your code and underlying framework code spawn their own threads. This is actually a quite common problem in big projects. For example, if you create eight threads to take advantage of eight CPU cores, and the framework code you call into from these threads does the same (as it doesn't know about the threads you already created), you can quickly end up with dozens or even hundreds of threads. Each part of the code involved acted responsibly in itself; nevertheless, the end result is problematic. Threads don't come for free. Each thread ties up memory and kernel resources.
Next up, we'll discuss two queue-based concurrency APIs: Grand Central Dispatch and operation queues. They alleviate this problem by centrally managing a [thread pool](http://en.wikipedia.org/wiki/Thread_pool_pattern) that everybody uses collaboratively.
### Grand Central Dispatch
Grand Central Dispatch (GCD) was introduced in OS X 10.6 and iOS 4 in order to make it easier for developers to take advantage of the increasing numbers of CPU cores in consumer devices. We will go into more detail about GCD in our [article about low-level concurrency APIs][300].
With GCD you don't interact with threads directly anymore. Instead you add blocks of code to queues, and GCD manages a [thread pool](http://en.wikipedia.org/wiki/Thread_pool_pattern) behind the scenes. GCD decides on which particular thread your code blocks are going to be executed on, and it manages these threads according to the available system resources. This alleviates the problem of too many threads being created, because the threads are now centrally managed and abstracted away from application developers.
The other important change with GCD is that you as a developer think about work items in a queue rather than threads. This new mental model of concurrency is easier to work with.
GCD exposes five different queues: the main queue running on the main thread, three background queues with different priorities, and one background queue with an even lower priority, which is I/O throttled. Furthermore, you can create custom queues, which can either be serial or concurrent queues. While custom queues are a powerful abstraction, all blocks you schedule on them will ultimately trickle down to one of the system's global queues and its thread pool(s).

Making use of several queues with different priorities sounds pretty straightforward at first. However, we strongly recommend that you use the default priority queue in almost all cases. Scheduling tasks on queues with different priorities can quickly result in unexpected behavior if these tasks access shared resources. This can lead as far as causing your whole program to come to a grinding halt because some low-priority tasks are blocking a high-priority task from executing. You can read more about this phenomenon, called priority inversion, [below](#priority-inversion).
Although GCD is a low-level C API, it's pretty straightforward to use. This makes it easy to forget that all caveats and pitfalls of concurrent programming still apply while dispatching blocks onto GCD queues. Please make sure to read about the [challenges of concurrent programming](#challenges-of-concurrent-programming) below, in order to be aware of the potential problems. Furthermore, we have an excellent [walkthrough of the GCD API][300] in this issue that contains many in-depth explanations and valuable hints.
### Operation Queues
Operation queues are a Cocoa abstraction of the queue model exposed by GCD. While GCD offers more low-level control, operation queues implement several convenient features on top of it, which often makes it the best and safest choice for application developers.
The `NSOperationQueue` class has two different types of queues: the main queue and custom queues. The main queue runs on the main thread, and custom queues are processed in the background. In any case, the tasks which are processed by these queues are represented as subclasses of `NSOperation`.
You can define your own operations in two ways: either by overriding `main`, or by overriding `start`. The former is very simple to do, but gives you less flexibility. In return, the state properties like `isExecuting` and `isFinished` are managed for you, simply by assuming that the operation is finished when `main` returns.
```objc
@implementation YourOperation
- (void)main
{
// do your work here ...
}
@end
```
If you want more control and to maybe execute an asynchronous task within the operation, you can override `start`:
```objc
@implementation YourOperation
- (void)start
{
self.isExecuting = YES;
self.isFinished = NO;
// start your work, which calls finished once it's done ...
}
- (void)finished
{
self.isExecuting = NO;
self.isFinished = YES;
}
@end
```
Notice that in this case, you have to manage the operation's state manually. In order for an operation queue to be able to pick up a such a change, the state properties have to be implemented in a KVO-compliant way. So make sure to send proper KVO messages in case you don't set them via default accessor methods.
In order to benefit from the cancelation feature exposed by operation queues, you should regularly check the `isCancelled` property for longer-running operations:
```objc
- (void)main
{
while (notDone && !self.isCancelled) {
// do your processing
}
}
```
Once you have defined your operation class, it's very easy to add an operation to a queue:
```objc
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
YourOperation *operation = [[YourOperation alloc] init];
[queue addOperation:operation];
```
Alternatively, you can also add blocks to operation queues. This comes in handy, e.g. if you want to schedule one-off tasks on the main queue:
```objc
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// do something...
}];
```
While this is a very convenient way of scheduling work onto a queue, defining your own NSOperation subclasses can be very helpful during debugging. If you override the operation's `description` method, you can easily identify all the operations currently scheduled in a certain queue.
Beyond the basics of scheduling operations or blocks, operation queues offer some features which would be non-trivial to get right in GCD. For example, you can easily control how many operations of a certain queue may be executed concurrently with the `maxConcurrentOperationCount` property. Setting it to one gives you a serial queue, which is great for isolation purposes.
Another convenient feature is the sorting of operations within a queue according to their priorities. This is not the same as GCD's queue priorities. It solely influences the execution order of all operations scheduled in one queue. If you need more control over the sequence of execution beyond the five standard priorities, you can specify dependencies between operations like this:
```objc
[intermediateOperation addDependency:operation1];
[intermediateOperation addDependency:operation2];
[finishedOperation addDependency:intermediateOperation];
```
This simple code guarantees that `operation1` and `operation2` will be executed before `intermediateOperation`, which, in turn, will be executed before `finishedOperation`. Operation dependencies are a very powerful mechanism to specify a well-defined execution order. This lets you create things like operation groups, which are guaranteed to be executed before the dependent operation, or serial operations within an otherwise concurrent queue.
By the very nature of abstractions, operation queues come with a small performance hit compared to using the GCD API. However, in almost all cases, this impact is negligible and operation queues are the tool of choice.
### Run Loops
Run loops are not technically a concurrency mechanism like GCD or operation queues, because they don't enable the parallel execution of tasks. However, run loops tie in directly with the execution of tasks on the main dispatch/operation queue and they provide a mechanism to execute code asynchronously.
Run loops can be a lot easier to use than operation queues or GCD, because you don't have to deal with the complexity of concurrency and still get to do things asynchronously.
A run loop is always bound to one particular thread. The main run loop associated with the main thread has a central role in each Cocoa and CocoaTouch application, because it handles UI events, timers, and other kernel events. Whenever you schedule a timer, use a `NSURLConnection`. or call `performSelector:withObject:afterDelay:`, the run loop is used behind the scenes in order to perform these asynchronous tasks.
Whenever you use a method which relies on the run loop, it is important to remember that run loops can be run in different modes. Each mode defines a set of events the run loop is going to react to. This is a clever way to temporarily prioritize certain tasks over others in the main run loop.
A typical example of this is scrolling on iOS. While you're scrolling, the run loop is not running in its default mode, and therefore, it's not going to react to, for example, a timer you have scheduled before. Once scrolling stops, the run loop returns to the default mode and the events which have been queued up are executed. If you want a timer to fire during scrolling, you need to add it to the run loop in the `NSRunLoopCommonModes` mode.
The main thread always has the main run loop set up and running. Other threads though don't have a run loop configured by default. You can set up a run loop for other threads too, but you will rarely need to do this. Most of the time it is much easier to use the main run loop. If you need to do heavier work that you don't want to execute on the main thread, you can still dispatch it onto another queue after your code is called from the main run loop. Chris has some good examples of this pattern in his article about [common background practices][200].
If you really need to set up a run loop on another thread, don't forget to add at least one input source to it. If a run loop has no input sources configured, every attempt to run it will exit immediately.
## Challenges of Concurrent Programming
Writing concurrent programs comes with many pitfalls. As soon as you're doing more than the most basic things, it becomes difficult to oversee all the different states in the interplay of multiple tasks being executed in parallel. Problems can occur in a non-deterministic way, which makes it even more difficult to debug concurrent code.
There is a prominent example for unforeseen behavior of concurrent programs: In 1995, NASA sent the Pathfinder mission to Mars. Not too long after a successful landing on our red neighboring planet, the mission almost [came to an abrupt end](http://research.microsoft.com/en-us/um/people/mbj/Mars_Pathfinder/Mars_Pathfinder.html). The Mars rover kept rebooting for unknown reasons -- it suffered from a phenomenon called *priority inversion*, where a low-priority thread kept blocking a high-priority one. We are going to explore this particular issue in more detail below. But this example should demonstrate that even with vast resources and lots of engineering talent available, concurrency can come back to bite you in many ways.
### Sharing of Resources
The root of many concurrency related evils is the access of shared resources from multiple threads. A resource can be a property or an object, memory in general, a network device, a file, etc. Anything you share between multiple threads is a potential point of conflict, and you have to take safety measures to prevent these kind of conflicts.
In order to demonstrate the problem, let's look at a simple example of a resource in the form of an integer property which you're using as a counter. Let's say we have two threads running in parallel, A and B, and both try to increment the counter at the same time. The problem is that what you write as one statement in C or Objective-C is mostly not just one machine instruction for the CPU. To increment our counter, the current value has to be read from memory. Then the value is incremented by one and finally written back to memory.
Imagine the hazards that can happen if both threads try to do this simultaneously. For example, thread A and thread B both read the value of the counter from memory; let's say it is `17`. Then thread A increments the counter by one and writes the resulting `18` back to memory. At the same time, thread B also increments the counter by one and writes a `18` back to memory, just after thread A. At this point the data has become corrupted, because the counter holds an `18` after it was incremented twice from a `17`.

This problem is called a [race condition](http://en.wikipedia.org/wiki/Race_conditions#Software) and can always happen if multiple threads access a shared resource without making sure that one thread is finished operating on a resource before another one begins accessing it. If you're not only writing a simple integer but a more complex structure to memory, it might even happen that a second thread tries to read from this memory while you're in the midst of writing it, therefore seeing half new and half old or uninitialized data. In order to prevent this, multiple threads need to access shared resources in a mutually exclusive way.
In reality, the situation is even more complicated than this, because modern CPUs change the sequence of reads and writes to memory for optimization purposes ([Out-of-order execution](http://en.wikipedia.org/wiki/Out-of-order_execution)).
### Mutual Exclusion
[Mutual exclusive](http://en.wikipedia.org/wiki/Mutex) access means that only one thread at a time gets access to a certain resource. In order to ensure this, each thread that wants to access a resource first needs to acquire a [*mutex* lock](http://en.wikipedia.org/wiki/Lock_%28computer_science%29) on it. Once it has finished its operation, it releases the lock, so that other threads get a chance to access it.

In addition to ensuring mutual exclusive access, locks must also handle the problem caused by out-of-order execution. If you cannot rely on the CPU accessing the memory in the sequence defined by your program instructions, guaranteeing mutually exclusive access alone is not enough. To work around this side effect of CPU optimization strategies, [memory barriers](http://en.wikipedia.org/wiki/Memory_barrier) are used. Setting a memory barrier makes sure that no out-of-order execution takes place across the barrier.
Of course the implementation of a mutex lock in itself needs to be race-condition free. This is a non-trivial undertaking and requires use of special instructions on modern CPUs. You can read more about atomic operations in Daniel's [low-level concurrency techniques][300] article.
Objective-C properties come with language level support for locking in the form of declaring them as atomic. In fact, properties are even atomic by default. Declaring a property as atomic results in implicit locking/unlocking around each access of this property. It might be tempting to just declare all properties as atomic, just in case. However, locking comes at a cost.
Acquiring a lock on a resource always comes with a performance cost. Acquiring and releasing a lock needs to be race-condition free, which is non-trivial on multi-core systems. And when acquiring a lock, the thread might have to wait because some other thread already holds the lock. In this case, that thread will sleep and has to be notified when the other thread relinquishes the lock. All of these operations are expensive and complicated.
There are different kinds of locks. Some locks are very cheap when there's no lock contention but perform poorly under contention. Other locks are more expensive at a base level, but degrade better under contention ([Lock contention](http://en.wikipedia.org/wiki/Lock_%28computer_science%29#Granularity) is the situation when one or more threads try to take a lock that has already been taken).
There is a trade-off to be made here: acquiring and releasing locks comes at a price (lock overhead). Therefore you want to make sure you're not constantly entering and exiting [critical sections](http://en.wikipedia.org/wiki/Critical_section) (i.e. acquiring and releasing locks). At the same time, if you acquire a lock for too large of a region of code, you run the risk of lock contention where other threads are often unable to do work because they're waiting to acquire a lock. It's not an easy task to solve.
It is quite common to see code which is supposed to run concurrently, but which actually results in only one thread being active at a time, because of the way locks for shared resources are set up. It's often non-trivial to predict how your code will get scheduled on multiple cores. You can use Instrument's [CPU strategy view](http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/AnalysingCPUUsageinYourOSXApp/AnalysingCPUUsageinYourOSXApp.html) to get a better idea of whether you're efficiently using the available CPU cores or not.
### Dead Locks
Mutex locks solve the problem of race conditions, but unfortunately they also introduce a new problem ([amongst others](http://en.wikipedia.org/wiki/Lock_%28computer_science%29#The_problems_with_locks)) at the same time: [dead locks](http://en.wikipedia.org/wiki/Deadlock). A dead lock occurs when multiple threads are waiting on each other to finish and get stuck.

Consider the following example code, which swaps the values of two variables:
```objc
void swap(A, B)
{
lock(lockA);
lock(lockB);
int a = A;
int b = B;
A = b;
B = a;
unlock(lockB);
unlock(lockA);
}
```
This works quite well most of the time. But when by chance two threads call it at the same time with opposite variables
```objc
swap(X, Y); // thread 1
swap(Y, X); // thread 2
```
we can end up in a dead lock. Thread 1 acquires a lock on X, thread 2 acquires a lock on Y. Now they're both waiting for the other lock, but will never be able to acquire it.
Again, the more resources you share between threads and the more locks you take, the greater your risk of running into a dead lock situation. This is one more reason to keep things as simple as possible and to share as few resources as possible between threads. Make sure to also read the section about [doing things asynchronously][301] in the [low-level concurrency APIs][300] article.
### Starvation
Just when you thought that there are enough problems to think of, a new one comes around the corner. Locking shared resources can result in the [readers-writers problem](http://en.wikipedia.org/wiki/Readers-writers_problem). In many cases, it would be wasteful to restrict reading access to a resource to one access at a time. Therefore, taking a reading lock is allowed as long as there is no writing lock on the resource. In this situation, a thread that is waiting to acquire a write lock can be starved by more read locks occurring in the meantime.
In order to solve this issue, more clever solutions than a simple read/write lock are necessary, e.g. giving [writers preference](http://en.wikipedia.org/wiki/Readers–writer_lock) or using the [read-copy-update](http://en.wikipedia.org/wiki/Read-copy-update) algorithm. Daniel shows in his [low-level concurrency techniques][302] article how to implement a multiple reader/single writer pattern with GCD which doesn't suffer from writer starvation.
### Priority Inversion
We started this section with the example of NASA's Pathfinder rover on Mars suffering from a concurrency problem. Now we will have a closer look why Pathfinder almost failed, and why your application can suffer from the same problem, called [priority inversion](http://en.wikipedia.org/wiki/Priority_inversion).
Priority inversion describes a condition where a lower priority task blocks a higher priority task from executing, effectively inverting task priorities. Since GCD exposes background queues with different priorities, including one which even is I/O throttled, it's good to know about this possibility.
The problem can occur when you have a high-priority and a low-priority task share a common resource. When the low-priority task takes a lock to the common resource, it is supposed to finish off quickly in order to release its lock and to let the high-priority task execute without significant delays. Since the high-priority task is blocked from running as long as the low-priority task has the lock, there is a window of opportunity for medium-priority tasks to run and to preempt the low-priority task, because the medium-priority tasks have now the highest priority of all currently runnable tasks. At this moment, the medium-priority tasks hinder the low-priority task from releasing its lock, therefore effectively gaining priority over the still waiting, high-priority tasks.

In your own code, things might not be as dramatic as the rebooting that occurred in the Mars rover, as priority inversion happens quite often in a less severe manner.
In general, don't use different priorities. Often you will end up with high-priority code waiting on low-priority code to finish. When you're using GCD, always use the default priority queue (directly, or as a target queue). If you're using different priorities, more likely than not, it's actually going to make things worse.
The lesson from this is that using multiple queues with different priorities sounds good on paper, but it adds even more complexity and unpredictability to concurrent programs. And if you ever run into a weird problem where your high-priority tasks seem to get stuck for no reason, maybe you will remember this article and the problem called priority inversion, which even the NASA engineers encountered.
## Conclusion
We hope to have demonstrated the complexity of concurrent programming and its problems, no matter how straightforward an API may look. The resulting behavior quickly gets very difficult to oversee, and debugging these kind of problems is often very hard.
On the other hand, concurrency is a powerful tool to take advantage of the computing power of modern multicore CPUs. The key is to keep your concurrency model as simple as possible, so that you can limit the amount of locking necessary.
A safe pattern we recommend is this: pull out the data you want to work on the main thread, then use an operation queue to do the actual work in the background, and finally get back onto the main queue to deliver the result of your background work. This way, you don't need to do any locking yourself, which greatly reduces the chances for mistakes.
[90]: /issues/2-concurrency/editorial/
[100]: /issues/2-concurrency/concurrency-apis-and-pitfalls/
[101]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#challenges-of-concurrent-programming
[102]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#priority-inversion
[103]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#sharing-of-resources
[104]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#dead_locks
[200]: /issues/2-concurrency/common-background-practices/
[300]: /issues/2-concurrency/low-level-concurrency-apis/
[301]: /issues/2-concurrency/low-level-concurrency-apis/#async
[302]: /issues/2-concurrency/low-level-concurrency-apis/#multiple-readers-single-writer
[400]: /issues/2-concurrency/thread-safe-class-design/
================================================
FILE: 2013-07-07-editorial.markdown
================================================
---
title: "Editorial"
category: "2"
date: "2013-07-07 11:00:00"
tags: editorial
---
Welcome to objc.io issue #2!
First of all, we would like to thank everyone for the overwhelming response to our first issue -- we couldn't have hoped for a better start.
In this second issue we are going to dive deep into the subject of concurrent programming. These days, we have multiple CPU cores at our disposal, even on mobile devices. If we get concurrency right, it can give our applications a big performance boost.
Unfortunately, concurrent programming inherently has many intricate problems and pitfalls, no matter how simple the API makes it seem. We hope that the articles in this issue will give you a deeper understanding of the subject and help you navigate around the many potential pitfalls.
For this issue we are very glad to have [Peter Steinberger](https://twitter.com/steipete) and [Tobias Kräntzer](http://twitter.com/anagrom_ataf) as guest authors. Peter shares his experiences with regard to concurrent programming from his well known [PSPDFKit](http://pspdfkit.com/) library, and Tobias writes about testing asynchronous code.
If you have a topic in mind that you would like to contribute to objc.io in the future, please [get it in touch](mailto:mail@objc.io) with us.
Lastly, we have good news for all of you who asked for an RSS feed: you can now subscribe to objc.io at [objc.io/feed.xml](/feed.xml).
Happy reading!
Chris, Daniel, and Florian.
================================================
FILE: 2013-07-07-low-level-concurrency-apis.md
================================================
---
title: "Low-Level Concurrency APIs"
category: "2"
date: "2013-07-07 8:00:00"
author:
- name: Daniel Eggert
url: https://twitter.com/danielboedewadt
tags: article
---
In this article we'll talk about some low-level APIs available on both iOS and OS X. Except for `dispatch_once`, we generally discourage using any of this.
But we wanted to show what's available under the covers. These low-level APIs provide a huge amount of flexibility, yet with that flexibility comes a lot of complexity and responsibility. The higher-level APIs and patterns that we mention in our [article about common background practices](/issues/2-concurrency/common-background-practices/) let you focus on your task at hand and save you a lot of trouble. And generally, the higher-level APIs will provide better performance unless you can afford the time and effort to tweak and debug code that uses lower-level APIs.
Knowing how things work further down the software stack is good, though. We hope this article will give you a better understanding of the platform, and at the same time, will make you appreciate the higher-level APIs more.
First, we'll go through most of the bits and pieces that make up *Grand Central Dispatch*. It's been around for some years and Apple keeps adding to it and improving it. Apple has open sourced it, which means it's available for other platforms, too. Finally, we'll take a look at [atomic operations](#atomic_operations) -- another set of low-level building blocks.
Probably the best book ever written about concurrent programming is *M. Ben-Ari*: "Principles of Concurrent Programming", [ISBN 0-13-701078-8](https://en.wikipedia.org/wiki/Special:BookSources/0-13-701078-8). If you're doing anything with concurrent programming, you need to read this. It's more than 30 years old, and is still unsurpassed. Its concise writing, excellent examples, and exercises take you through the fundamental building blocks of concurrent programming. It's out of print, but there are still some copies floating around. There's a new version called "Principles of Concurrent and Distributed Programming", [ISBN 0-321-31283-X](https://en.wikipedia.org/wiki/Special:BookSources/0-321-31283-X) that seems to cover much of the same, but I haven't read it myself.
## Once Upon a Time…
Probably the most widely used and misused feature in GCD is `dispatch_once`. Correctly used, it will look like this:
```objc
+ (UIColor *)boringColor;
{
static UIColor *color;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
color = [UIColor colorWithRed:0.380f green:0.376f blue:0.376f alpha:1.000f];
});
return color;
}
```
The block will only get run once. And during successive calls, the check is very performant. You can use this to initialize global data such as singletons. Beware that using `dispatch_once_t` makes testing very difficult -- singletons and testing don't go well together.
Make sure that the `onceToken` is declared `static` or has global scope. Anything else causes undefined behavior. In other words: Do **not** put a `dispatch_once_t` as a member variable into an object or the like.
Back in ancient times (i.e. a few years ago), people would use `pthread_once`, which you should never use again, as `dispatch_once` is easier to use and less error-prone.
## Delaying / After
Another common companion is `dispatch_after`. It lets you do work *a little bit later*. It's powerful, but beware: You can easily get into a lot of trouble. Common usage looks like this:
```objc
- (void)foo
{
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self bar];
});
}
```
This looks awesome at first sight. There are a few drawbacks, though. We can't (directly) cancel the block we're submitting to `dispatch_after`. It will run.
Another thing to note is there's a problematic tendency where people use `dispatch_after` to work around timing bugs they have in their code. Some code gets run too early and you may not know why, so you put it inside a `dispatch_after`. Now everything works. But some weeks later it stops working and since you have no clear indication of in which order your code runs, debugging turns into a nightmare. Don't do this. Most of the time, you're better of putting your code into the right place. If inside `-viewWillAppear` is too early, perhaps `-viewDidAppear` is the right place.
You'll save yourself a lot of trouble by creating direct calls (analogous to `-viewDidAppear`) in your own code instead of relying on `dispatch_after`.
If you need something to run at a specific point in time, `dispatch_after` may be the right thing, though. Be sure to check out `NSTimer`, too. That API is a tiny bit more cumbersome, but it allows you to cancel the firing of the timer.
## Queues
One of the basic building blocks of GCD is queues. Below, we'll give a few examples on how you can put them to use. When using queues, you'll do yourself a favor when giving them a good label. While debugging, this label is displayed within Xcode (and lldb), and will help you understand what your app is up to:
```objc
- (id)init;
{
self = [super init];
if (self != nil) {
NSString *label = [NSString stringWithFormat:@"%@.isolation.%p", [self class], self];
self.isolationQueue = dispatch_queue_create([label UTF8String], NULL);
label = [NSString stringWithFormat:@"%@.work.%p", [self class], self];
self.workQueue = dispatch_queue_create([label UTF8String], NULL);
}
return self;
}
```
Queues can be either *concurrent* or *serial*. By default, they're serial, which means that only a single block runs at any given time. That's how isolation queues work, which we'll get to in a bit. Queues can also be concurrent, which allows multiple blocks to run at the same time.
GCD queues use threads internally. GCD manages these threads, and thus when using GCD you don't need to create threads yourself. But the important takeaway is that GCD presents to you, the user of the API, a very different abstraction level. When you use GCD to do concurrent work, you don't think in terms of threads, but instead in terms of queues and work items (blocks submitted to queues). While down below, there're still threads, GCD's abstraction level lends itself way better to how you're usually writing code.
The queues and work items also solve a common problem of consecutive fanning out: If we're using threads directly, and want to do something concurrently, we may split our work up into 100 smaller work items, and then create threads according to the number of available CPU cores, let's say eight. We send the work items to those eight threads. As we process those items, we might call some function as part of our work. The person who wrote that function also wanted to use concurrency, and hence also creates eight threads when you call the function. Now you have 8 x 8 = 64 threads, even though you only have eight cores -- i.e. only 12% of the threads can actually run at any point in time while the other 88% are not doing anything. With GCD you don't have this problem, and GCD can even adjust the number of threads when the system turns off cores to save power.
GCD creates a so-called [thread pool](http://en.wikipedia.org/wiki/Thread_pool_pattern) that roughly matches the number of cores. Remember that threads don't come for free. Each thread ties up memory and kernel resources. There's one problem though: If you're submitting a block to GCD, and that code blocks the thread, this thread is no longer available at that point in time to do other work -- it's blocked. In order to keep processing work items (blocks) on the queues, GCD has to create a new thread and add it to the pool.
If your code is blocking many threads, that can become quite problematic. First off, threads consume resources, but moreover, it's expensive to create them. And it takes some time. And during that time, GCD can't process work items at full speed. There are quite a few things that can cause a thread to block, but the most common are I/O related, i.e. reading and writing from / to a file or the network. You should not do that on a GCD queue in a blocking manner for this very reason. Take a look at the [Input / Output section](#input_output) below for information about how to do I/O in a way that plays nicely with GCD.
### Target Queue
You can set a **target queue** for any queue that you create. This can be very powerful. And it helps debugging.
It is generally considered good style for a class to create its own queue instead of using a global queue. This way you can set the name of that queue, which eases debugging a lot -- Xcode lets you see the names of all queues in the Debug Navigator, or if you're using `lldb` directly, `(lldb) thread list` will print out the queue names. Once you're using a lot of async stuff, this is very valuable help.
Using a private queue also enforces encapsulation. It's your queue; you get to decide how to use it.
By default, a newly created queue forwards into the default priority global queue. We'll talk more about priorities in a bit.
You can change which queue your queue forwards into -- you can set your queue's target queue. This way you can chain multiple queues together. Your class `Foo` has a queue which forwards into the queue of class `Bar` which forwards into a global queue.
This can be very useful when you use a queue for isolation (which we'll also talk about). `Foo` has an isolation queue, and by forwarding into `Bar`'s isolation queue, it will automatically be thread-safe with respect to the resources that `Bar`'s isolation queue protects.
Make sure to make your private queue concurrent if you want multiple blocks to run on it. And note that if a queue's target queue is serial (i.e. non-concurrent), it effectively turns into a serial queue as well.
### Priorities
You change the priority of your own queue by setting its target queue to be one of the global queues. But you should refrain from the temptation to do so.
In most cases, changing the priority is not going to do what you intend. What may seem straightforward is actually a very complex problem. You'll very easily run into what is known as [Priority Inversion](http://en.wikipedia.org/wiki/Priority_inversion). Our [article about concurrency APIs and pitfalls](/issues/2-concurrency/concurrency-apis-and-pitfalls/#challenges) has more info on this problem which almost bricked NASA's Pathfinder rover on Mars.
Furthermore, you need to be particularly careful with the `DISPATCH_QUEUE_PRIORITY_BACKGROUND` queue. Don't use it unless you understand what *throttled I/O* and *background status as per setpriority(2)* mean. Otherwise the system might end up putting your app to a grinding halt. It is mostly intended for doing I/O in a way such that it doesn't interfere with other parts of the system doing I/O. But combined with priority inversion, it can easily become a dangerous cocktail.
## Isolation
Isolation queues are one of the most common patterns in GCD queue usage. There are two variations.
### Protecting a Resource
The most common scenario in multi-threaded programming is that you have a resource that only one thread is allowed to access at a time.
Our [article about concurrency techniques](/issues/2-concurrency/concurrency-apis-and-pitfalls/) talks a bit more about what *resource* means in concurrent programming. It's often a piece of memory or an object that only one thread must access at a time.
Let's say we need to access a `NSMutableDictionary` from multiple threads (queues). We would do something like this:
```objc
- (void)setCount:(NSUInteger)count forKey:(NSString *)key
{
key = [key copy];
dispatch_async(self.isolationQueue, ^(){
if (count == 0) {
[self.counts removeObjectForKey:key];
} else {
self.counts[key] = @(count);
}
});
}
- (NSUInteger)countForKey:(NSString *)key;
{
__block NSUInteger count;
dispatch_sync(self.isolationQueue, ^(){
NSNumber *n = self.counts[key];
count = [n unsignedIntegerValue];
});
return count;
}
```
With this, only one thread will access the `NSMutableDictionary` instance.
Note four things:
1. Don't use this code. First read about [multiple readers, single writer](#multiple-readers-single-writer) and also about [contention](#contention).
2. We're using `async` when storing a value. This is important. We don't want to and don't need to block the current thread for the *write* to complete. When reading, we're using `sync` since we need to return the result.
3. According to the method interface, `-setCount:forKey:` takes an `NSString`, which we're passing onto `dispatch_async`. The caller is free to pass in an `NSMutableString` and can modify it after the method returns, but before the block executes. Hence we *have* to copy the string to guarantee that the method works correctly. If the passed-in string isn't mutable (i.e. a normal `NSString`) the call to `-copy` is basically a no-op.
4. The `isolationQueue` needs to have been created with a `dispatch_queue_attr_t` of `DISPATCH_QUEUE_SERIAL` (or `0`).
<a name="multiple-readers-single-writer" id="multiple-readers-single-writer"> </a>
### One Resource, Multiple Readers, and a Single Writer
We can improve upon the above example. GCD has concurrent queues on which multiple threads can run. We can safely read from the `NSMutableDictionary` on multiple threads as long as we don't mutate it at the same time. When we need to change the dictionary, we dispatch the block with a *barrier*. Such a block runs once all previously scheduled blocks have completed and before any following blocks are run.
We'll create the queue with:
```objc
self.isolationQueue = dispatch_queue_create([label UTF8String], DISPATCH_QUEUE_CONCURRENT);
```
and then change the setter like this:
```objc
- (void)setCount:(NSUInteger)count forKey:(NSString *)key
{
key = [key copy];
dispatch_barrier_async(self.isolationQueue, ^(){
if (count == 0) {
[self.counts removeObjectForKey:key];
} else {
self.counts[key] = @(count);
}
});
}
```
When you use concurrent queues, make sure that all *barrier* calls are *async*. If you're using `dispatch_barrier_sync` you'll quite likely get yourself (or rather: your code) into a deadlock. Writes *need* a barrier, and *can* be async.
<a name="contention" id="contention"> </a>
### A Word on Contention
First off, a word of warning here: The resource we're protecting in this simple example is an `NSMutableDictionary`. This serves the purpose of an example very well. But in real code, it is important to put the isolation at the right complexity level.
If you're accessing the `NSMutableDictionary` very frequently, you'll be running into what's known as lock contention. Lock contention is in no way specific to GCD or queues. Any form of locking mechanism will have the same problem -- different locking mechanisms in different ways.
All calls to `dispatch_async`, `dispatch_sync`, etc. need to perform some form of locking -- making sure that only one thread or specific threads run a given block. GCD can avoid locks to some extent and use scheduling instead, but at the end of the day the problem just shifts. The underlying problem remains: if you have a **lot** of threads hitting the same lock or queue at the same time, you'll see performance hits. Performance can degrade severely.
You need to isolate at the right complexity level. When you see performance degrade, it's a clear sign of a design problem in your code. There are two costs that you need to balance. First is the cost of being inside a critical section for so long that other threads are blocked from entering a critical section, and second is the cost of constantly entering and leaving critical sections. In the world of GCD, the first cost is describing the fact that if a block runs on your isolation queue, it may potentially block other code from running on your isolation queue. The second cost describes the fact that calling `dispatch_async` and `dispatch_sync`, while highly optimized, don't come for free.
Sadly, there can be no general rule of what the right balance is: You need to measure and adjust. Spin up Instruments and see what your app is up to.
If we look at the example code above, our critical code section is only doing very simple things. That may or may not be good, depending on how it's used.
In your own code, consider if you're better off by protecting with an isolation queue on a higher level. For example, instead of the class `Foo` having an isolation queue and it itself protecting access to its `NSMutableDictionary`, you could have the class `Bar` that uses `Foo` have an isolation queue which protects all use of the class `Foo`. In other words: you would change `Foo` so that it is no longer thread-safe, (no isolation queue) and then inside `Bar`, use an isolation queue to make sure that only one thread is using `Foo` at any point in time.
<a name="async" id="async"> </a>
### Going Fully Asynchronous
Let's sidetrack a bit here. As you've seen above, you can dispatch a block, a work unit, both synchronously and asynchronously. A very common problem that we talk about in our [article about concurrency APIs and pitfalls](/issues/2-concurrency/concurrency-apis-and-pitfalls/) is [dead locks](http://en.wikipedia.org/wiki/Deadlock). It's quite easy to run into the problem with GCD with synchronous dispatching. The trivial case is:
```objc
dispatch_queue_t queueA; // assume we have this
dispatch_sync(queueA, ^(){
dispatch_sync(queueA, ^(){
foo();
});
});
```
Once we hit the second `dispatch_sync` we'll deadlock: We can't dispatch onto queueA, because someone (the current thread) is already on that queue and is never going to leave it. But there are more subtle ways:
```objc
dispatch_queue_t queueA; // assume we have this
dispatch_queue_t queueB; // assume we have this
dispatch_sync(queueA, ^(){
foo();
});
void foo(void)
{
dispatch_sync(queueB, ^(){
bar();
});
}
void bar(void)
{
dispatch_sync(queueA, ^(){
baz();
});
}
```
Each call to `dispatch_sync()` on its own looks good, but in combination, they'll deadlock.
This is all inherent to being synchronous. If we use asynchronous dispatching such as
```objc
dispatch_queue_t queueA; // assume we have this
dispatch_async(queueA, ^(){
dispatch_async(queueA, ^(){
foo();
});
});
```
things will work just fine. *Asynchronous calls will not deadlock*. It is therefore very desirable to use asynchronous calls whenever possible. Instead of writing a function or method that returns a value (and hence has to be synchronous), we use a method that calls a result block asynchronously. That way we're less likely to run into problems with deadlocks.
The downside of asynchronous calls is that they're difficult to debug. When we stop the code in the debugger, there's no meaningful backtrace to look at.
Keep both of these in mind. Deadlocks are generally the tougher problem to deal with.
### How to Write a Good Async API
If you're designing an API for others to use (or even for yourself), there are a few good practices to keep in mind.
As we just mentioned, you should prefer asynchronous API. When you create an API, you can get called in ways that are outside your control, and if your code could deadlock, it will.
You should write your functions or methods so that the function calls `dispatch_async()`. Don't make the caller call it. The caller should be able to call into your function or method.
If your function or method has a result, deliver it asynchronously through a callback handler. The API should be such that your function or method takes both a result block and a queue to deliver the result on. The caller of your function should not have to dispatch onto the queue themself. The reason for this is quite simple: Almost all the time, the caller needs to be on a certain queue, and this way the code is easier to read. And your function will (should) call `dispatch_async()` anyhow to run the callback handler, so it might as well do that on the queue that the caller needs it to be on.
If you're writing a class, it is probably a good option to let the user of the class set a queue that all callbacks will be delivered on. Your code would look like this:
```objc
- (void)processImage:(UIImage *)image completionHandler:(void(^)(BOOL success))handler;
{
dispatch_async(self.isolationQueue, ^(void){
// do actual processing here
dispatch_async(self.resultQueue, ^(void){
handler(YES);
});
});
}
```
If you write your classes this way, it's easy to make classes work together. If class A uses class B, it will set the callback queue of B to be its own isolation queue.
## Iterative Execution
If you're doing some number crunching and the problem at hand can be dissected in smaller parts of identical nature, `dispatch_apply` can be very useful.
If you have some code like this
```objc
for (size_t y = 0; y < height; ++y) {
for (size_t x = 0; x < width; ++x) {
// Do something with x and y here
}
}
```
you may be able to speed it up by simply changing it to
```objc
dispatch_apply(height, dispatch_get_global_queue(0, 0), ^(size_t y) {
for (size_t x = 0; x < width; x += 2) {
// Do something with x and y here
}
});
```
How well this works depends a lot on exactly what you're doing inside that loop.
The work done by the block must be non trivial, otherwise the overhead is too big. Unless the code is bound by computational bandwidth, it is critical that the memory that each work unit needs to read from and write to fits nicely into the cache size. This can have dramatic effects on performance. Code bound by critical sections may not perform well at all. Going into detail about these problems is outside the scope of this article. Using `dispatch_apply` may help performance, yet performance optimization is a complex topic on its own. Wikipedia has an article about [Memory-bound function](https://en.wikipedia.org/wiki/Memory_bound). Memory access speed changes dramatically between L2, L3, and main memory. Seeing a performance drop of 10x is not uncommon when your data access pattern doesn’t fit within the cache size.
## Groups
Quite often, you'll find yourself chaining asynchronous blocks together to perform a given task. Some of these may even run in parallel. Now, if you want to run some code once this task is complete, i.e. all blocks have completed, "groups" are the right tool. Here's a sample:
```objc
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^(){
// Do something that takes a while
[self doSomeFoo];
dispatch_group_async(group, dispatch_get_main_queue(), ^(){
self.foo = 42;
});
});
dispatch_group_async(group, queue, ^(){
// Do something else that takes a while
[self doSomeBar];
dispatch_group_async(group, dispatch_get_main_queue(), ^(){
self.bar = 1;
});
});
// This block will run once everything above is done:
dispatch_group_notify(group, dispatch_get_main_queue(), ^(){
NSLog(@"foo: %d", self.foo);
NSLog(@"bar: %d", self.bar);
});
```
The important thing to note is that all of this is entirely non-blocking. At no point are we telling the current thread to wait until something else is done. Quite contrary, we're simply enqueuing multiple blocks. Since this code pattern doesn't block, it's not going to cause a deadlock.
Also note how we're switching between different queues in this small and simple example.
### Using dispatch\_group\_t with Existing API
Once you've added groups to your tool belt, you'll be wondering why most async API doesn't take a `dispatch_group_t` as an optional argument. But there's no reason to despair: It's easy to add that yourself, although you have to be more careful to make sure your code is *balanced*.
We can, for example, add it to Core Data's `-performBlock:` API like this:
```objc
- (void)withGroup:(dispatch_group_t)group performBlock:(dispatch_block_t)block
{
if (group == NULL) {
[self performBlock:block];
} else {
dispatch_group_enter(group);
[self performBlock:^(){
block();
dispatch_group_leave(group);
}];
}
}
```
This allows us to use `dispatch_group_notify` to run a block when a set of operations on Core Data (possibly combined with other blocks) completes.
We can obviously do the same for `NSURLConnection`:
```objc
+ (void)withGroup:(dispatch_group_t)group
sendAsynchronousRequest:(NSURLRequest *)request
queue:(NSOperationQueue *)queue
completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
{
if (group == NULL) {
[self sendAsynchronousRequest:request
queue:queue
completionHandler:handler];
} else {
dispatch_group_enter(group);
[self sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
handler(response, data, error);
dispatch_group_leave(group);
}];
}
}
```
In order for this to work, you need to make sure that
* `dispatch_group_enter()` is guaranteed to run before `dispatch_group_leave()`
* Calls to `dispatch_group_enter()` and `dispatch_group_leave()` are always balanced (even when errors happen)
## Sources
One of the lesser-known features of GCD is the event sources `dispatch_source_t`.
Just like most of GCD, this is pretty low-level stuff. When you need it, it can be extremely useful, though. Some of it is extremely esoteric, and we'll just touch upon a few of the uses. A lot of this isn't very useful on iOS where you can't launch processes (hence no point in watching them) and you can't write outside your app bundle (hence no need to watch files), etc.
GCD sources are implemented in an extremely resource-efficient way.
### Watching Processes
If some process is running and you want to know when it exits, GCD has you covered. You can also use it to check when that process forks, i.e. spawns child processes or a signal was delivered to the process (e.g. `SIGTERM`).
```objc
@import AppKit;
// ...
NSArray *array = [NSRunningApplication
runningApplicationsWithBundleIdentifier:@"com.apple.mail"];
if (array == nil || [array count] == 0) {
return;
}
pid_t const pid = [[array firstObject] processIdentifier];
self.source = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid,
DISPATCH_PROC_EXIT, DISPATCH_TARGET_QUEUE_DEFAULT);
dispatch_source_set_event_handler(self.source, ^(){
NSLog(@"Mail quit.");
// If you would like continue watching for the app to quit,
// you should cancel this source with dispatch_source_cancel and create new one
// as with next run app will have another process identifier.
});
dispatch_resume(self.source);
```
This will print **Mail quit.** when the Mail.app exits.
Note that you must call `dispatch_resume()` before any events will be delivered to your event handler.
<a name="watching_files" id="watching_files"> </a>
### Watching Files
The possibilities seem near endless. You can watch a file directly for changes, and the source's event handler will get called when a change happens.
You can also use this to watch a directory, i.e. create a *watch folder*:
```objc
NSURL *directoryURL; // assume this is set to a directory
int const fd = open([[directoryURL path] fileSystemRepresentation], O_EVTONLY);
if (fd < 0) {
char buffer[80];
strerror_r(errno, buffer, sizeof(buffer));
NSLog(@"Unable to open \"%@\": %s (%d)", [directoryURL path], buffer, errno);
return;
}
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd,
DISPATCH_VNODE_WRITE | DISPATCH_VNODE_DELETE, DISPATCH_TARGET_QUEUE_DEFAULT);
dispatch_source_set_event_handler(source, ^(){
unsigned long const data = dispatch_source_get_data(source);
if (data & DISPATCH_VNODE_WRITE) {
NSLog(@"The directory changed.");
}
if (data & DISPATCH_VNODE_DELETE) {
NSLog(@"The directory has been deleted.");
}
});
dispatch_source_set_cancel_handler(source, ^(){
close(fd);
});
self.source = source;
dispatch_resume(self.source);
```
You should probably always add `DISPATCH_VNODE_DELETE` to check if the file or directory has been deleted -- and then stop monitoring it.
### Timers
In most cases, `NSTimer` is your go-to place for timer events. GCD's version is lower-level. It gives you more control -- use that carefully.
It is extremely important to point out that specifying a low *leeway* value for GCD timers interferes with the OS's attempt to conserve power. You'll be burning more battery if you unnecessarily specify a low leeway value.
Here we're setting up a timer to fire every 5 seconds and allow for a leeway of 1/10 of a second:
```objc
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
0, 0, DISPATCH_TARGET_QUEUE_DEFAULT);
dispatch_source_set_event_handler(source, ^(){
NSLog(@"Time flies.");
});
dispatch_source_set_timer(source, DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC,
100ull * NSEC_PER_MSEC);
self.source = source;
dispatch_resume(self.source);
```
### Canceling
All sources allow you to add a *cancel handler*. This can be useful to clean up any resources you've created for the event source, such as closing file descriptors. GCD guarantees that all calls to the event handler have completed before the cancel handler gets called.
See the use of `dispatch_source_set_cancel_handler()` in the above [example for a watch folder](#watching_files).
<a name="input_output" id="input_output"> </a>
## Input / Output
Writing code that performs well while doing heavy I/O is extremely tricky. GCD has a few tricks up its sleeve to help. Without going into too much detail, we'll shortly touch upon what these problems are, and how GCD approaches them.
Traditionally when you were reading data from a network socket, you'd either have to do a blocking read, i.e. parking a thread until data became available, or you'd have to repeatedly poll. Both approaches are wasteful and don't scale. However, `kqueue` solved the polling by posting an event once data became available, and GCD uses the same approach, although more elegantly. When writing data to a socket, the identical problems exist, where you have to either perform a blocking write, or wait for the socket to be able to accept data.
The second problem when performing I/O is that data arrives in small chunks; when reading from a network, the chunk size is typically around 1.5k bytes due to the MTU -- [maximum transmission unit](https://en.wikipedia.org/wiki/Maximum_transmission_unit). This can be anything, though. Once this data arrives, you're often interested in data that spans multiple chunks, and traditionally you would concatenate the data into one larger buffer and then process that. Let's say (contrived example), you receive these eight chunks
```
0: HTTP/1.1 200 OK\r\nDate: Mon, 23 May 2005 22:38
1: :34 GMT\r\nServer: Apache/1.3.3.7 (Unix) (Red-H
2: at/Linux)\r\nLast-Modified: Wed, 08 Jan 2003 23
3: :11:55 GMT\r\nEtag: "3f80f-1b6-3e1cb03b"\r\nCon
4: tent-Type: text/html; charset=UTF-8\r\nContent-
5: Length: 131\r\nConnection: close\r\n\r\n<html>\r
6: \n<head>\r\n <title>An Example Page</title>\r\n
7: </head>\r\n<body>\r\n Hello World, this is a ve
```
If you were looking for an HTTP header, it'd be much simpler to concatenate all data chunks into a larger buffer and then scan for `\r\n\r\n`. But in doing so, you'd be copying around data a lot. The other problem with a lot of the *old* C APIs is that there's no ownership of buffers so that functions had to copy data into their own buffers -- another copy. Copying data may seem trivial, but when you're doing a lot of I/O you'll see those copies show up in your profiling tool (Instruments). Even if you only copy each memory region once, you're incurring twice the memory bandwidth and you're burning through twice the amount of memory cache.
### GCD and Buffers
The more straightforward piece is about data buffers. GCD has a `dispatch_data_t` type that to some extent is similar to what `NSData` does for Objective-C. It can do other things, though, and is more generic.
Note that `dispatch_data_t` can be retained and released, and the `dispatch_data_t` object *owns* the buffer it holds onto.
This may seem trivial, but we have to remember that GCD is a plain C API, and can't use Objective-C. The traditional way was to have a buffer either backed by the stack or a `malloc`'d memory region -- these don't have ownership.
One relatively unique property of `dispatch_data_t` is that it can be backed by disjoint memory regions. That solves the concatenation problem we just mentioned. When you concatenate two data objects with
```objc
dispatch_data_t a; // Assume this hold some valid data
dispatch_data_t b; // Assume this hold some valid data
dispatch_data_t c = dispatch_data_create_concat(a, b);
```
the data object `c` will *not* copy `a` and `b` into a single, larger memory region. Instead it will simply retain both `a` and `b`. You can then traverse the memory regions represented by `c` with `dispatch_data_apply`:
```objc
dispatch_data_apply(c, ^bool(dispatch_data_t region, size_t offset, const void *buffer, size_t size) {
fprintf(stderr, "region with offset %zu, size %zu\n", offset, size);
return true;
});
```
Similarly you can create a subrange with `dispatch_data_create_subrange` that won't do any copying.
### Reading and Writing
At its core, *Dispatch I/O* is about so-called *channels*. A dispatch I/O channel provides a different way to read and write from a file descriptor. The most basic way to create such a channel is by calling
```objc
dispatch_io_t dispatch_io_create(dispatch_io_type_t type, dispatch_fd_t fd,
dispatch_queue_t queue, void (^cleanup_handler)(int error));
```
This returns the created channel which then *owns* the file descriptor. You must not modify the file descriptor in any way after you've created a channel from it.
There are two fundamentally different *types* of channels: streams and random access. If you open a file on disk, you can use it to create a random access channel (because such a file descriptor is `seek`able). If you open a socket, you can create a stream channel.
If you want to create a channel for a file, you're better off using `dispatch_io_create_with_path`, which takes a path, and lets GCD open the file. This is beneficial, since GCD can postpone opening the file -- hence limiting the number of files that are open at the same time.
Analogous to the normal `read(2)`, `write(2)`, and `close(2)`, GCD offers `dispatch_io_read`, `dispatch_io_write`, and `dispatch_io_close`. Reading and writing is done via a callback block that is called whenever data is read or written. This effectively implements non-blocking, fully async I/O.
We can't go into all details here, but here's an example for setting up a TCP server:
First we create a listening socket and set up an event source for incoming connections:
```objc
_isolation = dispatch_queue_create([[self description] UTF8String], NULL);
_nativeSocket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
struct sockaddr_in sin = {};
sin.sin_len = sizeof(sin);
sin.sin_family = AF_INET6;
sin.sin_port = htons(port);
sin.sin_addr.s_addr= INADDR_ANY;
int err = bind(result.nativeSocket, (struct sockaddr *) &sin, sizeof(sin));
NSCAssert(0 <= err, @"");
_eventSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, _nativeSocket, 0, _isolation);
dispatch_source_set_event_handler(result.eventSource, ^{
acceptConnection(_nativeSocket);
});
```
When accepting a connection, we create an I/O channel:
```objc
typedef union socketAddress {
struct sockaddr sa;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} socketAddressUnion;
socketAddressUnion rsa; // remote socket address
socklen_t len = sizeof(rsa);
int native = accept(nativeSocket, &rsa.sa, &len);
if (native == -1) {
// Error. Ignore.
return nil;
}
_remoteAddress = rsa;
_isolation = dispatch_queue_create([[self description] UTF8String], NULL);
_channel = dispatch_io_create(DISPATCH_IO_STREAM, native, _isolation, ^(int error) {
NSLog(@"An error occured while listening on socket: %d", error);
});
//dispatch_io_set_high_water(_channel, 8 * 1024);
dispatch_io_set_low_water(_channel, 1);
dispatch_io_set_interval(_channel, NSEC_PER_MSEC * 10, DISPATCH_IO_STRICT_INTERVAL);
socketAddressUnion lsa; // remote socket address
socklen_t len = sizeof(rsa);
getsockname(native, &lsa.sa, &len);
_localAddress = lsa;
```
If we want to set `SO_KEEPALIVE` (if we're using HTTP-level keep-alive), we need to do so before calling `dispatch_io_create`.
Having created a `dispatch_io` channel, we can set up the read handler:
```objc
dispatch_io_read(_channel, 0, SIZE_MAX, _isolation, ^(bool done, dispatch_data_t data, int error){
if (data != NULL) {
if (_data == NULL) {
_data = data;
} else {
_data = dispatch_data_create_concat(_data, data);
}
[self processData];
}
});
```
If all you want to do is to read from or write to a file, GCD provides two convenience wrappers: `dispatch_read` and `dispatch_write`. You pass `dispatch_read` a file path and a block to be called for each data block that's read. Similarly, `dispatch_write` takes a file path and a `dispatch_data_t` object to be written.
## Benchmarking
In the obscure corners of GCD, you'll find a neat little tool for optimizing your code:
```objc
uint64_t dispatch_benchmark(size_t count, void (^block)(void));
```
Put this declaration into your code, and you can measure the average number of nanoseconds the given block takes to execute. E.g.
```objc
size_t const objectCount = 1000;
uint64_t n = dispatch_benchmark(10000, ^{
@autoreleasepool {
id obj = @42;
NSMutableArray *array = [NSMutableArray array];
for (size_t i = 0; i < objectCount; ++i) {
[array addObject:obj];
}
}
});
NSLog(@"-[NSMutableArray addObject:] : %llu ns", n);
```
On my machine this outputs
```objc
-[NSMutableArray addObject:] : 31803 ns
```
i.e. that adding 1000 objects to an NSMutableArray takes 31803 ns, or about 32 ns per object.
As the [man page](http://opensource.apple.com/source/libdispatch/libdispatch-84.5/man/dispatch_benchmark.3) for `dispatch_benchmark` points out, measuring performance isn't as trivial as it may seem. Particularly when comparing concurrent code with non-concurrent, you need to pay attention to computational bandwidth and memory bandwidth of the particular piece of hardware you're running on. It will change a lot from machine to machine. And the contention problem we mentioned above will affect code if its performance is bound by access to critical sections.
Don't put this into shipping code. Aside from the fact that it'd be pretty pointless to do so, it's also private API. It's intended for debugging and performance analysis work only.
View the man page with
```objc
curl "http://opensource.apple.com/source/libdispatch/libdispatch-84.5/man/dispatch_benchmark.3?txt"
| /usr/bin/groffer --tty -T utf8
```
<a name="atomic_operations" id="atomic_operations"> </a>
## Atomic Operations
The header file `libkern/OSAtomic.h` has lots of powerful functions for lower-level multi-threaded programming. Although it's part of the kernel header files, it's intended to also be used outside kernel and driver programming.
These functions are lower-level, and there are a few extra things you need to be aware of. If you do, though, you might find a thing or two here, that you'd otherwise not be able to do -- or not do as easily. It's mostly interesting if you're working on high-performance code and / or are implementing lock-free and wait-free algorithms.
These functions are all summarized in the `atomic(3)` man page -- run `man 3 atomic` to get the complete documentation. You'll see it talking about memory barriers. Check out the [Wikipedia article about memory barriers](https://en.wikipedia.org/wiki/Memory_barrier). If you're in doubt, you probably need a memory barrier.
### Counters
There's a long list of `OSAtomicIncrement` and `OSAtomicDecrement` functions that allow you to increment and decrement an integer value in an atomic way -- thread safe without having to take a lock (or use queues). These can be useful if you need to increment global counters from multiple threads for statistics. If all you do is increment a global counter, the barrier-free `OSAtomicIncrement` versions are fine, and when there's no contention, they're cheap to call.
Similarly, the `OSAtomicOr`, `OSAtomicAnd`, and `OSAtomicXor` functions can be used to perform logical operations, and `OSAtomicTest` functions to set or clear bits.
### Compare and Swap
The `OSAtomicCompareAndSwap` can be useful to do lock-free lazy initializations like this:
```objc
void * sharedBuffer(void)
{
static void * buffer;
if (buffer == NULL) {
void * newBuffer = calloc(1, 1024);
if (!OSAtomicCompareAndSwapPtrBarrier(NULL, newBuffer, &buffer)) {
free(newBuffer);
}
}
return buffer;
}
```
If there's no buffer, we create one and then atomically write it to `buffer` if `buffer` is NULL. In the rare case that someone else set `buffer` at the same time as the current thread, we simply free it. Since the compare-and-swap method is atomic, this is a thread-safe way to lazily initialize values. The check that `NULL` and setting `buffer` are done atomically.
Obviously, you can do something similar with `dispatch_once()`.
### Atomic Queues
The `OSAtomicEnqueue()` and `OSAtomicDequeue()` let you implement LIFO queues (also known as stacks) in a thread-safe, lock-free way. For code that has strict latency requirements, this can be a powerful building block.
There's also a `OSAtomicFifoEnqueue()` and `OSAtomicFifoDequeue()` for FIFO queues, but these only have documentation in the header file -- read carefully when using.
### Spin Locks
Finally, the `OSAtomic.h` header defines the functions to work with spin locks: `OSSpinLock`. Again, Wikipedia has [in-depth information on spin locks](https://en.wikipedia.org/wiki/Spinlock). Check out the `spinlock(3)` man page with `man 3 spinlock`. The short story is that a spin lock is very cheap when there's no lock contention.
Spin locks can be useful in certain situations as a performance optimization. As always: measure first, then optimize. Don't do optimistic optimizations.
Here's an example for OSSpinLock:
```objc
@interface MyTableViewCell : UITableViewCell
@property (readonly, nonatomic, copy) NSDictionary *amountAttributes;
@end
@implementation MyTableViewCell
{
NSDictionary *_amountAttributes;
}
- (NSDictionary *)amountAttributes;
{
if (_amountAttributes == nil) {
static __weak NSDictionary *cachedAttributes = nil;
static OSSpinLock lock = OS_SPINLOCK_INIT;
OSSpinLockLock(&lock);
_amountAttributes = cachedAttributes;
if (_amountAttributes == nil) {
NSMutableDictionary *attributes = [[self subtitleAttributes] mutableCopy];
attributes[NSFontAttributeName] = [UIFont fontWithName:@"ComicSans" size:36];
attributes[NSParagraphStyleAttributeName] = [NSParagraphStyle defaultParagraphStyle];
_amountAttributes = [attributes copy];
cachedAttributes = _amountAttributes;
}
OSSpinLockUnlock(&lock);
}
return _amountAttributes;
}
```
In the above example, it's probably not worth the trouble, but it shows the concept. We're using ARC's `__weak` to make sure that the `amountAttributes` will get `dealloc`'ed once all instances of `MyTableViewCell` go away. Yet we're able to share a single instance of this dictionary among all instances.
The reason this performs well is that we're unlikely to hit the inner-most part of the method. This is quite esoteric -- don't use this in your App unless you have a real need.
================================================
FILE: 2013-07-07-thread-safe-class-design.md
================================================
---
title: "Thread-Safe Class Design"
category: "2"
date: "2013-07-07 07:00:00"
author:
- name: Peter Steinberger
url: https://twitter.com/steipete
tags: article
---
This article will focus on *practical* tips, design patterns, and anti-patterns with regard to writing thread-safe classes and using Grand Central Dispatch (GCD).
## Thread Safety
### Apple's Frameworks
First, let's have a look at Apple's frameworks. In general, unless declared otherwise, most classes are not thread-safe by default. For some this is expected; for others it's quite interesting.
One of the most common mistakes even experienced iOS/Mac developers make is accessing parts of UIKit/AppKit on background threads. It's very easy to make the mistake of setting properties like `image` from a background thread, because their content is being requested from the network in the background anyway. Apple's code is performance-optimized and will not warn you if you change properties from different threads.
In the case of an image, a common symptom is that your change is picked up with a delay. But if two threads set the image at the same time, it's likely that your app will simply crash, because the currently set image could be released twice. Since this is timing dependent, it usually will crash when used by your customers and not during development.
There are no *official* tools to find such errors, but there are some tricks that will do the job just fine. The [UIKit Main Thread Guard](https://gist.github.com/steipete/5664345) is a small source file that will patch any calls to UIView's `setNeedsLayout` and `setNeedsDisplay` and check for being executed on the main thread before forwarding the call. Since these two methods are called for a lot of UIKit setters (including image), this will catch many thread-related mistakes. Although this trick does not use private API, we don't recommend using this in production apps -- it's great during development though.
It's a conscious design decision from Apple's side to not have UIKit be thread-safe. Making it thread-safe wouldn't buy you much in terms of performance; it would in fact make many things slower. And the fact that UIKit is tied to the main thread makes it very easy to write concurrent programs and use UIKit. All you have to do is make sure that calls into UIKit are always made on the main thread.
#### Why Isn't UIKit Thread Safe?
Ensuring thread safety for a big framework like UIKit would be a major undertaking and would come at a great cost. Changing non-atomic to atomic properties would only be a tiny part of the changes required. Usually you want to change several properties at once, and only then see the changed result. For this, Apple would have to expose a method much like CoreData's `performBlock:` and `performBlockAndWait:` to synchronize changes. And if you consider that most calls to UIKit classes are about *configuration*, it's even more pointless to make them thread-safe.
However, even calls that are not about configuration shared internal state and thus weren't thread-safe. If you already wrote apps back in the dark ages of iOS3.2 and before, you surely experienced random crashes when using NSString's `drawInRect:withFont:` while preparing background images. Thankfully, with iOS4, [Apple made most drawing methods and classes like `UIColor` and `UIFont` usable on background threads](http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniOS/).
Unfortunately, Apple's documentation is lacking on the subject of thread safety. They recommend access on the main thread only, and even for drawing methods they don't explicitly guarantee thread safety - so it's always a good idea to read the [iOS Release Notes](http://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniOS/Articles/iPhoneOS4.html) as well.
For the most part, UIKit classes should be used only from the application’s main thread. This is particularly true either for classes derived from UIResponder or those that involve manipulating your application’s user interface in any way.
#### The Deallocation Problem
Another danger when using UIKit objects in the background is called "The Deallocation Problem." Apple outlines the issue in [TN2109](http://developer.apple.com/library/ios/#technotes/tn2109/_index.html) and presents various solutions. The problem is that UI objects should be deallocated on the main thread, because some of them might perform changes to the view hierarchy in `dealloc`. As we know, such calls to UIKit need to happen on the main thread.
Since it's common that a secondary thread, operation, or block retains the caller, this is very easy to get wrong and quite hard to find/fix. This was also [a long-standing bug in AFNetworking](https://github.com/AFNetworking/AFNetworking/issues/56), simply because not a lot of people know about this issue and -- as usual -- it manifests itself in rare, hard-to-reproduce crashes. Consistent use of \_\_weak and not accessing ivars in async blocks/operations helps.
#### Collection Classes
Apple has a good overview document for both [iOS and Mac](https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-SW1) listing thread safety for the most common foundation classes. In general, immutable classes like `NSArray` are thread-safe, while their mutable variants like `NSMutableArray` are not. In fact, it's fine to use them from different threads, as long as access is serialized within a queue. Remember that methods might return a mutable variant of a collection object even if they declare their return type as immutable. It's good practice to write something like `return [array copy]` to ensure the returned object is in fact immutable.
Unlike in languages like [Java](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html), the Foundation framework doesn't offer thread-safe collection classes out of the box. This is actually very reasonable, because in most cases you want to apply your locks higher up anyway to avoid too many locking operations. A notable exception are caches, where a mutable dictionary might hold immutable data -- here Apple added `NSCache` in iOS4 that not only locks access, but also purges its content in low-memory situations.
That said, there might be valid cases in your application where a thread-safe, mutable dictionary can be handy. And thanks to the class cluster approach, [it's easy to write one](https://gist.github.com/steipete/5928916).
### Atomic Properties
Ever wondered how Apple is handling atomic setting/getting of properties? By now you have likely heard about spinlocks, semaphores, locks, @synchronized - so what's Apple using? Thankfully, [the Objective-C runtime is public](http://www.opensource.apple.com/source/objc4/), so we can take a look behind the curtain.
A nonatomic property setter might look like this:
```objc
- (void)setUserName:(NSString *)userName {
if (userName != _userName) {
[userName retain];
[_userName release];
_userName = userName;
}
}
```
This is the variant with manual retain/release; however, the ARC-generated code looks similar. When we look at this code it's obvious why this means trouble when `setUserName:` is called concurrently. We could end up releasing `_userName` twice, which can corrupt memory and lead to hard-to-find bugs.
What's happening internally for any property that's not manually implemented is that the compiler generates a call to [`objc_setProperty_non_gc(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic, signed char shouldCopy)`](https://github.com/opensource-apple/objc4/blob/master/runtime/Accessors.subproj/objc-accessors.mm#L127). In our example, the call parameters would look like this:
```objc
objc_setProperty_non_gc(self, _cmd,
(ptrdiff_t)(&_userName) - (ptrdiff_t)(self), userName, NO, NO);`
```
The ptrdiff_t might look weird to you, but in the end it's simple pointer arithmetic, since an Objective-C class is just another C struct.
`objc_setProperty` calls down to following method:
```objc
static inline void reallySetProperty(id self, SEL _cmd, id newValue,
ptrdiff_t offset, bool atomic, bool copy, bool mutableCopy)
{
id oldValue;
id *slot = (id*) ((char*)self + offset);
if (copy) {
newValue = [newValue copyWithZone:NULL];
} else if (mutableCopy) {
newValue = [newValue mutableCopyWithZone:NULL];
} else {
if (*slot == newValue) return;
newValue = objc_retain(newValue);
}
if (!atomic) {
oldValue = *slot;
*slot = newValue;
} else {
spin_lock_t *slotlock = &PropertyLocks[GOODHASH(slot)];
_spin_lock(slotlock);
oldValue = *slot;
*slot = newValue;
_spin_unlock(slotlock);
}
objc_release(oldValue);
}
```
Aside from the rather funny name, this method is actually fairly straightforward and uses one of the 128 available spinlocks in `PropertyLocks`. This is a pragmatic and fast approach -- the worst case scenario is that a setter might have to wait for an unrelated setter to finish because of a hash collision.
While those methods aren't declared in any public header, it is possible to call them manually. I'm not saying this is a good idea, but it's interesting to know and could be quite useful if you want atomic properties *and* to implement the setter at the same time.
```objc
// Manually declare runtime methods.
extern void objc_setProperty(id self, SEL _cmd, ptrdiff_t offset,
id newValue, BOOL atomic, BOOL shouldCopy);
extern id objc_getProperty(id self, SEL _cmd, ptrdiff_t offset,
BOOL atomic);
#define PSTAtomicRetainedSet(dest, src) objc_setProperty(self, _cmd,
(ptrdiff_t)(&dest) - (ptrdiff_t)(self), src, YES, NO)
#define PSTAtomicAutoreleasedGet(src) objc_getProperty(self, _cmd,
(ptrdiff_t)(&src) - (ptrdiff_t)(self), YES)
```
[Refer to this gist](https://gist.github.com/steipete/5928690) for the full snippet including code to handle structs. But keep in mind that we don't recommend using this.
#### What about @synchronized?
You might be curious why Apple isn't using `@synchronized(self)` for property locking, an already existing runtime feature. Once you [look at the source](https://github.com/opensource-apple/objc4/blob/master/runtime/objc-sync.mm#L291), you'll see that there's a lot more going on. Apple is using [up to three lock/unlock sequences](http://googlemac.blogspot.co.at/2006/10/synchronized-swimming.html), partly because they also add [exception unwinding](https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW3). This would be a slowdown compared to the much faster spinlock approach. Since setting the property usually is quite fast, spinlocks are perfect for the job. `@synchonized(self)` is good when you need to ensure that exception can be thrown without the code deadlocking.
### Your Own Classes
Using atomic properties alone won't make your classes thread-safe. It will only protect you against [race conditions][103] in the setter, but won't protect your application logic. Consider the following snippet:
```objc
if (self.contents) {
CFAttributedStringRef stringRef = CFAttributedStringCreate(NULL,
(__bridge CFStringRef)self.contents, NULL);
// draw string
}
```
I've made this mistake early on in [PSPDFKit](http://pspdfkit.com). From time to time, the application crashed with a EXC_BAD_ACCESS, when the `contents` property was set to nil after the check. A simple fix for this issue would be to capture the variable:
```objc
NSString *contents = self.contents;
if (contents) {
CFAttributedStringRef stringRef = CFAttributedStringCreate(NULL,
(__bridge CFStringRef)contents, NULL);
// draw string
}
```
This would solve the issue here, but in most cases it's not that simple. Imagine that we also have a `textColor` property and we change both properties on one thread. Then our render thread could end up using the new content along with the old color value and we get a weird combination. This is one reason why Core Data binds model objects to one thread or queue.
There's no one-size-fits-all solution for this problem. Using [immutable models](http://www.cocoawithlove.com/2008/04/value-of-immutable-values.html) is a solution, but it has its own problems. Another way is to limit changes to existing objects to the main thread or a specific queue and to generate copies before using them on worker threads. I recommend Jonathan Sterling's article about [Lightweight Immutability in Objective-C](http://www.jonmsterling.com/posts/2012-12-27-a-pattern-for-immutability.html) for even more ideas on solving this problem.
The simple solution is to use @synchronize. Anything else is very, very likely to get you into trouble. Way smarter people have failed again and again at doing so.
#### Practical Thread-Safe Design
Before trying to make something thread-safe, think hard if it's necessary. Make sure it's not premature optimization. If it's anything like a configuration class, there's no point in thinking about thread safety. A much better approach is to throw some asserts in to ensure it's used correctly:
```objc
void PSPDFAssertIfNotMainThread(void) {
NSAssert(NSThread.isMainThread,
@"Error: Method needs to be called on the main thread. %@",
[NSThread callStackSymbols]);
}
```
Now there's code that definitely should be thread-safe; a good example is a caching class. A good approach is to use a concurrent dispatch_queue as read/write lock to maximize performance and try to only lock the areas that are really necessary. Once you start using multiple queues for locking different parts, things get tricky really fast.
Sometimes you can also rewrite your code so that special locks are not required. Consider this snippet that is a form of a multicast delegate. (In many cases, using NSNotifications would be better, but there are [valid use cases for multicast delegates.](https://code.google.com/r/riky-adsfasfasf/source/browse/Utilities/GCDMulticastDelegate.h))
```objc
// header
@property (nonatomic, strong) NSMutableSet *delegates;
// in init
_delegateQueue = dispatch_queue_create("com.PSPDFKit.cacheDelegateQueue",
DISPATCH_QUEUE_CONCURRENT);
- (void)addDelegate:(id<PSPDFCacheDelegate>)delegate {
dispatch_barrier_async(_delegateQueue, ^{
[self.delegates addObject:delegate];
});
}
- (void)removeAllDelegates {
dispatch_barrier_async(_delegateQueue, ^{
self.delegates removeAllObjects];
});
}
- (void)callDelegateForX {
dispatch_sync(_delegateQueue, ^{
[self.delegates enumerateObjectsUsingBlock:^(id<PSPDFCacheDelegate> delegate, NSUInteger idx, BOOL *stop) {
// Call delegate
}];
});
}
```
Unless `addDelegate:` or `removeDelegate:` is called thousand times per second, a simpler and cleaner approach is the following:
```objc
// header
@property (atomic, copy) NSSet *delegates;
- (void)addDelegate:(id<PSPDFCacheDelegate>)delegate {
@synchronized(self) {
self.delegates = [self.delegates setByAddingObject:delegate];
}
}
- (void)removeAllDelegates {
@synchronized(self) {
self.delegates = nil;
}
}
- (void)callDelegateForX {
[self.delegates enumerateObjectsUsingBlock:^(id<PSPDFCacheDelegate> delegate, NSUInteger idx, BOOL *stop) {
// Call delegate
}];
}
```
Granted, this example is a bit constructed and one could simply confine changes to the main thread. But for many data structures, it might be worth it to create immutable copies in the modifier methods, so that the general application logic doesn't have to deal with excessive locking.
## Pitfalls of GCD
For most of your locking needs, GCD is perfect. It's simple, it's fast, and its block-based API makes it much harder to accidentally do imbalanced locks. However, there are quite a few pitfalls, some of which we are going to explore here.
### Using GCD as a Recursive Lock
GCD is a queue to serialize access to shared resources. This can be used for locking, but it's quite different than `@synchronized`. GCD queues are not reentrant - this would break the queue characteristics. Many people tried working around this with using `dispatch_get_current_queue()`, which is [a bad idea](https://gist.github.com/steipete/3713233), and Apple had its reasons for deprecating this method in iOS6.
```objc
// This is a bad idea.
inline void pst_dispatch_sync_reentrant(dispatch_queue_t queue,
dispatch_block_t block)
{
dispatch_get_current_queue() == queue ? block()
: dispatch_sync(queue, block);
}
```
Testing for the current queue might work for simple solutions, but it fails as soon as your code gets more complex, and you might have multiple queues locked at the same time. Once you are there, you almost certainly will get a [deadlock][104]. Sure, one could use `dispatch_get_specific()`, which will traverse the whole queue hierarchy to test for specific queues. For that you would have to write custom queue constructors that apply this metadata. Don't go that way. There are use cases where a `NSRecursiveLock` is the better solution.
### Fixing Timing Issues with dispatch_async
Having some timing-issues in UIKit? Most of the time, this will be the perfect "fix:"
```objc
dispatch_async(dispatch_get_main_queue(), ^{
// Some UIKit call that had timing issues but works fine
// in the next runloop.
[self updatePopoverSize];
});
```
Don't do this, trust me. This will haunt you later as your app gets larger. It's super hard to debug and soon things will fall apart when you need to dispatch more and more because of "timing issues." Look through your code and find the proper place for the call (e.g. viewWillAppear instead of viewDidLoad). I still have some of those hacks in my codebase, but most of them are properly documented and an issue is filed.
Remember that this isn't really GCD-specific, but it's a common anti-pattern and just very easy to do with GCD. You can apply the same wisdom for `performSelector:afterDelay:`, where the delay is 0.f for the next runloop.
### Mixing dispatch\_sync and dispatch\_async in Performance Critical Code
That one took me a while to figure out. In [PSPDFKit](http://pspdfkit.com) there is a caching class that uses a LRU list to track image access. When you scroll through the pages, this is called *a lot*. The initial implementation used dispatch\_sync for availability access, and dispatch\_async to update the LRU position. This resulted in a frame rate far from the goal of 60 FPS.
When other code running in your app is blocking GCD's threads, it might take a while until the dispatch manager finds a thread to perform the dispatch\_async code -- until then, your sync call will be blocked. Even when, as in this example, the order of execution for the async case isn't important, there's no easy way to tell that to GCD. Read/Write locks won't help you there, since the async process most definitely needs to perform a barrier write and all your readers will be locked during that. Lesson: `dispatch_async` can be expensive if it's misused. Be careful when using it for locking.
### Using dispatch_async to Dispatch Memory-Intensive Operations
We already talked a lot about NSOperations, and that it's usually a good idea to use the more high-level API. This is especially true if you deal with blocks of work that do memory-intensive operations.
In an old version of PSPDFKit, I used a GCD queue to dispatch writing cached JPG images to disk. When the retina iPad came out, this started causing trouble. The resolution doubled, and it took much longer to encode the image data than it took to render it. Consequently, operations piled up in the queue and when the system was busy it could crash of memory exhaustion.
There's no way to see how many operations are queued (unless you manually add code to track this), and there's also no built-in way to cancel operations in case of a low-memory notification. Switching to NSOperations made the code a lot more debuggable and allowed all this without writing manual management code.
Of course there are some caveats; for example you can't set a target queue on your `NSOperationQueue` (like `DISPATCH_QUEUE_PRIORITY_BACKGROUND` for throttled I/O). But that's a small price for debuggability, and it also prevents you from running into problem like [priority inversion][102]. I even recommend against the nice `NSBlockOperation` API and suggest real subclasses of NSOperation, including an implementation of description. It's more work, but later on, having a way to print all running/pending operations is insanely useful.
[90]: /issues/2-concurrency/editorial/
[100]: /issues/2-concurrency/concurrency-apis-and-pitfalls/
[101]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#challenges
[102]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#priority_inversion
[103]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#shared_resources
[104]: /issues/2-concurrency/concurrency-apis-and-pitfalls/#dead_locks
[200]: /issues/2-concurrency/common-background-practices/
[300]: /issues/2-concurrency/low-level-concurrency-apis/
[301]: /issues/2-concurrency/low-level-concurrency-apis/#async
[302]: /issues/2-concurrency/low-level-concurrency-apis/#multiple-readers-single-writer
[400]: /issues/2-concurrency/thread-safe-class-design/
================================================
FILE: 2013-08-07-advanced-auto-layout-toolbox.md
================================================
---
title: "Advanced Auto Layout Toolbox"
category: "3"
date: "2013-08-07 06:00:00"
author:
- name: Florian Kugler
url: http://twitter.com/floriankugler
tags: article
---
Auto Layout was introduced in OS X 10.7, and one year later it made its way into iOS 6. Soon apps on iOS 7 will be expected to honor the systemwide font size setting, thus requiring even more flexibility in the user interface layout next to different screen sizes and orientations. Apple is doubling down on Auto Layout, so now is a good time to get your feet wet if you haven't done so yet.
Many developers struggle with Auto Layout when first trying it, because of the often-frustrating experience of building constraint-based layouts with Xcode 4's Interface Builder. But don't let yourself be discouraged by that; Auto Layout is much better than Interface Builder's current support for it. Xcode 5 will bring some major relief in this area.
This article is not an introduction to Auto Layout. If you haven't worked with it yet, we encourage you to watch the Auto Layout sessions from WWDC 2012 ([202 -- Introduction to Auto Layout for iOS and OS X](https://developer.apple.com/videos/wwdc/2012/?id=202), [228 -- Best Practices for Mastering Auto Layout](https://developer.apple.com/videos/wwdc/2012/?id=228), [232 -- Auto Layout by Example](https://developer.apple.com/videos/wwdc/2012/?id=232)). These are excellent introductions to the topic which cover a lot of ground.
Instead, we are going to focus on several advanced tips and techniques, which enhance productivity with Auto Layout and make your (development) life easier. Most of these are touched upon in the WWDC sessions mentioned above, but they are the kind of things that are easy to oversee or forget while trying to get your daily work done.
<a name="layout-process"> </a>
## The Layout Process
First we will recap the steps it takes to bring views on screen with Auto Layout enabled. When you're struggling to produce the kind of layout you want with Auto Layout, specifically with advanced use cases and animation, it helps to take a step back and to recall how the layout process works.
Compared to working with springs and struts, Auto Layout introduces two additional steps to the process before views can be displayed: updating constraints and laying out views. Each step is dependent on the one before; display depends on layout, and layout depends on updating constraints.
The first step -- updating c
gitextract_pol5nsbk/ ├── 2013-06-07-containment-view-controller.md ├── 2013-06-07-introduction.markdown ├── 2013-06-07-lighter-view-controllers.md ├── 2013-06-07-table-views.md ├── 2013-06-07-testing-view-controllers.md ├── 2013-07-07-async-testing.md ├── 2013-07-07-common-background-practices.md ├── 2013-07-07-concurrency-apis-and-pitfalls.md ├── 2013-07-07-editorial.markdown ├── 2013-07-07-low-level-concurrency-apis.md ├── 2013-07-07-thread-safe-class-design.md ├── 2013-08-07-advanced-auto-layout-toolbox.md ├── 2013-08-07-collection-view-layouts.md ├── 2013-08-07-custom-controls.markdown ├── 2013-08-07-editorial.md ├── 2013-08-07-moving-pixels-onto-the-screen.md ├── 2013-08-07-scroll-view.md ├── 2013-09-09-SQLite-instead-of-core-data.markdown ├── 2013-09-09-core-data-fetch-requests.md ├── 2013-09-09-core-data-migration.md ├── 2013-09-09-core-data-models-and-model-objects.md ├── 2013-09-09-core-data-overview.md ├── 2013-09-09-editorial.md ├── 2013-09-09-full-core-data-application.md ├── 2013-09-09-importing-large-data-sets-into-core-data.md ├── 2013-10-08-collection-views-and-uidynamics.md ├── 2013-10-08-editorial.md ├── 2013-10-08-from-nsurlconnection-to-nsurlsession.md ├── 2013-10-08-getting-to-know-textkit.md ├── 2013-10-08-iOS7-hidden-gems-and-workarounds.md ├── 2013-10-08-multitasking.md ├── 2013-10-08-redesigning-for-ios-7.md ├── 2013-10-08-view-controller-transitions.md ├── 2013-11-08-build-process.md ├── 2013-11-08-cocoapods-under-the-hood.md ├── 2013-11-08-compiler.markdown ├── 2013-11-08-editorial.md ├── 2013-11-08-mach-o-executables.md ├── 2013-11-08-travis-ci.markdown ├── 2013-12-07-collections.md ├── 2013-12-09-communication-patterns.md ├── 2013-12-09-editorial.md ├── 2013-12-09-key-value-coding-and-observing.md ├── 2013-12-09-linguistic-tagging.md ├── 2013-12-09-nsformatter.md ├── 2013-12-09-value-objects.md ├── 2014-01-08-communicating-with-the-quadcopter.md ├── 2014-01-08-editorial.md ├── 2014-01-08-the-quadcopter-client-app.md ├── 2014-01-08-the-quadcopter-navigator-app.md ├── 2014-01-08-the-quadcopter-project.md ├── 2014-02-10-editorial.md ├── 2014-02-10-string-localization.md ├── 2014-02-10-string-parsing.md ├── 2014-02-10-string-rendering.md ├── 2014-02-10-unicode.md ├── 2014-02-10-working-with-strings.md ├── 2014-03-07-data-synchronization.md ├── 2014-03-07-editorial.md ├── 2014-03-07-icloud-core-data.md ├── 2014-03-07-icloud-document-store.md ├── 2014-03-07-ip-tcp-http.markdown ├── 2014-03-07-networked-core-data-application.md ├── 2014-03-07-sync-case-study.md ├── 2014-04-01-android-intents.md ├── 2014-04-01-android-notifications.md ├── 2014-04-01-android_101_for_ios_developers.md ├── 2014-04-01-dependency-injection-in-java.md ├── 2014-04-01-editorial.md ├── 2014-04-01-responsive-android-applications.md ├── 2014-04-01-sqlite-database-support-in-android.md ├── 2014-05-08-animating-custom-layer-properties.md ├── 2014-05-08-animations-explained.md ├── 2014-05-08-collectionview-animations.md ├── 2014-05-08-custom-container-view-controller-transitions.md ├── 2014-05-08-editorial.md ├── 2014-05-08-interactive-animations.md ├── 2014-05-08-view-layer-synergy.md ├── 2014-06-09-behaviors.md ├── 2014-06-09-editorial.md ├── 2014-06-09-mvvm.md ├── 2014-06-09-singletons.md ├── 2014-06-09-subclassing.md ├── 2014-06-09-viper.md ├── 2014-07-11-appkit-for-uikit-developers.md ├── 2014-07-11-editorial.md ├── 2014-07-11-plugins.md ├── 2014-07-11-sandbox-scripting.md ├── 2014-07-11-scripting-data.md ├── 2014-07-11-xpc.markdown ├── 2014-08-11-bad-testing-practices.md ├── 2014-08-11-behavior-driven-development.md ├── 2014-08-11-dependency-injection.md ├── 2014-08-11-editorial.md ├── 2014-08-11-mocking-stubbing.md ├── 2014-08-11-snapshot-testing.md ├── 2014-08-11-user-interface-testing.md ├── 2014-08-11-xctest.markdown ├── 2014-09-10-editorial.md ├── 2014-09-10-functional-swift-apis.md ├── 2014-09-10-power-of-swift.md ├── 2014-09-10-rapid-prototyping-in-swift-playgrounds.md ├── 2014-09-10-swift-classes-vs-structs.md ├── 2014-09-10-swift-functions.md ├── 2014-10-10-editorial.md ├── 2014-10-10-inside-code-signing.md ├── 2014-10-10-receipt-validation.md ├── 2014-10-10-why-security.md ├── 2014-11-10-designing-elegant-mobile-games.md ├── 2014-11-10-editorial.md ├── 2014-11-10-metal.md ├── 2014-11-10-multipeer-connectivity-for-games.md ├── 2014-11-10-scenekit.md ├── 2014-11-10-sound-design.md ├── 2014-12-08-activity-tracing.md ├── 2014-12-08-debugging-case-study.md ├── 2014-12-08-debugging-checklist.md ├── 2014-12-08-dtrace.markdown ├── 2014-12-08-editorial.md ├── 2014-12-08-lldb-debugging.md ├── 2015-01-13-andy-matuschak.md ├── 2015-01-13-editorial.md ├── 2015-01-13-loren-brichter.md ├── 2015-01-13-natasha-murashev.md ├── 2015-02-10-camera-capture-on-ios.md ├── 2015-02-10-core-image-intro.md ├── 2015-02-10-editorial.md ├── 2015-02-10-face-recognition-with-opencv.md ├── 2015-02-10-gpu-accelerated-image-processing.md ├── 2015-02-10-gpu-accelerated-machine-vision.md ├── 2015-02-10-how-your-camera-works.md ├── 2015-02-10-image-formats.md ├── 2015-02-10-photo-extensions.md ├── 2015-02-10-the-photos-framework.md ├── 2015-03-10-artsy.md ├── 2015-03-10-dropbox.md ├── 2015-03-10-editorial.md ├── 2015-03-10-facebook.md ├── 2015-03-10-omni-group.md ├── 2015-03-10-square.md ├── 2015-04-13-capturing-video.md ├── 2015-04-13-core-image-video.md ├── 2015-04-13-editorial.md ├── 2015-04-13-videotoolbox.md ├── 2015-05-11-audio-api-overview.md ├── 2015-05-11-audio-dog-house.md ├── 2015-05-11-editorial.md ├── 2015-05-11-functional-signal-processing.md ├── 2015-05-11-sound-design.md └── README.md
Condensed preview — 150 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,889K chars).
[
{
"path": "2013-06-07-containment-view-controller.md",
"chars": 9436,
"preview": "---\ntitle: \"View Controller Containment\"\ncategory: \"1\"\ndate: \"2013-06-07 08:00:00\"\nauthor:\n - name: Ricki Gregersen\n "
},
{
"path": "2013-06-07-introduction.markdown",
"chars": 2090,
"preview": "---\ntitle: \"Introduction\"\ncategory: \"1\"\ndate: \"2013-06-07 12:00\"\ntags: editorial\n---\n\nWelcome to the first edition of o"
},
{
"path": "2013-06-07-lighter-view-controllers.md",
"chars": 10932,
"preview": "---\ntitle: \"Lighter View Controllers\"\ncategory: \"1\"\ndate: \"2013-06-07 11:00:00\"\nauthor:\n - name: Chris Eidhof\n url:"
},
{
"path": "2013-06-07-table-views.md",
"chars": 14519,
"preview": "---\ntitle: \"Clean Table View Code\"\ncategory: \"1\"\ndate: \"2013-06-07 10:00:00\"\nauthor:\n - name: Florian Kugler\n url: h"
},
{
"path": "2013-06-07-testing-view-controllers.md",
"chars": 18630,
"preview": "---\ntitle: \"Testing View Controllers\"\ncategory: \"1\"\ndate: \"2013-06-07 09:00\"\nauthor:\n - name: Daniel Eggert\n url: ht"
},
{
"path": "2013-07-07-async-testing.md",
"chars": 13318,
"preview": "---\ntitle: \"Testing Concurrent Applications\"\ncategory: \"2\"\ntags: article\ndate: \"2013-07-07 06:00:00\"\nauthor:\n - name: "
},
{
"path": "2013-07-07-common-background-practices.md",
"chars": 26748,
"preview": "---\ntitle: \"Common Background Practices\"\ncategory: \"2\"\ndate: \"2013-07-07 09:00:00\"\nauthor:\n - name: Chris Eidhof\n u"
},
{
"path": "2013-07-07-concurrency-apis-and-pitfalls.md",
"chars": 32312,
"preview": "---\ntitle: \"Concurrent Programming: APIs and Challenges\"\ncategory: \"2\"\ndate: \"2013-07-07 10:00:00\"\nauthor:\n - name: Flo"
},
{
"path": "2013-07-07-editorial.markdown",
"chars": 1470,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"2\"\ndate: \"2013-07-07 11:00:00\"\ntags: editorial\n---\n\nWelcome to objc.io issue #2!\n\nFir"
},
{
"path": "2013-07-07-low-level-concurrency-apis.md",
"chars": 44684,
"preview": "---\ntitle: \"Low-Level Concurrency APIs\"\ncategory: \"2\"\ndate: \"2013-07-07 8:00:00\"\nauthor:\n - name: Daniel Eggert\n ur"
},
{
"path": "2013-07-07-thread-safe-class-design.md",
"chars": 21677,
"preview": "---\ntitle: \"Thread-Safe Class Design\"\ncategory: \"2\"\ndate: \"2013-07-07 07:00:00\"\nauthor:\n - name: Peter Steinberger\n "
},
{
"path": "2013-08-07-advanced-auto-layout-toolbox.md",
"chars": 43222,
"preview": "---\ntitle: \"Advanced Auto Layout Toolbox\"\ncategory: \"3\"\ndate: \"2013-08-07 06:00:00\"\nauthor:\n - name: Florian Kugler\n "
},
{
"path": "2013-08-07-collection-view-layouts.md",
"chars": 25394,
"preview": "---\ntitle: \"Custom Collection View Layouts\"\ncategory: \"3\"\ndate: \"2013-08-07 08:00:00\"\nauthor:\n - name: Ole Begemann\n "
},
{
"path": "2013-08-07-custom-controls.markdown",
"chars": 16642,
"preview": "---\ntitle: \"Custom Controls\"\ncategory: \"3\"\ndate: \"2013-08-07 07:00:00\"\nauthor:\n - name: Chris Eidhof\n url: http://t"
},
{
"path": "2013-08-07-editorial.md",
"chars": 1670,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"3\"\r\ndate: \"2013-08-07 11:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue #"
},
{
"path": "2013-08-07-moving-pixels-onto-the-screen.md",
"chars": 50585,
"preview": "---\ntitle: \"Getting Pixels onto the Screen\"\ncategory: \"3\"\ndate: \"2013-08-07 10:00:00\"\nauthor:\n - name: Daniel Eggert\n "
},
{
"path": "2013-08-07-scroll-view.md",
"chars": 15575,
"preview": "---\ntitle: \"Understanding Scroll Views\"\ncategory: \"3\"\ndate: \"2013-08-07 09:00:00\"\nauthor:\n - name: Joe Conway\n url: "
},
{
"path": "2013-09-09-SQLite-instead-of-core-data.markdown",
"chars": 23908,
"preview": "---\ntitle: On Using SQLite and FMDB Instead of Core Data\ncategory: \"4\"\ndate: \"2013-09-09 09:00:00\"\nauthor:\n - name: Bre"
},
{
"path": "2013-09-09-core-data-fetch-requests.md",
"chars": 19695,
"preview": "---\ntitle: Fetch Requests\ncategory: \"4\"\ndate: \"2013-09-09 06:00:00\"\nauthor:\n - name: Daniel Eggert\n url: http://twit"
},
{
"path": "2013-09-09-core-data-migration.md",
"chars": 22895,
"preview": "---\ntitle: Custom Core Data Migrations\ncategory: \"4\"\ndate: \"2013-09-06 05:00:00\"\nauthor:\n - name: Martin Hwasser\n ur"
},
{
"path": "2013-09-09-core-data-models-and-model-objects.md",
"chars": 27702,
"preview": "---\ntitle: Data Models and Model Objects\ncategory: \"4\"\ndate: \"2013-09-09 08:00:00\"\nauthor:\n - name: Florian Kugler\n "
},
{
"path": "2013-09-09-core-data-overview.md",
"chars": 19267,
"preview": "---\ntitle: Core Data Overview\ncategory: \"4\"\ndate: \"2013-09-09 11:00:00\"\nauthor:\n - name: Daniel Eggert\n url: http://"
},
{
"path": "2013-09-09-editorial.md",
"chars": 3126,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"4\"\r\ndate: \"2013-09-09 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\n[100]:/issues/4-core-data/"
},
{
"path": "2013-09-09-full-core-data-application.md",
"chars": 27161,
"preview": "---\ntitle: A Complete Core Data Application\ncategory: \"4\"\ndate: \"2013-09-09 10:00:00\"\nauthor:\n - name: Chris Eidhof\n "
},
{
"path": "2013-09-09-importing-large-data-sets-into-core-data.md",
"chars": 19608,
"preview": "---\ntitle: Importing Large Data Sets\ncategory: \"4\"\ndate: \"2013-09-09 07:00:00\"\nauthor:\n - name: Florian Kugler\n url:"
},
{
"path": "2013-10-08-collection-views-and-uidynamics.md",
"chars": 28348,
"preview": "---\ntitle: \"UICollectionView + UIKit Dynamics\"\ncategory: \"5\"\ndate: \"2013-10-07 10:00:00\"\ntags: article\nauthor:\n - name"
},
{
"path": "2013-10-08-editorial.md",
"chars": 1361,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"5\"\r\ndate: \"2013-10-07 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue #"
},
{
"path": "2013-10-08-from-nsurlconnection-to-nsurlsession.md",
"chars": 17882,
"preview": "---\ntitle: \"From NSURLConnection to NSURLSession\"\ncategory: \"5\"\ndate: \"2013-10-07 08:00:00\"\ntags: article\nauthor:\n - n"
},
{
"path": "2013-10-08-getting-to-know-textkit.md",
"chars": 36370,
"preview": "---\ntitle: \"Getting to Know TextKit\"\ncategory: \"5\"\ndate: \"2013-10-07 11:00:00\"\ntags: article\nauthor:\n - name: Max Seel"
},
{
"path": "2013-10-08-iOS7-hidden-gems-and-workarounds.md",
"chars": 23974,
"preview": "---\ntitle: \"iOS 7: Hidden Gems and Workarounds\"\ncategory: \"5\"\ndate: \"2013-10-07 06:00:00\"\ntags: article\nauthor:\n - nam"
},
{
"path": "2013-10-08-multitasking.md",
"chars": 24885,
"preview": "---\ntitle: \"Multitasking in iOS 7\"\ncategory: \"5\"\ndate: \"2013-10-07 07:00:00\"\ntags: article\nauthor:\n - name: David Caunt"
},
{
"path": "2013-10-08-redesigning-for-ios-7.md",
"chars": 11318,
"preview": "---\r\ntitle: \"Re-Designing an App for iOS 7\"\r\ncategory: \"5\"\r\ndate: \"2013-10-07 05:00:00\"\r\ntags: article\r\nauthor:\r\n - nam"
},
{
"path": "2013-10-08-view-controller-transitions.md",
"chars": 12139,
"preview": "---\ntitle: \"View Controller Transitions\"\ncategory: \"5\"\ndate: \"2013-10-07 09:00:00\"\ntags: article\nauthor:\n - name: Chri"
},
{
"path": "2013-11-08-build-process.md",
"chars": 18744,
"preview": "---\ntitle: \"The Build Process\"\ncategory: \"6\"\ndate: \"2013-11-08 11:00:00\"\ntags: article\nauthor:\n - name: Florian Kugler"
},
{
"path": "2013-11-08-cocoapods-under-the-hood.md",
"chars": 12449,
"preview": "---\ntitle: \"CocoaPods Under The Hood\"\ncategory: \"6\"\ndate: \"2013-11-08 08:00:00\"\ntags: article\nauthor:\n - name: Michele"
},
{
"path": "2013-11-08-compiler.markdown",
"chars": 24735,
"preview": "---\ntitle: \"The Compiler\"\ncategory: \"6\"\ndate: \"2013-11-08 10:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n url"
},
{
"path": "2013-11-08-editorial.md",
"chars": 2347,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"6\"\r\ndate: \"2013-11-08 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue #"
},
{
"path": "2013-11-08-mach-o-executables.md",
"chars": 35718,
"preview": "---\ntitle: \"Mach-O Executables\"\ncategory: \"6\"\ndate: \"2013-11-08 09:00:00\"\ntags: article\nauthor:\n - name: Daniel Eggert\n"
},
{
"path": "2013-11-08-travis-ci.markdown",
"chars": 26397,
"preview": "---\ntitle: \"Travis CI for iOS\"\ncategory: \"6\"\ndate: \"2013-11-08 07:00:00\"\ntags: article\nauthor:\n - name: Mattes Groeger\n"
},
{
"path": "2013-12-07-collections.md",
"chars": 52161,
"preview": "---\ntitle: \"The Foundation Collection Classes\"\ncategory: \"7\"\ndate: \"2013-12-09 11:00:00\"\ntags: article\nauthor:\n - name:"
},
{
"path": "2013-12-09-communication-patterns.md",
"chars": 18417,
"preview": "---\ntitle: \"Communication Patterns\"\ncategory: \"7\"\ndate: \"2013-12-09 08:00:00\"\ntags: article\nauthor:\n - name: Florian K"
},
{
"path": "2013-12-09-editorial.md",
"chars": 2253,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"7\"\r\ndate: \"2013-12-09 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue #"
},
{
"path": "2013-12-09-key-value-coding-and-observing.md",
"chars": 34840,
"preview": "---\ntitle: \"Key-Value Coding and Observing\"\ncategory: \"7\"\ndate: \"2013-12-09 09:00:00\"\ntags: article\nauthor:\n - name: Da"
},
{
"path": "2013-12-09-linguistic-tagging.md",
"chars": 21123,
"preview": "---\ntitle: \"Linguistic Tagging\"\ncategory: \"7\"\ndate: \"2013-12-09 06:00:00\"\ntags: article\nauthor:\n - name: Oliver Mason\n"
},
{
"path": "2013-12-09-nsformatter.md",
"chars": 13827,
"preview": "---\ntitle: \"Custom Formatters\"\ncategory: \"7\"\ndate: \"2013-12-09 07:00:00\"\ntags: article\nauthor:\n - name: Klaas Pieter A"
},
{
"path": "2013-12-09-value-objects.md",
"chars": 18385,
"preview": "---\ntitle: \"Value Objects\"\ncategory: \"7\"\ndate: \"2013-12-09 10:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n ur"
},
{
"path": "2014-01-08-communicating-with-the-quadcopter.md",
"chars": 17502,
"preview": "---\ntitle: \"Communicating with the Quadcopter\"\ncategory: \"8\"\ndate: \"2014-01-08 10:00:00\"\ntags: article\nauthor:\n - name:"
},
{
"path": "2014-01-08-editorial.md",
"chars": 1711,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"8\"\r\ndate: \"2014-01-08 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue #"
},
{
"path": "2014-01-08-the-quadcopter-client-app.md",
"chars": 10363,
"preview": "---\ntitle: \"The Client App\"\ncategory: \"8\"\ndate: \"2014-01-08 08:00:00\"\ntags: article\nauthor:\n - name: Florian Kugler\n "
},
{
"path": "2014-01-08-the-quadcopter-navigator-app.md",
"chars": 9611,
"preview": "---\ntitle: \"The Navigator App\"\ncategory: \"8\"\ndate: \"2014-01-08 09:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n "
},
{
"path": "2014-01-08-the-quadcopter-project.md",
"chars": 6009,
"preview": "---\ntitle: \"The Project\"\ncategory: \"8\"\ndate: \"2014-01-08 11:00:00\"\ntags: article\nauthor:\n - name: Florian Kugler\n u"
},
{
"path": "2014-02-10-editorial.md",
"chars": 1095,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"9\"\r\ndate: \"2014-02-10 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue #"
},
{
"path": "2014-02-10-string-localization.md",
"chars": 32156,
"preview": "---\ntitle: \"String Localization\"\ncategory: \"9\"\ndate: \"2014-02-10 09:00:00\"\ntags: article\nauthor:\n - name: Florian Kugl"
},
{
"path": "2014-02-10-string-parsing.md",
"chars": 24206,
"preview": "---\ntitle: \"String Parsing\"\ncategory: \"9\"\ndate: \"2014-02-10 08:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n "
},
{
"path": "2014-02-10-string-rendering.md",
"chars": 20148,
"preview": "---\ntitle: \"String Rendering\"\ncategory: \"9\"\ndate: \"2014-02-07 07:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n "
},
{
"path": "2014-02-10-unicode.md",
"chars": 45129,
"preview": "---\ntitle: \"NSString and Unicode\"\ncategory: \"9\"\ndate: \"2014-02-10 11:00:00\"\ntags: article\nauthor:\n - name: Ole Begeman"
},
{
"path": "2014-02-10-working-with-strings.md",
"chars": 27009,
"preview": "---\ntitle: \"Working with Strings\"\ncategory: \"9\"\ndate: \"2014-02-10 10:00:00\"\ntags: article\nauthor:\n - name: Daniel Egge"
},
{
"path": "2014-03-07-data-synchronization.md",
"chars": 26620,
"preview": "---\ntitle: \"Data Synchronization\"\ncategory: \"10\"\ndate: \"2014-03-07 11:00:00\"\ntags: article\nauthor:\n - name: Drew McCor"
},
{
"path": "2014-03-07-editorial.md",
"chars": 2324,
"preview": "---\r\ntitle: \"Editorial\"\r\ncategory: \"10\"\r\ndate: \"2014-03-07 12:00:00\"\r\ntags: editorial\r\n---\r\n\r\nWelcome to objc.io issue "
},
{
"path": "2014-03-07-icloud-core-data.md",
"chars": 25201,
"preview": "---\ntitle: \"iCloud and Core Data\"\ncategory: \"10\"\ndate: \"2014-03-07 10:00:00\"\ntags: article\nauthor:\n - name: Matthew Bi"
},
{
"path": "2014-03-07-icloud-document-store.md",
"chars": 36126,
"preview": "---\ntitle: \"Mastering the iCloud Document Store\"\ncategory: \"10\"\ndate: \"2014-03-07 09:00:00\"\ntags: article\nauthor:\n - n"
},
{
"path": "2014-03-07-ip-tcp-http.markdown",
"chars": 46531,
"preview": "---\ntitle: \"IP, TCP, and HTTP\"\ncategory: \"10\"\ndate: \"2014-03-07 06:00:00\"\ntags: article\nauthor:\n - name: Daniel Eggert\n"
},
{
"path": "2014-03-07-networked-core-data-application.md",
"chars": 13636,
"preview": "---\ntitle: \"A Networked Core Data Application\"\ncategory: \"10\"\ndate: \"2014-03-07 07:00:00\"\ntags: article\nauthor:\n - nam"
},
{
"path": "2014-03-07-sync-case-study.md",
"chars": 20763,
"preview": "---\ntitle: \"A Sync Case Study\"\ncategory: \"10\"\ndate: \"2014-03-07 08:00:00\"\ntags: article\nauthor:\n - name: Florian Kugle"
},
{
"path": "2014-04-01-android-intents.md",
"chars": 32464,
"preview": "---\ntitle: \"Android Intents\"\ncategory: \"11\"\ndate: \"2014-04-01 10:00:00\"\ntags: article\nauthor:\n - name: Martin Marconci"
},
{
"path": "2014-04-01-android-notifications.md",
"chars": 21614,
"preview": "---\ntitle: \"Android’s Notification Center\"\ncategory: \"11\"\ndate: \"2014-04-01 08:00:00\"\ntags: article\nauthor:\n - name: K"
},
{
"path": "2014-04-01-android_101_for_ios_developers.md",
"chars": 29881,
"preview": "---\ntitle: \"Android 101 for iOS Developers\"\ncategory: \"11\"\ndate: \"2014-04-01 11:00:00\"\ntags: article\nauthor:\n - name: "
},
{
"path": "2014-04-01-dependency-injection-in-java.md",
"chars": 13133,
"preview": "---\ntitle: \"Dependency Injection, Annotations, and why Java is Better Than you Think it is\"\ncategory: \"11\"\ndate: \"2014-0"
},
{
"path": "2014-04-01-editorial.md",
"chars": 2173,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"11\"\ndate: \"2014-04-01 12:00:00\"\ntags: editorial\n---\n\nHey everyone,\n\nobjc.io goes Andr"
},
{
"path": "2014-04-01-responsive-android-applications.md",
"chars": 13529,
"preview": "---\ntitle: \"Responsive Android Applications\"\ncategory: \"11\"\ndate: \"2014-04-01 09:00:00\"\ntags: article\nauthor:\n - name:"
},
{
"path": "2014-04-01-sqlite-database-support-in-android.md",
"chars": 12963,
"preview": "---\ntitle: \"SQLite Database Support in Android\"\ncategory: \"11\"\ndate: \"2014-04-01 07:00:00\"\ntags: article\nauthor:\n - na"
},
{
"path": "2014-05-08-animating-custom-layer-properties.md",
"chars": 20241,
"preview": "---\ntitle: \"Animating Custom Layer Properties\"\ncategory: \"12\"\ndate: \"2014-05-08 10:00:00\"\ntags: article\nauthor:\n - nam"
},
{
"path": "2014-05-08-animations-explained.md",
"chars": 20723,
"preview": "---\ntitle: \"Animations Explained\"\ncategory: \"12\"\ndate: \"2014-05-08 11:00:00\"\ntags: article\nauthor:\n - name: Robert Böh"
},
{
"path": "2014-05-08-collectionview-animations.md",
"chars": 23295,
"preview": "---\ntitle: \"Animating Collection Views\"\ncategory: \"12\"\ndate: \"2014-05-08 07:00:00\"\ntags: article\nauthor:\n - name: Engi"
},
{
"path": "2014-05-08-custom-container-view-controller-transitions.md",
"chars": 19469,
"preview": "---\ntitle: \"Custom Container View Controller Transitions\"\ncategory: \"12\"\ndate: \"2014-05-08 09:00:00\"\ntags: article\nauth"
},
{
"path": "2014-05-08-editorial.md",
"chars": 1872,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"12\"\ndate: \"2014-05-08 12:00:00\"\ntags: editorial\n---\n\nHey everyone,\n\nThis issue is all"
},
{
"path": "2014-05-08-interactive-animations.md",
"chars": 26699,
"preview": "---\r\ntitle: \"Interactive Animations\"\r\ncategory: \"12\"\r\ndate: \"2014-05-08 06:00:00\"\r\ntags: article\r\nauthor:\r\n - name: Ch"
},
{
"path": "2014-05-08-view-layer-synergy.md",
"chars": 20692,
"preview": "---\ntitle: \"View-Layer Synergy\"\ncategory: \"12\"\ndate: \"2014-05-08 08:00:00\"\ntags: article\nauthor:\n - name: David Rönnqv"
},
{
"path": "2014-06-09-behaviors.md",
"chars": 8886,
"preview": "---\ntitle: \"Behaviors in iOS Apps\"\ncategory: \"13\"\ndate: \"2014-06-09 09:00:00\"\ntags: article\nauthor:\n - name: Krzysztof"
},
{
"path": "2014-06-09-editorial.md",
"chars": 2138,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"13\"\ndate: \"2014-06-09 12:00:00\"\ntags: editorial\n---\n\nHey all,\n\nThe very first issue o"
},
{
"path": "2014-06-09-mvvm.md",
"chars": 10538,
"preview": "---\ntitle: \"Introduction to MVVM\"\ndate: \"2014-06-09 11:00:00\"\ntags: article\ncategory: \"13\"\nauthor:\n - name: Ash Furrow\n"
},
{
"path": "2014-06-09-singletons.md",
"chars": 16453,
"preview": "---\ntitle: \"Avoiding Singleton Abuse\"\ncategory: \"13\"\ndate: \"2014-06-09 10:00:00\"\ntags: article\nauthor:\n - name: Stephe"
},
{
"path": "2014-06-09-subclassing.md",
"chars": 9089,
"preview": "---\ntitle: \"Subclassing\"\ncategory: \"13\"\ndate: \"2014-06-09 08:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n ur"
},
{
"path": "2014-06-09-viper.md",
"chars": 37627,
"preview": "---\ntitle: \"Architecting iOS Apps with VIPER\"\ncategory: \"13\"\ndate: \"2014-06-07 07:00:00\"\ntags: article\nauthor:\n - name:"
},
{
"path": "2014-07-11-appkit-for-uikit-developers.md",
"chars": 27214,
"preview": "---\ntitle: \"AppKit for UIKit Developers\"\ncategory: \"14\"\ndate: \"2014-07-11 07:00:00\"\ntags: article\nauthor:\n - name: Flo"
},
{
"path": "2014-07-11-editorial.md",
"chars": 1519,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"14\"\ndate: \"2014-07-11 12:00:00\"\ntags: editorial\n---\n\nHi all,\n\nThis month's issue is a"
},
{
"path": "2014-07-11-plugins.md",
"chars": 14867,
"preview": "---\ntitle: Plugins\ncategory: \"14\"\ndate: \"2014-07-11 09:00:00\"\nauthor:\n - name: Gus Mueller\n url: https://twitter.com"
},
{
"path": "2014-07-11-sandbox-scripting.md",
"chars": 27621,
"preview": "---\ntitle: Scripting from a Sandbox\ncategory: \"14\"\ndate: \"2014-07-11 10:00:00\"\nauthor:\n - name: Craig Hockenberry\n u"
},
{
"path": "2014-07-11-scripting-data.md",
"chars": 18196,
"preview": "---\ntitle: Making Your Mac App’s Data Scriptable\ncategory: \"14\"\ndate: \"2014-07-11 11:00:00\"\nauthor:\n - name: Brent Simm"
},
{
"path": "2014-07-11-xpc.markdown",
"chars": 27320,
"preview": "---\ntitle: \"XPC\"\ncategory: \"14\"\ndate: \"2014-07-11 08:00:00\"\ntags: article\nauthor:\n - name: Daniel Eggert\n url: http"
},
{
"path": "2014-08-11-bad-testing-practices.md",
"chars": 18430,
"preview": "---\ntitle: Bad Testing Practices\ncategory: \"15\"\ndate: \"2014-08-11 08:00:00\"\nauthor:\n - name: Luis Solano\n url: http:"
},
{
"path": "2014-08-11-behavior-driven-development.md",
"chars": 38692,
"preview": "---\ntitle: \"Behavior-Driven Development\"\ncategory: \"15\"\ndate: \"2014-08-11 11:00:00\"\nauthor:\n - name: Pawel Dudek\n u"
},
{
"path": "2014-08-11-dependency-injection.md",
"chars": 17528,
"preview": "---\ntitle: Dependency Injection\ncategory: \"15\"\ndate: \"2014-08-11 09:00:00\"\nauthor:\n - name: Jon Reid\n url: http://qu"
},
{
"path": "2014-08-11-editorial.md",
"chars": 1558,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"15\"\ndate: \"2014-08-11 12:00:00\"\ntags: editorial\n---\n\nHi all,\n\nThis month's issue is a"
},
{
"path": "2014-08-11-mocking-stubbing.md",
"chars": 14311,
"preview": "---\ntitle: \"Test Doubles: Mocks, Stubs, and More\"\ncategory: \"15\"\ndate: \"2014-08-11 07:00:00\"\nauthor:\n - name: Mike Laze"
},
{
"path": "2014-08-11-snapshot-testing.md",
"chars": 10891,
"preview": "---\ntitle: \"Snapshot Testing\"\ncategory: \"15\"\ndate: \"2014-08-11 05:00:00\"\nauthor:\n - name: Orta Therox\n url: https:/"
},
{
"path": "2014-08-11-user-interface-testing.md",
"chars": 12135,
"preview": "---\ntitle: User Interface Testing\ncategory: \"15\"\ndate: \"2014-08-11 06:00:00\"\nauthor:\n - name: Klaas Pieter Annema\n u"
},
{
"path": "2014-08-11-xctest.markdown",
"chars": 33353,
"preview": "---\ntitle: \"Real-World Testing with XCTest\"\ncategory: \"15\"\ndate: \"2014-08-11 10:00:00\"\ntags: article\nauthor:\n - name: "
},
{
"path": "2014-09-10-editorial.md",
"chars": 1988,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"16\"\ndate: \"2014-09-10 12:00:00\"\ntags: editorial\n---\n\nWelcome to objc.io issue 16!\n\nOn"
},
{
"path": "2014-09-10-functional-swift-apis.md",
"chars": 16569,
"preview": "---\ntitle: \"Functional APIs with Swift\"\ncategory: \"16\"\ndate: \"2014-09-10 08:00:00\"\ntags: article\nauthor:\n - name: Flor"
},
{
"path": "2014-09-10-power-of-swift.md",
"chars": 18243,
"preview": "---\ntitle: \"The Power of Swift\"\ncategory: \"16\"\ndate: \"2014-09-10 11:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof"
},
{
"path": "2014-09-10-rapid-prototyping-in-swift-playgrounds.md",
"chars": 17201,
"preview": "---\ntitle: \"Rapid Prototyping in Swift Playgrounds\"\ncategory: \"16\"\ndate: \"2014-09-10 07:00:00\"\nauthor:\n - name: Brad L"
},
{
"path": "2014-09-10-swift-classes-vs-structs.md",
"chars": 12114,
"preview": "---\ntitle: \"A Warm Welcome to Structs and Value Types\"\ncategory: \"16\"\ndate: \"2014-09-10 10:00:00\"\nauthor:\n - name: And"
},
{
"path": "2014-09-10-swift-functions.md",
"chars": 27630,
"preview": "---\ntitle: \"The Many Faces of Swift Functions\"\ncategory: \"16\"\ndate: \"2014-09-10 09:00:00\"\nauthor:\n - name: Natasha Mur"
},
{
"path": "2014-10-10-editorial.md",
"chars": 1475,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"17\"\ndate: \"2014-10-10 12:00:00\"\ntags: editorial\n---\n\nHi all,\n\nThis month's issue is a"
},
{
"path": "2014-10-10-inside-code-signing.md",
"chars": 24236,
"preview": "---\ntitle: Inside Code Signing\ncategory: \"17\"\ndate: \"2014-10-10 10:00:00\"\nauthor:\n - name: Thomas 'toto' Kollbach\n u"
},
{
"path": "2014-10-10-receipt-validation.md",
"chars": 32526,
"preview": "---\ntitle: \"Receipt Validation\"\ncategory: \"17\"\ndate: \"2014-10-10 09:00:00\"\nauthor:\n - name: Laurent Etiemble\n url: "
},
{
"path": "2014-10-10-why-security.md",
"chars": 10310,
"preview": "---\ntitle: Why Security Still Matters Today\ncategory: \"17\"\ndate: \"2014-10-10 11:00:00\"\nauthor:\n - name: Graham Lee\n "
},
{
"path": "2014-11-10-designing-elegant-mobile-games.md",
"chars": 13069,
"preview": "---\ntitle: \"Designing Elegant Mobile Games\"\ncategory: \"18\"\ndate: \"2014-11-10 11:00:00\"\ntags: article\nauthor:\n - name: M"
},
{
"path": "2014-11-10-editorial.md",
"chars": 1266,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"18\"\ndate: \"2014-11-10 12:00:00\"\ntags: editorial\n---\n\n \nWelcome to the first objc.io i"
},
{
"path": "2014-11-10-metal.md",
"chars": 22293,
"preview": "---\ntitle: \"Metal\"\ncategory: \"18\"\ndate: \"2014-11-10 10:00:00\"\ntags: article\nauthor:\n - name: Max Christ\n url: http:"
},
{
"path": "2014-11-10-multipeer-connectivity-for-games.md",
"chars": 15797,
"preview": "---\ntitle: \"Multipeer Connectivity in Games\"\ncategory: \"18\"\ndate: \"2014-11-10 08:00:00\"\ntags: article\nauthor:\n - name:"
},
{
"path": "2014-11-10-scenekit.md",
"chars": 14394,
"preview": "---\ntitle: \"Scene Kit\"\ncategory: \"18\"\ndate: \"2014-11-10 09:00:00\"\ntags: article\nauthor:\n - name: David Rönnqvist\n u"
},
{
"path": "2014-11-10-sound-design.md",
"chars": 30179,
"preview": "---\ntitle: \"Virtual Soundscapes: The Art of Sound Design\"\ncategory: \"18\"\ndate: \"2014-11-10 07:00:00\"\nauthor:\n - name: "
},
{
"path": "2014-12-08-activity-tracing.md",
"chars": 12762,
"preview": "---\ntitle: \"Activity Tracing\"\ncategory: \"19\"\ndate: \"2014-12-08 07:00:00\"\ntags: article\nauthor:\n - name: Florian Kugler"
},
{
"path": "2014-12-08-debugging-case-study.md",
"chars": 19568,
"preview": "---\ntitle: \"Debugging: A Case Study\"\ncategory: \"19\"\ndate: \"2014-12-08 11:00:00\"\nauthor:\n - name: Peter Steinberger\n "
},
{
"path": "2014-12-08-debugging-checklist.md",
"chars": 15481,
"preview": "---\ntitle: Debugging Checklist\ncategory: \"19\"\ndate: \"2014-12-08 09:00:00\"\ntags: article\nauthor:\n - name: Chris Eidhof\n "
},
{
"path": "2014-12-08-dtrace.markdown",
"chars": 37038,
"preview": "---\ntitle: \"DTrace\"\ncategory: \"19\"\ndate: \"2014-12-08 08:00:00\"\ntags: article\nauthor:\n - name: Daniel Eggert\n url: h"
},
{
"path": "2014-12-08-editorial.md",
"chars": 1618,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"19\"\ndate: \"2014-12-08 12:00:00\"\ntags: editorial\n---\n\n\nWelcome to objc.io issue 19: al"
},
{
"path": "2014-12-08-lldb-debugging.md",
"chars": 29342,
"preview": "---\ntitle: \"Dancing in the Debugger — A Waltz with LLDB\"\ncategory: \"19\"\ndate: \"2014-12-08 10:00:00\"\ntags: article\nautho"
},
{
"path": "2015-01-13-andy-matuschak.md",
"chars": 28299,
"preview": "---\ntitle: \"A Generation of Lifelong Learners\"\ncategory: \"20\"\ndate: \"2015-01-13 11:00:00\"\ntags: article, interview\nauth"
},
{
"path": "2015-01-13-editorial.md",
"chars": 646,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"20\"\ndate: \"2015-01-13 12:00:00\"\ntags: editorial\n---\n\nHappy New Year and welcome to ob"
},
{
"path": "2015-01-13-loren-brichter.md",
"chars": 12533,
"preview": "---\ntitle: \"Something Slightly Less Terrible\"\ncategory: \"20\"\ndate: \"2015-01-13 10:00:00\"\ntags: article, interview\nautho"
},
{
"path": "2015-01-13-natasha-murashev.md",
"chars": 11447,
"preview": "---\ntitle: \"Infinite Things to Learn\"\ncategory: \"20\"\ndate: \"2015-01-13 09:00:00\"\ntags: article, interview\nauthor:\n - n"
},
{
"path": "2015-02-10-camera-capture-on-ios.md",
"chars": 22212,
"preview": "---\ntitle: \"Camera Capture on iOS\"\ncategory: \"21\"\ndate: \"2015-02-10 09:00:00\"\ntags: article\nauthor:\n - name: Matteo Cal"
},
{
"path": "2015-02-10-core-image-intro.md",
"chars": 15279,
"preview": "---\ntitle: \"An Introduction to Core Image\"\ncategory: \"21\"\ndate: \"2015-02-10 07:00:00\"\ntags: article\nauthor:\n - name: W"
},
{
"path": "2015-02-10-editorial.md",
"chars": 2264,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"21\"\ndate: \"2015-02-10 12:00:00\"\ntags: editorial\n---\n\nWelcome to objc.io issue 21. Thi"
},
{
"path": "2015-02-10-face-recognition-with-opencv.md",
"chars": 19698,
"preview": "---\ntitle: \"Face Recognition with OpenCV\"\ncategory: \"21\"\ndate: \"2015-02-10 04:00:00\"\ntags: article\nauthor:\n - name: Eng"
},
{
"path": "2015-02-10-gpu-accelerated-image-processing.md",
"chars": 47068,
"preview": "---\ntitle: \"GPU-Accelerated Image Processing\"\ncategory: \"21\"\ndate: \"2015-02-10 06:00:00\"\nauthor:\n - name: Janie Clayton"
},
{
"path": "2015-02-10-gpu-accelerated-machine-vision.md",
"chars": 27980,
"preview": "---\ntitle: \"GPU-Accelerated Machine Vision\"\ncategory: \"21\"\ndate: \"2015-02-10 05:00:00\"\nauthor:\n - name: Brad Larson\n "
},
{
"path": "2015-02-10-how-your-camera-works.md",
"chars": 34233,
"preview": "---\ntitle: \"How Your Camera Works\"\ncategory: \"21\"\ndate: \"2015-02-10 11:00:00\"\ntags: article\nauthor:\n - name: Daniel Eg"
},
{
"path": "2015-02-10-image-formats.md",
"chars": 14950,
"preview": "---\ntitle: \"Image Formats\"\ncategory: \"21\"\ndate: \"2015-02-10 10:00:00\"\ntags: article\nauthor:\n - name: Oliver Mason\n "
},
{
"path": "2015-02-10-photo-extensions.md",
"chars": 19681,
"preview": "---\ntitle: \"Photo Extensions\"\ncategory: \"21\"\ndate: \"2015-02-10 07:30:00\"\ntags: article\nauthor:\n - name: Sam Davies\n "
},
{
"path": "2015-02-10-the-photos-framework.md",
"chars": 21876,
"preview": "---\ntitle: \"The Photos Framework\"\ncategory: \"21\"\ndate: \"2015-02-10 08:00:00\"\nauthor:\n - name: Saniul Ahmed\n url: ht"
},
{
"path": "2015-03-10-artsy.md",
"chars": 13695,
"preview": "---\ntitle: \"Artsy\"\ncategory: \"22\"\ndate: \"2015-03-10 11:00:00\"\ntags: article\nauthor:\n - name: Orta Therox\n url: http"
},
{
"path": "2015-03-10-dropbox.md",
"chars": 7733,
"preview": "---\ntitle: \"The Art of Code Review: A Dropbox Story\"\ncategory: \"22\"\ndate: \"2015-03-10 9:00:00\"\ntags: article\nauthor:\n "
},
{
"path": "2015-03-10-editorial.md",
"chars": 1145,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"22\"\ndate: \"2015-03-10 13:00:00\"\ntags: editorial\n---\n\nWelcome to issue 22 of objc.io. "
},
{
"path": "2015-03-10-facebook.md",
"chars": 15345,
"preview": "---\ntitle: \"React-Inspired Views\"\ncategory: \"22\"\ndate: \"2015-03-10 8:00:00\"\ntags: article\nauthor:\n - name: Adam Ernst\n"
},
{
"path": "2015-03-10-omni-group.md",
"chars": 13621,
"preview": "---\ntitle: \"Inside Omni\"\ncategory: \"22\"\ndate: \"2015-03-10 12:00:00\"\ntags: article\nauthor:\n - name: Brent Simmons\n u"
},
{
"path": "2015-03-10-square.md",
"chars": 19582,
"preview": "---\ntitle: \"Scaling Square Register\"\ncategory: \"22\"\ndate: \"2015-03-10 10:00:00\"\ntags: article\nauthor:\n - name: Kyle Va"
},
{
"path": "2015-04-13-capturing-video.md",
"chars": 22588,
"preview": "---\ntitle: Capturing Video on iOS\ncategory: \"23\"\ndate: \"2015-04-13 11:00:00\"\ntags: article\nauthor:\n - name: Adriaan St"
},
{
"path": "2015-04-13-core-image-video.md",
"chars": 15538,
"preview": "---\ntitle: \"Core Image and Video\"\ncategory: \"23\"\ndate: \"2015-04-13 10:00:00\"\ntags: article\nauthor:\n - name: Daniel Egg"
},
{
"path": "2015-04-13-editorial.md",
"chars": 872,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"23\"\ndate: \"2015-04-13 13:00:00\"\ntags: editorial\n---\n\nWelcome to issue 23 of objc.io. "
},
{
"path": "2015-04-13-videotoolbox.md",
"chars": 16113,
"preview": "---\ntitle: \"Video Toolbox and Hardware Acceleration\"\ncategory: \"23\"\ndate: \"2015-04-13 09:00:00\"\ntags: article\nauthor:\n "
},
{
"path": "2015-05-11-audio-api-overview.md",
"chars": 6071,
"preview": "---\ntitle: \"Audio API Overview\"\ncategory: \"24\"\ndate: \"2015-05-11 8:00:00\"\ntags: article\nauthor:\n - name: Daniel Eggert\n"
},
{
"path": "2015-05-11-audio-dog-house.md",
"chars": 96355,
"preview": "---\ntitle: \"The Audio Processing Dog House\"\ncategory: \"24\"\ndate: \"2015-05-11 11:00:00\"\ntags: article\nstylesheets: \"issu"
},
{
"path": "2015-05-11-editorial.md",
"chars": 1263,
"preview": "---\ntitle: \"Editorial\"\ncategory: \"24\"\ndate: \"2015-05-11 12:00:00\"\ntags: editorial\n---\n\nWelcome to issue 24 of objc.io. "
},
{
"path": "2015-05-11-functional-signal-processing.md",
"chars": 11842,
"preview": "---\ntitle: \"Functional Signal Processing Using Swift\"\ncategory: \"24\"\ndate: \"2015-05-11 10:00:00\"\ntags: article\nauthor:\n"
},
{
"path": "2015-05-11-sound-design.md",
"chars": 6558,
"preview": "---\ntitle: \"Play, Fail, Iterate: Sound Design for Products\"\ncategory: \"24\"\ndate: \"2015-05-11 9:00:00\"\ntags: article\naut"
},
{
"path": "README.md",
"chars": 417,
"preview": "# objc.io articles\n\nThis repository contains all available articles from [objc.io](http://www.objc.io).\n\nIf you find mis"
}
]
About this extraction
This page contains the full source code of the objcio/articles GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 150 files (2.7 MB), approximately 713.8k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.