MKMapSnapshotter initWithOptions nullability

MKMapSnapshotter has the following constructor (within NS_ASSUME_NONNULL_BEGIN):

- (instancetype)initWithOptions:(MKMapSnapshotOptions *)options NS_DESIGNATED_INITIALIZER;

Which means an options param must be supplied. However the documentation contradicts this, stating “If you specify nil for this property, the snapshotter uses a set of default options that capture an image of the current user’s country”, thus it should be tagged nullable:

- (instancetype)initWithOptions:(nullable MKMapSnapshotOptions *)options NS_DESIGNATED_INITIALIZER;

This is odd because the MapKit API has been updated for nullability so I think maybe was skipped because it wasn’t straightforward. Using a decompiler we can see the code has problems, rather than the init being disallowed it actually exists and looks like this:

- (instancetype)init{
    return [self initWithOptions:nil];

And the initWithOptions checks for the nil param and creates an instance of MKMapSnapshotOptions (which has all the settings needed in its default states. This is actually not the correct way to implement designated initializers and initWithOptions should actually disallow null and the init should be:

- (instancetype)init{
    return [self initWithOptions:[MKMapSnapshotOptions.alloc init]];

I think the best way to resolve this is just to add init to the header and document that it will use a default MKMapSnapshotOptions and remove the nil options allowed to initWithOptions in the documentation. That is better than making init NS_UNAVAILABLE and adding nullable to initWithOptions because its what coders who understand designated inits expect.

The Reason NSFetchedResultsChangeUpdate Is so Buggy

Always wondered why NSFetchedResultsChangeUpdate is so buggy? The reason is Apple don’t actually use it in their own apps. Instead, what they do is have a UITableViewCell subclass with a custom property setter for the object where they add KVO for only the properties they are interested in updates to, e.g. ones that require updating the cell’s views. This is a pretty good optimisation if you have a complicated object that has lots of non-user properties being updated all the time, e.g. that have server info for remote objects. They don’t go as far as updating each label for each key change, they just update all the views when any of them change. They do some times use `NSObject`’s `cancelPerformSelector` to batch the updates into one UI update. And they might also cache some data, e.g. a count of relational data. They also can use KVO contexts in really interesting ways, like using the context to “group” key paths that all have the same outcome, which saves checking the key is say in a certain array of keys that require view updates.

It makes me so sad to see so many people struggle with `NSFetchedResultsChangeUpdate` and `NSFetchedResultsChangeMove` I wish more people knew to instead go the KVO route. I think it would be cool if when creating an Xcode project they had varying levels of templates. So this KVO usage could perhaps be in an advanced core data app template and the original in a novice one, along with a health warning about not using it if you have table sections or have objects with many non-user visible properties.

I put an example in this sample code. You can see in the example controller there is no longer `NSFetchedResultsChangeUpdate` being used, and also note the workaround for UITableView moveRows not working properly across sections, also something Apple do.

New Way to Override NSManagedObject Properties

There is a new, yet not very well-known way to override NSManagedObject properties without needing to manually call KVO methods willChangeValueForKey etc. This is achieved using dynamic accessors prefixed with managedObjectOriginal as follows:


@interface Department : NSManagedObject
@property (nullable, nonatomic, copy) NSString *name;


@interface Department (DynamicAccessors)
- (NSString *)managedObjectOriginal_name;
- (void)managedObjectOriginal_setName:(NSString *)newName;

@implementation Department

@dynamic name;

- (NSString *)name
    // invoke the dynamic implementation of name
    NSString *name = [self managedObjectOriginal_name];
    // your custom code
    return name;

- (void)setName:(NSString *)name
    // invoke the dynamic implementation of setName
    [self managedObjectOriginal_setName:(NSString *)name;
    // your custom code


As seen at bottom of What’s New in Core Data in macOS 10.12, iOS 10.0, tvOS 10.0, and watchOS 3.0.

Common Init for a UIViewController Subclass

When creating a UIViewController subclass, e.g. in a framework, which you require to support being created from both storyboards and code, it is useful to implement initialisation which works for both. That can be achieved with a common init routine as follows:

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        [self doCommonInit];
    return self;

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {
        [self doCommonInit];
    return self;

- (void)doCommonInit{
    // init for both storyboards and code

Note: don’t call it _doCommonInit because Apple use that name for their own common init method! Actually it’s best avoid underscore prefix in any methods, cause that’s reserved for Apple’s use.

How to change the screenshot save folder on your Mac

By default, screenshots save to the Desktop which isn’t ideal. With this terminal command you can change the folder, e.g. to the Pictures folder:

defaults write location ~/Pictures

To remove the setting and go back to the default do:

defaults delete location

To query what the current setting is do:

defaults read location

Here are all the key combos for taking screenshots:

command+shift+3 capture whole screen.

command+shift+4 capture drag to capture area.

command+shift+4 then space and click window to capture.

If you would prefer to use a simple menu bar utility for taking screenshots try my app ScreenshotMenu in the Mac App Store.

Revisiting Hackintosh

Like many others I’ve been unhappy with the lack of Mac hardware lately so thought I’d revisit the world of osx86 after many years. There seems to be many more people involved in the scene now including some excellent how-to Youtube videos even by some high profile Mac blogs and building some absolute beasts of machines. My story is I use a 2012 Mac Mini as a server and that is limited to USB 2 so was looking to upgrade, however not only is the current mini 2 years old but doesn’t have user replaceable drives or RAM so a straightforward Mini upgrade was out. Also I use a mid-2015 15″ 16GB 256GB MacBook Pro which despite all efforts to remove everything non-essential I’m running with only a few gig free, which makes working with large IPSWs painful. Furthermore because I typically have at least Xcode, Intellij, Hopper, Textmate, Transmit and Safari with at least 10 tabs open I find the 16GB memory too limiting and I in fact run most of the time with a 8GB page file which again eats into my SSD. I considered getting a new MacBook Pro with 512GB however 16GB RAM is still the max, plus I wasn’t ready to sacrifice ports or function keys. I have felt let down by Apple when I upgraded from the 6 to 6S for 3D Touch which I hardly ever use. To solve both my problems I thought I would built a high-end Hackintosh to be used both as a development machine and server, and then use a lighter travel laptop instead for casual work, perhaps a 13″ function key MBP. There are 2 things I’d have to deal with though. I tend to work a lot in coffee shops so would need to give that up and spend more time at home. Also I would need to investigate syncing large code projects between machines pre-commit, however I have an idea about that. Because a lot of my work lately has been on sync systems I think it is time to embrace a multi-device world and looking forward to the challenge.

Modern way to register NSUserDefaults

Here is a modern way to register user defaults. It uses dispatch_once to ensure the registration only happens once and performs it lazily on the first access. Keeps your defaults all on the one place. Also it is implemented as a global block in the class.

NSInteger (^countBeforeAlerting)(void) = ^NSInteger(void) {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [[NSUserDefaults standardUserDefaults] registerDefaults:@{@"CountBeforeAlerting" : @10}];
    return [[NSUserDefaults standardUserDefaults] integerForKey:@"CountBeforeAlerting"];

Where to find IOKit headers for iOS

Sometimes when compiling more sophisticated iOS projects you need the IOKit headers which were removed from the iOS SDK a few versions ago. A simple workaround is to copy them from the Mac OS SDK to the iOS SDK with these commands:

sudo cp -r /Applications/ /Applications/

Sometimes you also need OSTypes.h from libkern:

sudo cp /Applications/ /Applications/

If you still have build errors check you are building for device and not simulator.

Default behaviour of UISplitViewController collapseSecondaryViewController

The documentation for UISplitViewControllerDelegate collapseSecondaryViewController says:

When you return NO, the split view controller calls the collapseSecondaryViewController:forSplitViewController: method of the primary view controller, giving it a chance to do something with the secondary view controller’s content. Most view controllers do nothing by default but the UINavigationControllerclass responds by pushing the secondary view controller onto its navigation stack.

Similarily, for separateSecondaryViewControllerFromPrimaryViewController it says:

When you return nil from this method, the split view controller calls the primary view controller’s separateSecondaryViewControllerForSplitViewController: method, giving it a chance to designate an appropriate secondary view controller. Most view controllers do nothing by default but the UINavigationControllerclass responds by popping and returning the view controller from the top of its navigation stack.

I thought it might be interesting to try to implement this magic behaviour to help understand what is going on and thus provide a starting point for customisation.

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
    if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]] && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
        // Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return YES;
    } else {
        // push the secondary view controller onto the primary's navigation stack
        UINavigationController *nav = (UINavigationController *)primaryViewController;
        [nav pushViewController:secondaryViewController animated:NO];
        return YES;


- (nullable UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController{

    // respond by popping and returning the view controller from the top of its navigation stack
    UINavigationController *nav = (UINavigationController *)primaryViewController;
    return [nav popViewControllerAnimated:NO];


It’s strange it is possible to push the secondary navigation controller , since usually that exceptions with “Pushing a navigation controller is not supported”. Turns out within the push method it checks a private property _allowNestedNavigationControllers to allow it to pass in this case, and it must have been set by the split view controller at some point. These kind of tricks are really annoying because gives inconsistent behaviour and thus lowers developer confidence in the APIs.
It’s interesting to call: [(UINavigationController *)secondaryViewController setViewControllers:nil]; before pushing because it throws an exception that proves that nested navigation controllers are being used: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Cannot display a nested UINavigationController with zero viewControllers

I find using the plus iPhone simulator useful for testing the split controller because in portrait it is compact width but rotating to landscape it moves to regular width.

CloudPhotos – Apple CloudKit Sample

CloudPhotos : Using CloudKit with iOS is an interesting Apple sample project, last updated a year ago, I thought I would blog about some observations I had.

The table view controller uses an array of CKRecords for its data. I sort of remember Apple saying not to use CKRecord as your model class, but all I could find was this in the docs:

Customizing Records
The CKRecord class does not support any special customizations and should not be subclassed. Use this class as-is to manage data coming from or going to the server.

This doesn’t exactly say out-right don’t use as the model, but if they say don’t subclass it then to add your methods I suppose you might try to use a category. The thing is the CKRecord contains useful logic for change tracking, e.g. when modifying a property it stores the key in changedKeys. Then when you come to use a CKModifyRecordsOperation if you use the savePolicy save changed keys then it optimises by only sending those keys that were changed (I think). I suppose the issue here is this is a lot of useful behaviour you wouldn’t want to re-implement yourself in your own model class, so you do in fact want to be using CKRecord as your model class for things that will be sent back to the server. So why Apple say not to subclass it is a bit of a mystery. Anyway once you start to implement a local cache, or would like to make use of core data fetch controller and sorting, you likely will be using NSManagedObjects as your model classes. The CKRecord encodeSystemFields does not include the changedKeys array, I suppose what you can do is track the changed keys yourself on the managed object, and then when you come to transmit the record only set the keys that you want to be sent, and then CKRecord probably won’t mind it is missing the other information.

APLCloudManager is actually a controller, and is init from the app delegate. It sort of the MVC-N design (amazing video well worth the watch), where all network code is inside one controller and not in the view controllers. I say sort of because you are supposed to only manipulate the model inside here, and then model should notify the view controller new data is available, in Apples case their model is in their view controller and is updated via the completionHandler. It’s funny because in the video he says some people choose controller (who disagree controller should only be used in view controllers), and some use manager and right here is a manager example! So in this class we see all the methods for doing cloud network calls. At first I thought the saveRecord was strange because it looks like a direct wrapper around CKDatabase’s saveRecord. However it also has a dispatch back to main queue with in. This is cool because it means the UI view controller callbacks don’t need to worry at all about threading! Perhaps a good design tip to make use of. Maybe they should have at least named it savePhotoRecord though? That’s the only thing its used for. I suppose keeping it generic is ok, given the record itself is what contains the type. Actually one of the weirder things about CloudKit is in one batch you can save records of all different types in one batch, whereas CRUD API consumers would usually be saving one record type to each end point which would need multiple requests.

Again on this manager class, all the methods are void returns, meaning unfortunately there is no cancellation capability. I think Apple should have included cancellation on at least one of them to show people how it is done. Basically I think the method could return the NSOperation (wouldn’t work with convenience methods, would always need full operations) or a protocol (to hide that scary class from UI devs), then that has the cancel method. So for example if trying to refresh a table, then the user moves away, in the view will disappear the request could be cancelled.

The subscribe method in the manager is a particularly nasty one, no completion handler on it. It’s called from the main view controller’s viewDidLoad so if it fails then the user carries on none-the-wiser. Inside the method it does look for a not authenticated error, in which case it keeps retrying every 3 seconds. At this point I noticed the operation’s qualityOfService was not set to user interactive. This means it operates in the NSURLSession discretionary mode where it does fail with network errors and just keeps retrying on its own. I just wonder is this enough to mean that you don’t need any error handling at all? Hence why they didn’t even bother with a completion handler? Will need to look more into that. I think tho at least the user could have none not to leave the app until the subscription had been set up. I was thinking this kind of initialisation feature of checking for account/creating zones/creating subscriptions might be best done in an on-boarding UI screen. You know the kind that is like a welcome screen where there is some info, maybe a spinner while things are being set up then a button? The Apple News app has this on first launch.

In the APLMainTableViewController I’m dissapointed that upon a pull-to-refresh it calls loadPhotos which does a full download of all the photos again, and then it does a full table reload. Ideally we would want to download the changes and then insert/update records. Then we realise they are using the public database which doesn’t support the fetch changes feature, so now we know why they are doing a full download. They still however could have done the table delta updates, but maybe that was too much code for this intro to CloudKit.

Finally I’d like to make a general comment on this old project and why perhaps it is no longer a good beginner sample. CloudKit is all about privacy, so sharing photos to a public database does seem to conflict with that just a bit. In iOS 10 they added CKShare and secure sharing capabilities between friends, it would be great to see a photo sharing sample that uses that instead. I think most people that are struggling with CloudKit are trying to do caching or synchronisation, this sample doesn’t touch on that at all. Maybe there are other Apple CloudKit samples I haven’t discovered yet, but on my wish list would definitely be a proper sharing one, and a sync one (with silent notifications).