Category Archives: Xcode4

2012: Using OpenGL on iPhone/iPad, and Apple’s GLKit

Apple launched a library – GLKit – that makes iPhones handle OpenGL properly.

Most of the people writing tutorials on the web don’t know how to use it, and so they ignore it. The few tutorials I found that mentioned GLKit were written by people who clearly didn’t read the docs, and they did some silly stuff (like re-writing texture-loading from scratch, when it’s a 2-line method call in GLKit. Apple has already done the hard work for you! Doh!)

After reading the docs (!) and a bunch of trial and error, we got it working quite nicely – and it’s a big time-saver in several areas, while sticking to standard OpenGL. Nice!

Things you need to know about GLKit

  1. Only works in iOS 5 and later
  2. Works on all hardware (assuming the hardware can run iOS 5 or later)
  3. OpenGL ES 1.1 has been removed/ignored; you can still use ES 1.1 features, via a simple compatibility layer – which isn’t documented (but we worked it out in the end)
  4. Apple provides a full Vector and Matrix library – all the core methods (cross-product, normalization, etc) are implemented for you
    • Apple’s classes appear to work fine. Please don’t re-implement your own cross-product just to prove you can get it subtly wrong 🙂
    • NB: if you use Apple’s Vector and Matrix classes, your code will be automatically compatible with everyone else on iOS who does so. This would be a good thing…
  5. Texture loading is massively simplified – just 1 method call to load arbitrary Image files as textures, and a couple of properties to set if you want to configure them
  6. Apple has finally deleted their HORRIBLY broken Xcode template for OpenGL projects (the one with the coloured square), and replaced it with one that works correctly (and is configured correctly)
    • The iOS 3 and iOS 4 Xcode templates would disable 3D by default, for no apparent reason (depth buffer disabled). Not a good template to start from!
    • … and they used a strange-shaped rectangle on screen – but stretched it to look like a square, and claimed it was a “square” … because the person at Apple who wrote the project had a major bug they didn’t understand, and just hid it under the carpet (instead of fixing it)

Creating an ultra-simple OpenGL app using Xcode 4 and GLKit

Out of the box, Apple’s templates for Xcode 4 do NOT include a basic OpenGL project. Instead, you have a good quality project that’s customized to do OpenGL ES 2 shaders.

That’s great, but a huge amount of the code out there is pre-shader, and if you just want to update / port your iOS 3 apps – or if you don’t need shaders right now – you need to delete a big chunk out of the template. And you have to add back in a couple of small items that got left out.

…I was planning to include a sample project here, cut-down from Apple’s template, but Apple broke their templating system in Xcode 4 (removed lots of features that many developers made use of. No explanation given, no alternatives provided). Given how few people are using non-shaders / GL ES 1.1, I’m not sure it’s worth finishing and posting here.

If you *really* need / want it, please post in the comments, and I’ll dig it out and see how much I can make it work with current/latest Xcode (currently: 4.5 / 4.6)

box2D for iOS made easy: make it a static library

http://box2d.org/ is a wonderful, FREE!, physics library. Without it, we probably wouldn’t have the likes of Angry Birds (since Angry Birds was built on-top of it).

