iOS Quick Tip – “Storyboards are unavailable on iOS 4.3 and prior”

Another day, another bizzare Xcode error.

While working on my newest app, Gym Calculator, I came across a very strange problem. I had initially set my Deployment Target to iOS 4.3. since I didn’t need any fancy new iOS 6 features. However, I couldn’t build, because my project was using Storyboards, which 4.3 doesn’t support. Xcode helpfully gave me the error message

Storyboards are unavailable on iOS 4.3 and prior

Right, no problem then! I’ll just switch to iOS 5 instead. And… same error. Ok, how about a clean and rebuild? Same error. Restart Xcode? Same error.

After some frustration and head-scratching, I stumbled across a long StackOverflow question discussing the problem. The answer that worked for me – hidden in a sea of less useful answers – was C Fraire’s:

The solution that worked for me was just to delete the 
~/Library/Developer/Xcode/DerivedData directory for my project.

So in case anybody else runs into this problem, here’s your solution! (Or at least one potential solution that did the trick for me)

Xcode 4.5 and ‘file is universal (2 slices) but does not contain a(n) armv7s slice’

After firing up Xcode 4.5 for the first time, adding 4″ iPhone support to 20 Rep Squats, and attempting to run it on my device, Xcode gave me a bizzare error:

file is universal (2 slices) but does not contain a(n) armv7s slice: /Users/Marty/Desktop/Projects/20 Rep Squats/libCorePlot-CocoaTouch.a for architecture armv7s
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So, what gives?

It turns out that Xcode 4.5 adds support for the armv7s architecture, as opposed to the standard armv7 architecture. If you are using a library that has not been compiled for armv7s, and your project is set to armv7s, you will get the above error. In my case, it’s the Core Plot library that is throwing the error.

Fixing the problem is simple. You just need to remove armv7s from the list of valid architectures.

-Select your project from the Project Navigator

-Select your target from the list of targets

-Select the build settings tab

-Find the ‘Valid Architectures’ setting. It should say armv7 armv7s.

-Double-click on it to edit it, select armv7s, and press the button.

The Valid Architectures setting should now look like this:

And that’s it! Your code will now compile correctly.

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 Quick Tip – Viewing Core Data’s Generated SQL

If you are using Core Data – or any ORM or persistence framework, for that matter – it’s often handy to be able to view the generated SQL for your queries. Fortunately, Core Data makes this incredibly easy, and unlike some other ORMs, it doesn’t require crazy hacks or third party tools.

Click your project’s name in the Xcode toolbar:

Select ‘Edit Scheme’:

Go to the ‘Arguments’ tab and click the + button under ‘Arguments passed on launch’:

Enter ‘-com.apple.CoreData.SQLDebug 1’ as the argument:

Press OK, and run your app.

Notice all of the SQL statements that appear in Xcode’s output window.

Xcode 4.4 and Objective-C

Apple recently released Xcode 4.4. The list of new features is quite intriguing.

      • The compiler automatically calls @synthesize by default for unimplemented @properties.
      • For the NSArray and NSDictionary classes, support is provided for Objective-C literals.
      • Subscripting using '[ ]' syntax is supported for Objective-C container objects.
      • Compatibility with the C++11 standard is improved.
      • New static analyzer checks for common security mistakes in API and malloc usages.
      • The caller and callee for selected methods can be displayed in the Assistant Editor.
      • Code completion is enhanced with QuickHelp.
      • Scene Kit is supported with a viewer-editor for 3D document files.
      • Improved localization workflow uses base language .xib files.
      • Git supports staging of individual changes.

Leave it to Apple to introduce core language features in a point release of their IDE!

Anyway, it got me thinking about Objective-C, productivity, and John Siracusa’s comments from a few years back:

 A framework with methods like this:

NSInteger myCount = [[myDict objectForKey:@"count"] integerValue];
NSArray *myArray = [myString componentsSeparatedByString:@","];
myItem = [myArray objectAtIndex:i];

is just not going to fly in a language that (hypothetically) supports this:

myCount = myDict["count"];
myArray = myString.split(",");
myItem  = myArray[i];

Looks like John finally got his wish! And quite frankly, it’s about time. It doesn’t get much more basic than strings and arrays, and it boggles my mind that it took Apple this long to give us a non-eye-gouging syntax. Don’t get me wrong; I’m glad to have these improvements. It’s just that in my opinion, ObjC still lags far, far behind the rest of the civilized world when it comes to programmer productivity.

Over the next little while I will be taking a closer look at some of Objective-C’s productivity failures in comparison with languages like C#, Ruby, Python, and F#.

Stylish looking glossy buttons with UIButton+Glossy

You’ve all seen the standard, iOS buttons. Although functional, they are, well, plain, to put it mildly.

Perhaps you’ve even tried to make some prettier buttons in photoshop. But if you’re like me, and you have no artistic skills, this can be a challenge. Fortunately, Michael Heyeck has put together a slick little piece of code for generating stylish, glossy buttons.

It’s ridiculously easy to use, and the results look great.

Step 1 – download UIButton+Glossy.h and UIButton+Glossy.m and stick them in your project.

Step 2 – #import “UIButton+Glossy.h” in the view controller that holds your buttons.

Step 3 – style the buttons! This is done by calling the setBackgroundToGlossyRectOfColor:withhBorder:forState method. The color parameter specifies the button’s color. The withBorder parameter specifies whether or not the button should have a border, and the forState parameter is the UIControlState that the style should be applied to.

You can put this code in your view controller’s viewDidLoad method. So, given a UIButton* named button, we can style it like so:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [button setBackgroundToGlossyRectOfColor:[UIColor colorWithRed:.05 green:.65 blue:.05 alpha:1] withBorder:NO forState:UIControlStateNormal];
}

And with that, you have a stylish looking button!
A little style can go a long way into helping your app stand out from the crowd.

Download the Sample Project