A note on NSManagedObjectContextId

Like a lot of iOS Devs I’m used to working with my domain objects across various different threads.

As you may know, when you decide to work with an object on a different thread, you need to retrieve that object from that thread’s NSManagedObjectContext. This is normally done like so:

[myNewContext objectWithID:recordFromADifferentContext.objectID]

The record’s objectId is a universal identifier and you can find out more information from the Apple Docs on it.

However, I was recently having trouble with saving an object in one thread and then retrieving it in another thread. It was throwing an exception when I tried to use the object on the second thread.

The problem is that the initial objectId on a record is a temporary one. Therefore, when we hop onto a different thread, we can’t do a lookup on it.

The solution? Simply make the following call on your original managedObjectContext like so

[recordInFirstContext.managedObjectContext obtainPermanentIDsForObjects:@[recordInFirstContext] error:&error];

This will force the record to create a permanent objectId which can then be retrieved on another thread.

App Store Dollars Don’t Go Further

So Apple are going to start pulling apps that reward social sharing/other app promotion from the App Store.

I’m pretty disappointed to hear this since the social share for extra cash option in my app Hipster CEO was a pretty popular bit of functionality. In the game, if you levelled up you could earn extra cash by sharing your achievement on Twitter or Facebook.

However, the discussion over on Hacker News has been around the suggestion that Apple should ban consumable in-app purchases completely. This topic  seems to split the community into two camps:

  1. iOS Developers who would be unhappy to see a drop in revenue.
  2. Gamers who loath IAPs as its difficult to tell just how much a game will “really” cost them.

I have written about mobile apps’  pricing problem before but its practically impossible to make & maintain a worthwhile app where the customer lifetime value is $1.99. I’m not saying consumable IAPs are the answer – I hate games that offer me the chance to hurry actions up by paying, they just feel kinda hacky to me. I’m happy to say that Hipster CEO has no IAPs but I sure wish I put them in there. The app has made me back the money it cost to develop but it’s not paying enough for me to maintain it (note: I’m building a new version that I hope will change all that). If you paid just under two quid for a game then you really don’t deserve an experience that lasts longer than it takes to drink a beer.

If you bought a second-hand console game and never played it twice, you wouldn’t complain. If you sank five bucks into a game at the arcade in twenty minutes, you wouldn’t complain. And if you paid over a tenner for a movie that sucked then you probably wouldn’t complain. All of these things cost more than the average app but for some reason, a certain group of people feel their App Store dollars should go that bit further.

That being said, I understand the complaint. I don’t think gamers mind handing over cash – its the lack of transparency that bothers them. If an app is marketed as free/cheap but really costs $50+ to get value out of it then it feels like a bit of swindle. Games like Farmville are a perfect example. However, gamers only have themselves to blame. The only alternative I can thing of over IAPs is subscription based models – games like Ultima Online – and they’re all dying out with World of Warcraft being the exception to the rule.

Maybe there’s a better way to monetise – I don’t know. If you’ve any suggestions then leave a comment.

RMMapView not deallocating memory in iOS? This could be the problem

I’m working with Mapbox at the moment – it’s a great tool for bundling offline maps into your apps. I recently noticed that my RMMapView’s weren’t deallocating as expected. These map views used by Mapbox, I’m not sure if they’re open source or not. Anyway, long story short, this was leading to a memory leak and I spent about a day trying to figure out why. The fix is pretty simple, just remember to set the “showsUserLocation” flag to false when you destroy the parent view. Something like:

- (void)viewWillDisappear:(BOOL)animated {
    if ([self isMovingFromParentViewController]) {
        _mapView.showsUserLocation = NO;
    [super viewWillDisappear:animated];

Hope this helps save someone a lot of time someday!