But … it’s a C++ library, and the official version doesn’t play nice with iOS (iPhone/iPad). You can include the full source into your project, but then you (might) run into Apple’s bugs where C++ sometimes fails to compile correctly in Xcode. And … you get several Warnings for the box2D source, where it doesn’t quite meet Xcode’s expectations. Most teams work on a “zero warnings allowed” basis, forcing you to branch the project :(.

Solution: convert box2D into a static library!

Please note: This tutorial is the MINIMUM steps we found that workaround the Xcode bugs. They SHOULD work for all other C++ libraries too – this is a more careful, cautious approach than the “standard” way you create static libraries.

But … if you see an unecessary step, or mistake, please add a comment to this post and I’ll look into it.

1. Create a new Xcode Project

When we’re done, you’ll have two items (a file and a folder) which you can drag/drop into any xcode project, and they will Just Work ™ – every time, with no code changes needed.

To start with, create a new Xcode project, and choose a type of: “Cocoa Touch Static Library”

2. Add the Box2D source

This is where it gets slightly tricky: we are going to workaround a major bug in Xcode, and a minor nuisance in the way box2D’s source code is written.

NB: box2d’s source is correct – it’s following the standards – it’s Apple that is wrong here. But … many library authors have given up, and just follow Apple’s “customized” version of the standards, because it makes life easier.

i. Download the source

First, download the box2d source code (if it’s not there, use the links from box2d.org to find it)

ii. Find the correct set of files

Inside the zip file, you’ll find a lot of stuff:

…you want the Box2D sub-folder from the above screenshot. Copy the whole thing somewhere on your hard disk (you don’t want to change the original).

iii. Duplicate the headers

This step is critical: most libraries don’t need this, but we have to workaround a bug in Xcode

  1. Create two new folders: “src” and “headers”
  2. Copy/paste the Box2D folder into “headers”, and move the original into “src” – yes, you really DO need two copies of the source!
  3. Move both folders (“src” and “headers”) into the folder where your new Xcode project lives. DO NOT ADD THEM TO YOUR PROJECT.

Finally … open the “headers” copy of Box2D in Finder … and “move to trash” every single file that is NOT a “.h” file.

NB: you *will* end up with two copies of every header file – one in the “headers” folder, and one in the “src” folder. That sounds strange, but it’s how we force Xcode to do what it’s supposed to do.

iv. Add to project

This step is critical: most libraries don’t need this, but we have to workaround a bug in Xcode

  1. Drag/drop the “src” folder into your project
    1. CRITICAL: “Create groups for any added folders” MUST be checked
  2. Drag/drop the second Box2D folder (the one inside “headers” into your project
    1. CRITICAL: “Create folder references for any added folders” MUST be checked

When you’re finished, it MUST look like this. If not – you did it wrong, and YOUR LIBRARY WILL NOT WORK

Note that the copy from “headers” has all the folders coloured blue, whereas the copy from “src” has all the folders coloured yellow. That is very important…

3. Fix the headers (part 2)

We’ve duplicated the headers, and added them to the project.

But now we have to workaround ANOTHER bug in Xcode – one that is fatal to the box2D project.

Also … by default, Xcode does NOT make headers available to other projects. This is a bad “default” behaviour of Xcode – Xcode knows we’re making a static library, so it’s pretty obvious we’d want people to use it!

First, remove Xcode’s buggy, incorrect header-export:

  1. Open the build-settings for your new library project
  2. Select the “Build Phases” tab
  3. Open the “Copy Headers” phase
  4. …and delete all the headers in there

Next, add the headers CORRECTLY, and make them PUBLIC:

  1. Drag/drop the blue “Box2D” folder from the Project Navigator into the Public section
  2. …NB: you *must* drag the blue folder
  3. …NB: you *must* drag it – if you use the small “+” button, that is for adding headers, XCODE WILL NOT DO WHAT YOU TOLD IT TO (bug).

When you’re done, you should have exactly this:

5. Make the library “universal”

For Xcode 4.0, Apple removed a *critical* feature – their build notes said it was too confusing for developers, so they simply removed it. I think it’s more likely they decided they didn’t have time to fix all the bugs in their implementation (there were quite a few)…

Anyway, we’re going to add the feature back in.

Using this StackOverflow question and answer, convert your library from “Simulator only” / “Device only”, into a library that works on both simulators AND on devices, all in one file.

Briefly:

  1. In the Build Settings page you already have open in Xcode, click “Add Build Phase -> Run Script Phase” at bottom right
  2. Copy/paste the script from StackOverflow into the script area.

Easy!

6. Build, and add to your game / app project

Hit Build, and you get a library.

However, there’s ANOTHER bug in Xcode: it will “hide” the library somewhere semi-random on your hard disk. The StackOverflow answer has step-by-step instructions for finding it (hint: look in the Build Results window in Xcode, and the script prints the location to screen, so you can find it, because Xcode hides it from you).

Now drag/drop the file (e.g. “libBox2dStatic.a”, if you called your box2d project “Box2DStatic”) into your main app project.

In Finder, in the same folder where you found the “.a” file, you’ll see a folder “usr” – also drag/drop this one into your project. (it contains all the header files that Box2D needs)

7. Configure your project to find the header files

By default, Xcode ignores incoming header files. This is poor interface design from Apple – most IDE’s would have asked you “are you adding these files to your project – or are they part of a library that you’re importing?” – but it means we have to manually tell Xcode that we just added library headers.

  1. IN YOUR MAIN GAME/APP: go to the Build Settings page
  2. Select the TARGET you’re building (not the PROJECT), and select “Build Settings” tab
  3. in the search box, type “header”
  4. Edit the “Header Search Paths” line, and add an entry (if its not there already): “$(SRCROOT)”
  5. Hit Enter/Return key (Xcode will often delete the new entry if you don’t do this!)
  6. Check the little tickbox to the left of the new entry – this is REQUIRED

When you’re done, double-click the “Header Search Paths” and check your entry is there (c.f. note above, about how Xcode often deletes new entries for no apparent reason). It should look like this:

(NB: the libxml2 line in the screenshot probably isn’t needed in your project – in this example, I used a project that already had some Header Search Paths)

8. Import Box2D, and start coding…

YOU MUST NOT #import BOX2D – it doesn’t support that usage. Instead, you must #include it – and you MUST use angle-brackets.

Here’s an example – note how the “#import” for Foundation is an import, but the Box2D is an include:

Finally: since box2d is written in C++, you MUST make your source file into Objective-C++. This is very easy – all you have to do is rename it from “.m” to “.mm”.

(if that doesn’t work, you can open the right-hand panel in Xcode, and in the “Identity and Type” section, set the File Type setting to “C++ Source File”)

A very nasty bug in Apple’s compiler?

Just ran into this recently. Took a while to work this out – it seems to be a bug in Apple’s compiler (either that, or I massively misunderstand the scoping rules Apple is using). I didn’t try analysing the assembler output – I didn’t have time, this was for a project that had to ship yesterday!

(this is on the Apple LLVM 3.1 compiler – as shipped with latest/current Xcode)

In this code:

{
NSArray* a = ...get array...

if( something that is true )
{
NSString* p = [a objectAtIndex:0];

// 1. What is "p" at this point?

NSLog( @"%@", [p uppercaseString] );

// 2. What is "p" at this point?

NSLog( @"%@", [p uppercaseString] );

}

UIViewController* p = self.presentingViewController;
}

…it turned out that “p” was simultaneously both variables, with both values (which I thought would be impossible, code-wise: they are defined in non-overlapping scopes). Even more strangely (c.f. below) … Apple seemd to flip-flop between which of the two variables it used at each moment.

Stepping through with the debugger, 2 lines (and one scope!) before the second “p” variable was even declared, it already existed *and already had been defined*.

Maybe this is an obscure piece of Objective-C lore, but it looks to me like a major violation of C rules (hence: I think it’s a pre-emptive performance optimization gone wrong).

NB: the first call to

[s uppercaseString]

worked fine. The second call crashed repeatedly complaining that UIViewController doesn’t conform to selector uppercaseString. It seems that at points “1.” and “2.” the dereferencing of “p” pointed first to the String pointer, and second to the UIVC pointer.

NB: the braces above are exactly as in the source.

Solution

Rename either of the variables and – unsurprisingly – things work as expected. It was a quick “fix” – but worrying that it was needed.

I have almost zero knowledge of the internals of modern C compilers – so if the above behaviour is actually correct, and my understanding is wrong, I’d love it if someone can point to an explanation for this.

Apple’s C compiler (LLVM) doesn’t set float to 0.0 – why not?

With this piece of code, what gets output?

float aFloat;
NSLog(@"Default value of a float is zero, right? A float = %.3f", aFloat );

(Hint: USUALLY, you’ll get “0.000”. But not always… )

A common expectation

Apple’s C compiler doesn’t always initialize float’s as you might expect.

The C standard has two different aspects to float initialization. One version will set floats to 0.0 *always*. The other version … will set them to random mem contents – which on iOS, for instance, is normaly but not always … 0.0.

(and the C++ equivalent is, of course, more complicated still … depends on the surrounding context of your variables, e.g. are they in a class? how’s that class getting constructed? etc)

e.g. I had to fix the following code, which was running fine 9 times in 10, but crashing/asserting occasionally:

float infitesimal; // In almost all languages, this = 0.0;
float smallPositiveFloat = 0.0001;

infitesimal += smallPositiveFloat;

NSAssert( infitesimal > 0.0, @"Not with Apple's LLVM version 3, it ain't (sometimes) ..." );

Apple should fix this anyway…

UPDATE: As pointed out by Nathan, Build won’t hilight this, but the Static Analyzer *will* (by default). This is great, but like many devs, currently we only use Xcode’s “Analyze…” every few days (and/or the weekly build) – it’s too slow to do “every” build, and it errors on things that you’re forced to do (e.g. it doesn’t understand asynch callbacks, e.g. it doesn’t like dead code that’s sometimes needed to workaround the Xcode debugger).

It doesn’t surprise me that Apple has left their C mode compiling this – it’s slightly annoying, but technically correct, and following standards is a very good thing.

But the question begs: why doesn’t Xcode flag this as a WARNING by default? That would still be standards compliant, and yet reduce the bugginess of many iOS apps.

(I find it very hard to think of real situations today where an iOS or OSX app would actually want to use a float uninitialized – meanwhile, it’s begging for data corruption bugs, security holes, etc)

In the meantime, of course … whenever you see “float something;” without an ” = 0.0;” on the end … well, you know what to do.

A general problem with Objective C

A brief note on the general case: this isn’t just about floats.

The above behaviour is often removed from modern languages – or is reduced in extent (originally I wrote: doesn’t happen in C++. As James points out below, it does happen in C++, my mistake – although I’d still argue it happens less easily / accidentally). The tiny, rare benefit is outweighed by the large, common loss.

Unfortunately, since ObjectiveC is defined as an extension of C … we’re stuck with it.

Ironically, Apple’s choice of Obj-C (rather than – say – Obj-C++) sometimes has the unwanted effect of pushing programmers back to the dark ages, to the days when “the x-y position indicator” was still just a research project.

(Apple brought out their first consumer desktop with a mouse in 1984. C++ launched in 1983 … )

Handling crashes and NSAssert gracefully in a Production App

NSAssert? What? Why? (skip if you’re familiar with this)

During development, it’s standard “best practice” to us NSAssert liberally, alerting you early if you have unexpected bugs in your code, for instance:

-(NSString*) processItem:(int) index
{
	NSAssert( index < [myArray count], @"Index is bigger than number of items in the myArray array" );
	...
	... // rest of the method goes here
}

Unit Tests are an even better approach, but there are situations – e.g. complex algorithms – where you want to perform sanity-checks in the middle of code.

NSAssert in Xcode (Apple’s default setup for new projects)

Apple has hooked up NSAssert so that in Debug builds (by default: anything on the simulator or on the device using Development mode) it stops your app, and immediately tells you what’s gone wrong.

When you do a Release build (by default: anything you send out as Ad-Hoc, or to the Apple App Store), Apple automatically replaces your NSAssert calls with blank lines – nothing happens. Otherwise your app would crash in many situations where it’s probably OK to keep running.

But that means you lose this info that could be very valuable in discovering if your app has stopped working, and how/why – e.g. if Apple changed something in an iOS update that now breaks your app.

Ideally, we want to do something different for Release builds.

NSAssertionHandler to the rescue

In older platforms, you often had to manually do a #define to change the assert() function to something different, in different builds. That was midly annoying – complex macros are slightly harder to maintain than straight code – and not very configurable.

Fortunately, Apple uses an OOP approach via NSAssertionHandler. You can implement *multiple* subclasses of NSAssertionHandler, and switch between them at runtime.

First, create a subclass of NSAssertionHandler:

@implementation AssertionHandlerLogAll

-(void)handleFailureInFunction:(NSString *)functionName file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...
{
	NSLog(@"[%@] Assertion failure: FUNCTION = (%@) in file = (%@) lineNumber = %i", [self class], functionName, fileName, line );
}

-(void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format, ...
{
	NSLog(@"[%@] Assertion failure: METHOD = (%@) for object = (%@) in file = (%@) lineNumber = %i", [self class], NSStringFromSelector(selector), object, fileName, line );
}

@end

…then, in your AppDelegate class (whichever class implements “NSObject ” ):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
	// Override point for customization after application launch.
	NSLog(@"[%@] Setting a custom assertion handler", [self class] );
	NSAssertionHandler* customAssertionHandler = [[AssertionHandlerLogAll alloc] init];
	[[[NSThread currentThread] threadDictionary] setValue:customAssertionHandler forKey:NSAssertionHandlerKey];
	...
	// NB: your windowing code goes here - e.g. self.window.rootViewController = self.viewController;
}

Assertions – upload to Flurry, perhaps?

But why limit yourself to just one assertion handler?

If you’re using Flurry (or Google Analytics etc), why not automatically log + upload each assertion to Flurry, and have them show up in your Dashboard? That way, you can see if ANY assertions are firing – but also get a count of:

  1. how many
  2. which hardware (is this only happening on an iPhone 3GS, for instance?)
  3. which iOS version (perhaps it’s due to a bug in iOS v 4.2, but not in iOS 4.3?)

Something like this:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
	// Override point for customization after application launch.
	/** start Flurry  */
	[FlurryAPI startSession:@"whatever your private Flurry Key is"];
	
	NSLog(@"[%@] Setting a custom assertion handler", [self class] );
	NSAssertionHandler* customAssertionHandler = [[AssertionHandlerSendToFlurry alloc] init];
	[[[NSThread currentThread] threadDictionary] setValue:customAssertionHandler forKey:NSAssertionHandlerKey];
	...
	// NB: your windowing code goes here - e.g. self.window.rootViewController = self.viewController;
}

Xcode4: A script that creates / adds files to your project

This ought to be easy: it is the single most common function that a build system has to do.

So it’s rather depressing that Apple doesn’t support it. Every other build system (and IDE) I’ve ever used supports it out of the box. Apple for some unknown reason has designed Xcode4 to make this difficult. Strange.

The ultimate “fix” is just one line of code – but it’s a line of code that many people are afraid to write, because it seems like it would be fragile, and feels like it MUST be wrong. Most of this post is explaining why, in fact, it’s correct – and walking you through the other things we attempted before settling on this fix.

How you’d expect it to work

We’d expect: Step 1 – Add a “Run Script” phase

Aplpe has a simple process for adding scripts. Their script-management is very weak (it’s not been updated to modern standards in a long time), so you only have one option:

  1. Select the project itself, inside the project (it’s the thing with the blue icon)
  2. In the main window, select the target you’re building
  3. Click the Build Phases tab
  4. Hidden in the extreme bottom right corner of the screen (by a bad UI designer) is a button “Add Build Phase”, that lets you add a “Run Script” phas

OK, done. Wait … it’s asking us for “input files” and “output files”. What does that mean?

Well, whatever you were expecting is probably wrong: remember, this is a very weak build-system. It’s actually asking you:

  1. Every file you intend to read from, please tell me in advance, so I can cache your output if those files haven’t changed
  2. Every file you intend to write to, please tell me in advance, so I can cache the BUILD if your output hasn’t changed

(all modern build systems do the second feature automatically, and good ones have also been doing the first one automatically for over a decade)

Fine, so you fill those in. NB: even though you should be able to select input files from a Finder interface, Apple has disabled the Finder on this GUI, so you have to type them fully by hand.

What happens: The script runs, but the files vanish

If you use some debugging in your script, you can prove its run, by looking at the build log.

But the output files are NOT included in the build (even though we told Apple each file, by name).

Hmm. Well, maybe we need to use the only other option Apple provides us:

We’d expect: Step 2 – Add a “Copy Files” phase?

Actually, this should be automatic; we just told Xcode exactly what files we were creating, and where we were creating them.

But some badly-written build-systems are so dumb that you have to tell them what you’ve already told them. So, when step 1 above doesn’t work, we try step 2.

  1. Add a “Copy files” phase immediately after the “Run Script” phase
  2. Type in the name(s) of the file(s) generated in the “Run Script” phase
  3. …FAIL! Xcode4 is hardcoded to prevent you doing this

Yes, really. The “Add” button is grayed-out if you attempt to do this. Apple doesn’t want you to do it.

There is literally no way to take the output of a script and include it in your app.

Solving the problem with Xcode4

Instead, you have to write *into your script* the parts of Apple’s build system that they have barred you from accessing. Obviously, Apple is using “copy the output of a script” to take your compiled files and put the output into the app – but they won’t let you do that.

Here’s where it gets tricky: Apple’s documentation for Xcode4 is so misleading that I’d call it “incorrect”: it tells you to use the Copy Files phase described above (which we already know is impossible), and if you go digging in their build-system docs, it gives you various other places it suggests you manually copy your output files to.

But they don’t work, either because they’re missing key elements, or because Xcode4 ignores their content when making the build.

Pre-Solution: edit your attempts at Steps 1 and 2 above

Firstly, since Apple is ignoring the “output files” that we so carefully specified, and their docs say they will just re-run the script every time if the output files are blank … remove all your “output files” and “input files”. It’s the only safe way forwards – otherwise you’ll have to hand-maintain this error-prone dialog box forever.

Secondly, delete the Copy Files phase – Apple won’t let you use it. Give up, and move on.

Solution: Manually “insert” files into the final MyApplication.app file

I tried everything, and scoured the Apple docs, the Apple developer guides, StackOverflow, and Google. I found two things that worked: an easy one that requires some typing, and an extremely long-winded and difficult one that hacks Xcode’s GUI to force it to do what it was supposed to in the first place.

Too much effort, too much to go wrong – and too hard to maintain. Instead, I went for the quick and easy method. Fortunately, there’s a pair of poorly documented Apple build-variables that together makes this easy and (almost) idiot-proof. At least, they do if you know they exist, and once you’ve guessed what they actually do (as opposed to what the docs suggest).

Add the following to the very end of your script (or get your tool:

cp ${DERIVED_FILE_DIR}/[YOUR OUTPUT FILES] ${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}

…or just write your script so that it writes output directly to:

${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}

If you use script debugging, you’ll find that this deposits things directly inside the MyApplication.app file – and it works fine.

Regular Expressions Helper

NOTE: if you came here from an external site, you probably want the Regular Expressions Helper download/support page instead. Annoyingly, some Mac sites are direct-linking to this page, incorrectly

I tried some of the standard OS X apps for doing regexp, and they are all either too expensive, or massively over-featured. Or just far too difficult to understand.

I’ve integrated regexp behind the scenes in several iPhone apps, and I’m pretty confident using the libs. So, this seemed like a good excuse to make a first native OS X app.

Now available on the Mac App Store (http://www.apple.com/mac/app-store/?id=429461864)

Current features:

  1. The text you want to change can either be a file (drag/drop to the app), or text (copy/paste into the box)
  2. While you type your regexp, the app constantly updates the output to show you what would happen (great for checking you’ve got the regexp syntax you intended)
  3. When you’re done, select the output box and copy/paste the results to wherever you need them