Monthly Archives: June 2013

How to use Targets in Xcode

Targets are an extremely yet totally undocumented feature of Xcode. They allow you to write code once, and then build multiple “versions” of the same code base. This makes maintenance and code updates extremely easy across more than “product”.

I use those quotation marks because usually an “Xcode Project” equals a “Product” (such as one iPhone app, or one Mac app). But really it’s the Target that defines the product, and it is feasible to write code once and use it to create several “product versions” of your app, for example:

  • a Lite and a Pro version
  • an iPad and an iPhone version
  • an iPad/iPhone version and a Mac version
  • different apps altogether based on the same code family

Targets are extremely easy to use, let’s see how in Xcode 4.6:

Targets

Adding a Target

When you create a new Xcode Project, it already comes with one Target by default. You can add another one by clicking on the big blue Project Bar in the File Inspector on the left. At the bottom you’ll see a large plus sign that reads “Add a Target”. Do that and Xcode will bring up a dialogue that looks like the one when you create a new Project.

Select what you’d like to add, give it a name an identifier and hit Finish. Now you’ll have a new Target.

You’ll also have a new Group which includes all the files that came with the template you chose. So right now it’s like having two completely different apps inside one Xcode Project. That’s interesting, but you’ll probably want to share resources to make it useful.

Sharing New Resources

Try adding a new file to your Project to bring up the following dialogue:

Adding Resources to a Multi-Target Project in Xcode

Adding Resources to a Multi-Target Project in Xcode

I’m adding a simple image file here. Everything looks as usual, but notice that now you can select which Target this new resource belongs to. See how you can check multiple targets that can share a new resource – neat, huh? This is great for new resources, but what happens to the ones you already added to your project?

Sharing Existing Resources

If you already have resources in your Project (such as image files and Storyboards) and would like to make them available to your new target, click on each file in question, head over to the File Inspector in the right hand pane (it’s the left most one that looks like a piece of paper), and scroll down to Target Membership. Tick as appropriate:

Screen Shot 2013-06-29 at 10.37.44

This works well with most files, but code files (such as App Delegate and View Controllers) can’t be changed this way. In all likelihood you’ll want to share those too. You can’t add them to your new target either, as they’re greyed out if you try. What’s worse, you’ve probably spotted that after adding a new target you may end up with a second set of files – so what is a boy to do?

A tad hacky if I may say so myself, let’s go through this step by step:

  1. On your new Target, go and delete the files you don’t want (say your App Delegate and View Controller)
  2. Make sure you trash those files
  3. Now head over to your first target, and remove those files as well
  4. DO NOT trash them, just remove the references
  5. Now add those files again, this time ticking both targets

And that’s it! Now you can share files that Xcode didn’t want you to.

Building Each Target

Each Target behaves like a separate app, and you can choose which one you want to run by clicking your Project Name next to the device you’d like to run it on. In my case, it’s called TargetTest (confusingly). This will bring up a drop down of each Target you can run:

Run a Target

That’s all I know about Targets – have fun!

How to define Preprocessor Macros in Xcode

I’ve often wondered how to use those efficiently, and I’ve just found out how to do it. As always, they’re not difficult to implement – but not documented in a way that simple folk like me can understand it. Be that as it may…

Preprocessor Macros can be useful if you’d like to compile two different versions of the same Xcode Project, such as a Lite and a Pro version, or a separate iPhone and an iPad version. Rather than create separate Xcode Projects for each version, you have one project with two targets. Each target can build a different version from your code, making maintenance much simpler than having to change the same code in two projects.

How do they work?

Preprocessor Macros are directives executed by the compiler, so they’re not part of Objective C. We’ve used them many times before with the #import statement. But to stay with our Lite and Pro example: you can use a Preprocessor if/then statement to check which version is being compiled. For this, let’s define a Macro for the Pro version. Here’s how in Xcode 4.6:

Preprocessor Macros

Let’s define one

