Nested push animation can result in corrupted navigation bar

While updating one of my apps a while back, I suddenly started receiving a bizzare error message:

nested push animation can result in corrupted navigation bar

Like most iOS error messages, this one doesn’t really tell you anything about what the problem is or how to fix it. Nested push animation? Huh? Am I somehow calling push from within a call to push? Does ‘can result in’ really mean ‘results in’? Why should I care?

It turns out that the problem was quite simple, and was indeed my own fault. I had a segue hooked up in my storyboard… but I happened to have added some code that was manually calling pushViewController. Removing the old segue from the storyboard solved the problem.

Whoops!

The App Buying Experience

I recently attempted to purchase an app from the app store on my iPhone, and I must say, the experience was quite hilarious. Here is a rough overview of the process (from memory, so apologies if a few details are off):

  1. Tap the price
  2. Tap buy
  3. Enter my password
  4. Get prompted to enter in three security questions
  5. Tap not now
  6. Wait a while, notice that nothing is happening
  7. Tap buy
  8. Tap OK when prompted to enter in my security questions
  9. Select my questions and answers
  10. Tap ok
  11. Tap buy
  12. Get prompted to verify my credit card into
  13. Tap continue
  14. Enter in my credit card info
  15. Tap done

And there you have it – buying apps in only 15 easy steps!

I was going to make a snarky comment about how Apple should license Amazon’s one-click buying patent, but apparently they already have. Joke’s on me.

Querying Data – Core Data vs. Entity Framework

As someone coming to iOS development from a .NET background, one of the things that annoys me the most is the sheer amount of code it takes to do things that should be simple. Core Data is a perfect example of this.

Let’s say I want to retrieve the 5 most recently created widgets that have a certain type. The typical solution in Core Data looks something like this.

NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription
                               entityForName:@"Widget" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
 
NSPredicate* predicate = [NSPredicate predicateWithFormat: @"type == %@", someType];
[fetchRequest setPredicate:predicate];
 
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc]
                                    initWithKey:@"createddate" ascending:YES];
 
NSArray* sortDescriptors = [[NSArray alloc] initWithObjects: sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
 
[fetchRequest setFetchLimit:5];   
NSError* error;
NSArray* widgets = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

Aside from being obnoxiously long, this code also has zero type safety, zero refactorability, and three hardcoded strings that are only error-checked at runtime.

The equivalent code using Entity Framework and Linq would be something like this:

var widgets = context.Widgets.Where(w => w.Type == someType)
                             .OrderBy(w => w.CreatedDate)
                             .Take(5);

… with an optional call to ToList() at the end depending on whether or not you want to immediately materialize the query.

Code like this gives you type safety, refactorability, and proper intellisense support. I know which one I would rather write, read, debug, and support.

So, what’s the solution? Are there any better ways of doing this with Core Data? I’m not sure. Maybe something like Matt Gallagher’s One Line Fetch would make a good starting point. It certainly reduces the amount of code required, but it still suffers from many of the same flaws.

How about an IQueryable-like set of categories for Objective-C collections? Or some sort of magical wrapper around Core Data?

Things like that are far beyond my meager iOS development skills, but surely someone out there has done something to improve the situation, right? This can’t be as good as it gets.

iOS Pain Points – the App Review Waiting Game

My latest app was uploaded on July 9. It’s now July 19 – almost two full weeks worth of business days later – and approval is nowhere to be found. Granted, I’ve had pretty good luck so far, with most of my apps being approved in a week or so, but this is getting annoying.

What exactly am I paying $99 per year for? Forced upgrades, woefully inadequate development tools, constantly changing rules, a black-box review process? In short, why is Apple’s entire developer ecosystem so incredibly mediocore?

Am I wrong to expect better from one of the richest companies in the history of the world? Why can’t they hire a few more temps to help get through the app backlog and speed up the review times?

I believe that to a certain extent, Apple itself has caused many of these problems themselves , as the current app store rules encourage quick hacks and one-and-done applications.

As always, none of this matters, as Apple is simply not interested in the opinions of a small-time app developer. They are content to sit on their laurels and rake in their billions.

(And yes, there’s definitely a lot of bitterness in this post. Sorry.)

EDIT: Ironically, my app was approved the day after posting this. Thanks for listening, Apple!

Creating NSManagedObject Subclasses – So Handy, Yet So Strange

If you are a Core Data user, you’ll likely become intimately familiar with NSManagedObject and the Core Data model editor.

One aspect of NSManagedObject is the the creation of NSManagedObject subclasses. The only way I have found to (automatically) do this is to select your entities, then go to Editor -> Create NSManagedObjectSubclass.

Why on earth is ‘Create NSManagedObject Subclass’ a global menu item? And why is it in the ‘Editor’ menu? Whose brilliant idea was it to have a global menu item for something so incredibly specific to a particular portion of a particular screen? Why is generating code from your Core Data model so completely non-discoverable? Why isn’t there a ‘Create NSManagedObject Subclass’ button right next to the ‘Add Entity’ button?

And those are just my issues with the placement of the functionality. So aside from that, how well does it actually work?

In my limited usage so far, I would say that it’s marginally useable.

First of all, having to perform a manual process in order to keep your data model and your object model in sync is pointless. By contrast, when you edit an Entity Framework EDMX file or a LINQ to SQL DBML file, your object model classes are automatically regenerated. And hey, if you’re using EF Code-First, there’s nothing else you need to do!

Second, the code generation itself seems… inflexible. As far as I can tell, there is absolutely nothing remotely similar to .TT files in Xcode/Core Data. For those unfamiliar with the Visual Studio world, a .TT file is essentially a template that can describe, among other things, how classes are generated from a data model. You can customize a .TT file so that the generated classes look exactly like you want them to – add in validation attributes, extra fields, property change notifications, and so on. This standard functionality in EF/VS, but doesn’t seem to exist in Xcode.

In order to something similar, it appears that you need a third-party tool such as mogenerator. Now it’s great that such a tool exists, but it’s sad that it needs to exist. Customization of generated code is a pretty basic IDE feature these days, and it’s yet another area where Xcode falls short of the competition.

On another code generation note, it’s quite amusing that Xcode can’t even remember what group I previously added the NSManagedObject subclasses to, forcing me to manually select it every time I change my data model.

iOS Pain Points – The Prevalence of Magic Strings

One thing I’ve noticed while working with iOS is that magic strings seem to be quite common.
They’re in Core Data:

[NSEntityDescription insertNewObjectForEntityForName:@"Foo" inManagedObjectContext:context];

They’re in Storyboards and View Controllers:

[self.storyboard instantiateViewControllerWithIdentifier:@"SomeViewControllerIdentifier"];

They’re in Segues:

[self performSegueWithIdentifier:@"SomeSegueIdentifier" sender:self];

They’re in sorting:

NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
                                           ascending:YES];

They’re in the instantiation of table cells:

static NSString* CellIdentifier = @"Cell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Coming from the C# world of lambdas, generics, first-class enums, and strong typing, I find all of this incredibly bizzare. But hey, who needs refactorability and type safety when you can use strings!