Click on your Pro Target, head over to Build Settings and search for Preprocessor Macros. You’ll see something similar to the above screenshot. You can set Macros for each build configuration. By default we have two: Debug and Release. Notice that the Debug configuration already has a Macro defined – it’s called DEBUG=1. Therefore out of the box you can already check in your code if it has been compiled with the Debug or Release configuration.

To define your own Macro, click the little plus sign next Debug (and Release) and add something specific. I’m using IS_PRO=1, but you can choose anything you like really. I don’t know if you can set values other than boolean. Make sure you set your Macro in BOTH configurations, otherwise you’ll find different results when you submit your app.

How to check them in Code

Now that your Macro is defined, you can check if it’s present in your code like so:

And that’s all there’s to it! This makes most sense with Targets which we’ll discuss next.

How to check if your app is running on an iPad or an iPhone

Here’s how we check that:

Alternatively you can check the same method for UIUserInterfaceIdiomPhone instead, which is returned when you’re on an iPhone or iPod touch.

How to hide navigation elements with swishy animations

You can hide (and show) navigation bars and toolbars from your UINavigationController with extremely funky animations, much like we see in the Photos app on iOS. In the app, when you single-tap the screen, both top and bottom toolbars disappear.

Here’s how we do that: Provided you have your view controller embedded in a UINavigationController, you can call the following methods to slide the top and bottom bars in and out:

On the same note, you can do the same (and better) with the status bar at the very top of your screen (that’s the one that contains the time and carrier).

Here you even have a choice of

  • UIStatusBarAnimationSlide
  • UIStatusBarAnimationFade
  • UIStatusBarAnimationNone

Managed Object Context arrives empty when passed via a segue in iOS 5

I’ve just found that passing an NSManagedObjectContext object via a segue in iOS 5 doesn’t work: the property remains empty.

In iOS 6 on the other hand this isn’t a problem: the context arrives just like any other property would, and as logic would dictate. Here’s code from an amended Utility Template app:

Trying to execute a Fetch Request on FlipsideViewController results in this error message:

+entityForName: could not locate an NSManagedObjectModel for entity name ‘YourEntity’

The fact that this is fixed (yet completely undocumented) means that Apple knew about this and made it work in iOS 6. Why this doesn’t work in iOS 5 is anyone’s guess.

How to find out what class an NSObject belongs to

Sometimes you find yourself having a reference to an object (say a View Controller), but you don’t know what class it belongs to. Thankfully there’s a method for this which will work with any NSObject:

In this example we’re testing if our self.navController is a UIViewController. The method returns a BOOL.

If you inherit from other classes and test for a parent class, rest assured that this does not return false positives. So if you’d test the above for being a member of NSObject, the equation would return NO.

How to define a method that takes multiple parameters

I keep forgetting how to do this… don’t ask me why, it’s not that difficult! So here’s how we define one:

Add more parameters as you please. In theory, the method name is split across these multiple descriptive parts before each parameter is defined. However in reality I find it easier to just repeat the parameter names in each section, like this:

How to list the contents of an NSURL

On the iOS simulator we have the luxury of peeking inside our virtual devices with the Finder. We can do this by heading over to the Finder, holding down Option and clicking Go. This will bring up the Library, in which you can navigate to Application Support / iPhone Simulator / 7.0 / Applications / followed by a weird string. One of those will contain your app and all its directories.

But on a real device we’re not so lucky. Has a file really been copied the way we intended it to? NSFileManager to the rescue! Here’s how to read out the contents of a directory at an NSURL:

contentsOfDirectoryAtURL returns an NSArray (of NSURLs) which you can loop through and display any way you like. If you have a file path instead, you can use contentsOfDirectoryAtPath instead.

How to display a UIImage from an NSURL

If you’re displaying images from the main iOS bundle, things are fairly straightforward:

But if you have an NSURL to your image then it’s not as easy. It took me some digging to find out that you have to convert the URL into NSData first, and then display the data:

Convoluted – but currently the only way I know how to do it.

How to copy a file from the Main Bundle into the Documents Directory in iOS

You can do this either by using paths or NSURLs. Apple recommends using NSURLs, so here’s how it works.

In this example we’re copying a file called “Amy.png” which exists in the app’s main bundle.