Xcode Open Quickly – Efficiently Navigating Xcode

This post is a simple but powerful tip. If you’re not using Xcode’s Open Quickly, today’s post should help you dramatically improve your efficiency when navigating code. When I showed Open Quickly to a colleague for the first time, their response was “that’s a game changer!”

Accessing Open Quickly

There are two ways to access Open Quickly:

  1. Menu: File > Open Quickly
  2. Keyboard shortcut: Command + Shift + O (⇧⌘O)
Xcode Open Quickly

Great. What does it do?

Once you have the Open Quickly dialog open you may use it to search and open files or symbols. A symbol can include a variable, enum, type, constant, method, or class. The search uses a fuzzy match. This means you can search for files and symbols even if you only remember a few of its characters. For example, if I have a function called  updateBottomLayoutConstraintWithNotification: I could just enter ‘upblaconnotif’:

Xcode Open Quickly Fuzzy

Open Quickly provides a list of matching files and symbols. For each match, you’re given the matches type (in the example M for Method). The full filename or symbol is also displayed along with its location in your workspace. Remember that the search is fuzzy, so you can add as many or as little characters as you like. Finally, the search is case insensitive.

OK, how do I Open a File?

You can use the arrow keys to navigate through the list of matches, then kit the enter key. Double-clicking the desired match will also open it. Holding the Option key when opening the match will open it in the Assistant Editor. Holding Option-Shift will allow you to choose where the match is opened.

Searching for a Specific File Type

To search for a specific file type, add a dot to your search and the file extension you want:

Xcode Open Quickly File Extension

Search for a Line Number

A line number can be specified too. This can be particularly useful when you want to direct a colleague to the exact location of some code. It’s also great for finding the exact location of a crash from a crash report:

Xcode Open Quickly Line Number

Type in your search text and add a colon with the line number your’e interested in.

Apple’s documentation on Open Quickly can be found here.

Auto Layout when the Keyboard is Shown and Hidden

When I first started using Auto Layout, I found it particularly frustrating that previously simple layouts seemed so much harder to implement. So now I find it especially rewarding when Auto Layout makes previously difficult or tedious layouts trivial. One such example is responding to the appearance of the system keyboard. In this article I’ll show you a simple approach for adjusting layout in response to the system keyboard as Apple recommends:

When asked to display the keyboard, the system slides it in from the bottom of the screen and positions it over your app’s content. Because it is placed on top of your content, it is possible for the keyboard to be placed on top of the text object that the user wanted to edit. When this happens, you must adjust your content so that the target object remains visible.

Auto Layout and the Keyboard

To demonstrate this I’ve made a simple app that shows a picture and a text field. The text field contains the editable name of the picture.

Auto Layout Keyboard HiddenWhen the keyboard is displayed the view’s layout should look like this:

Auto Layout Keyboard Shown

Auto Layout – Constraints

There’s several important aspects for this layout:

  • The image should always maintain its original aspect
  • There is always a minimum 8 point vertical space between the image and the text field
  • There is always a minimum 10 point vertical space between the text field and the keyboard

Additionally we want to animate the view’s layout changes when the keyboard is shown and hidden. So to get started we need to add a  UIImageView:

Auto Layout Keyboard IB

Then set its contentMode  to ScaleAspectFit

Auto Layout Keyboard Image View

Pin the left, top, and right to its superview’s margins:

Auto Layout Keyboard Image View Constraints

To finish the views we add a UITextField  and a hidden UIView. The hidden UIView is a space view. It allows us to specify a constant padding between either the bottom of the view or the top of the keyboard:

Auto Layout Keyboard Text Field

For the UITextField  we pin its top, 8 points to the bottom of the  UIImageView. Its left and right are pinned to its superview’s margins. It’s bottom is pinned to the spacer view’s top. Finally we give it a constant height of 50 points:

Auto Layout Keyboard Text Field Constraints

The final constraints required are for the spacer view. We don’t care about the width so we just pin its left and right to its superview’s margins. Its bottom is pinned to the bottom layout guide. Its height is 10 points which ensures the padding we require.

Auto Layout Keyboard Spacer View Constraints

At this point we’ve set up our views and all their required constraints. Looking at Preview in the Assistant Editor our layout looks good on both a 3.5 inch display and a 5.5 inch display:

Auto Layout Keyboard Preview

Auto Layout – Animating

We’ve achieved a layout that is correctly adjusting to devices with different widths and heights. This is great, because all we need to do now is adjust the space between the spacer view and the bottom layout guide. This is done by adjusting the constant property on the corresponding NSLayoutConstraint.

Adjusting the constant value will be done in code in response to the keyboard being shown or hidden. First the constraint needs to be connected from the storyboard to our UIViewController  subclass. This is done by control clicking and then dragging from the constraint between the spacer view and the bottom layout guide:

Auto Layout Keyboard Wiring Up

Now we’re ready to write the code required to make everything functional. In order to respond to the keyboard being shown and hidden, we need to listen for the appropriate UINotification objects. We add observers in viewWillAppear and remove them in viewWillDisappear. This ensures we start observing once the view appears and stop once it disappears:

Next, we implement the functions that the notifications will call. These are simple functions that simply re-route to a function that will handle the layout update for us:

The NSNotification object contains useful data about how the keyboard will be displayed. We’re interested in the keyboard’s animation duration and its animation curve. This data tells us how we should animate our layout changes. The notification also contains the frame that this keyboard will have at the end of the animation. Pulling these constants out is mostly straightforward.

However, the  animationCurve requires us to jump through some hoops. In order to animate the change to the constraint’s constant, we’ll be using the class method  animateWithDuration:delay:options:animations:completion: on UIView. In order to specify the animation curve we pass in a  UIViewAnimationOptions value to this method. This is a mask of options as defined in  UIViewAnimationOptions. In particular the values for animation curves must be shifted to the left by 16 bits. Once we have the shifted value for the animation curve, we then use the fromRaw function onUIViewAnimationOptions struct to get the value we need.

To accommodate the space where the keyboard will be, we need to adjust our bottomLayoutConstraint’s constant. Effectively we want the constant to be 0 when the keyboard is not visible. When the keyboard is visible we want the constant to reflect the space from the bottom of our view to the top of the keyboard. To calculate the constant we just need  CGRectGetMaxY(view.bounds) - CGRectGetMinY(convertedKeyboardEndFrame). After updating the constraint’s constant, the final step is to animate the layout change.

That’s it! Apart from some boiler plate code to interact with the keyboard notification, adjusting our layout boils down to a single line of code that changes a constraint’s constant. The full source for this project is available here.

Evenly Spacing Views in Auto Layout

I’m a big fan of Auto Layout in iOS. However, in the beginning trying to use Interface Builder to create a responsive layout with Auto Layout was particularly challenging. Things just didn’t work the way you expected in Xcode 4:

Well, I just loaded in Xcode 5. I mainly wanted to see if they fixed auto layout. After my 10 hours using it, it does seem much better. Autolayout seems to make sense to me now.

I found Xcode 5 actually made Auto Layout fun and Xcode 6 has made it even better. Whilst all the tooling advances help, implementing seemingly simple layouts are often not obvious. It’s important to develop an understanding of common layout patterns to apply when using Auto Layout. To that end, in this post I’m going to cover how to evenly space views. What we’d like to achieve is three labels that are evenly spaced regardless of the size of the labels or where they appear in their superview. This will allow our view’s layout to respond appropriately on different screen sizes and to events like a banner sliding down, a keyboard sliding up, or an interface rotation:


IBPreview

 

Getting Started

So we create our three labels in Interface Builder. We also add a banner view at the top of the view. If you haven’t used Interface Builder’s Preview feature you should definitely try it now. Simply open the Assistant Editor and choose the Preview option from the Jump Bar. Without any constraints yet, the results are predictably un-useful:

AL1

Spacer Views

To solve this we need a way of telling Auto Layout how to control the space between the three UILabel instances. In order to do this we’ll use spacer views. These will be hidden UIView instances which give us the ability to specify constraints for our spacing. These spacer views won’t be visible to the user but they will participate within the Auto Layout system.

AL2

The key constraints required here are for equal heights on the spacer views. We also specify a constant width for the spacer views:

AL3

Having equal heights for the spacer views ensures their height is always equal and thus the spacing between our labels will also be equal. Of course just adding those constraints is not enough to satisfy Auto Layout:

AL4

Spacing the Spacers

Now we want to add some vertical spacing between our labels and spacer views. Select all three labels and both the spacer views and then add vertical space constraints with a constant of 10:

AL5

 

We also need to specify a constraint so Auto Layout knows how to position these views horizontally. We’ll just make them all centered:

AL6

 

Final Constraints

Finally we need to add constraints for our blue banner view at the top of our view. We’ll just pin the banner’s height, left, right, and top space:

AL7 Wrapping Up

Once all these constraints are in place you can set the spacer views’ hidden property as YES. Finally make sure you update all the frames in Interface Builder so your view’s layout reflects its constraints. Your view should now have no Auto Layout warnings or errors. The source code for this post is available here.

Instant New iPad Features in iOS 6 How-to

The Book

Instant New iPad Features in iOS 6 How-to is an eBook from Packt Publishing.

What is covered?

The book provides a short and practical coverage of apps available in iOS 6, specifically designed for iPad. The apps covered include iPhoto, iMovie, Keynote, Numbers, Pages, iBooks, GarageBand, Mail, and Photos. Instructions on how to leverage iCould to keep your data and documents in sync are also provided. Over 60% of the content is focussed on paid Apple apps, such as iPhone and GarageBand.

What isn’t covered?

At the start the book indicates technical device details wont be addressed. iOS 6 delivered significant new features that the book does not cover. For example Siri, Safari, and Phone had powerful additions. Maps is a completely new app and there was also the addition of Passbook and finally a Clock app. Social integration was also expanded and deepened. However, the book does not address these.

The Verdict?

Great little book if you require some practical guidance on using and setting up some of the Apple apps available for iPad.

Disclaimer: I was given a free copy for review.

Automated Xcode 4 builds and DerivedData

Xcode 4 introduced the DerivedData location. Derived data contains various pieces of data related to Xcode projects, including logs, indexes and build products. The location of the DerivedData folder that Xcode utilises can be configured in a number of places. By default Xcode will use the following path:

~/Library/Developer/Xcode/DerivedData

This location may also be affected by Xcode’s settings, by your project’s settings, or even by your project’s target settings. Typically this location won’t be of concern when just using Xcode’s GUI to build, run, and archive projects. However, one use case where this can be an issue is for automated builds triggered using the xcodebuild command. Imagine you’ve scripted an automated build that builds your Xcode project and produces build products (e.g. a static library or application binary) which are then packaged and/or distributed elsewhere. It would be difficult to know exactly where the DerivedData folder that contains these build products is located.

One solution is to favour some form of convention. That is, to always use the same location for the DerivedData folder for all your Xcode projects and have this folder hard-coded in your build scripts. The better solution is to tell xcodebuild where to place your build products. xcodebuild can accept build settings, so all we need to do is specify the appropriate setting value. For example:

xcodebuild -configuration Debug CONFIGURATION_BUILD_DIR=/tmp/build

The important piece is the setting of the CONFIGURATION_BUILD_DIR build setting. This allows your script to explicitly define where any build products are placed. In the example build products, including static libraries, application binaries, and dSYM folders would be placed in /tmp/build. Personally I use the following format:

xcodebuild -configuration Debug CONFIGURATION_BUILD_DIR=$SRCROOT/BuildProducts

This will place all the build products in a folder called BuildProducts relative to the project I’m building.

Pro Core Data for iOS

I recently read Pro Core Data for iOS: Data Access and Persistence Engine for iPhone, iPad, and iPod Touch Apps (Books for Professionals by Professionals)
from Apress. The book is co-authored by Michael Privat and Rob Warner. Unsurprisingly the book is about Apple’s Core Data framework, specifically the iOS flavour. The book’s introduction includes the following statement:

Introductory texts give you introductory-level understanding of the Core Data framework, which is fine for introductory-level applications but not for applications that cross the chasm from toys to real-life.

This is why I was eager to read this book, due to most tutorials, articles and books providing an introductory-level understanding of Core Data. However, I was keen to explore recommended best practices, common architectures being used, and all the sticky anti-patterns that the unaware engineer may fall into.

The book is organised into nine chapters. The first six chapters primarily deal with what Core Data is and how it’s leveraged in an iOS application. The final three chapters delve into performance, migrations, and various advanced use cases of Core Data.

Whilst the book’s title is prefixed with “Pro”, the first six chapters provide all the detail a beginner requires to integrate Core Data into an app. The reader is taken through the creation of sample apps to aid understanding. These chapters provide good depth, detail and understanding. For example, Chapter One includes a section titled “History of Persistence in iOS.” Chapter Three includes details on creating custom persistent stores, including a thorough example.

Personally, Chapter Six “Refining Result Sets” was the highlight of the book. The authors guide the reader through using NSPredicate object graphs and its query language in order to filter results. This chapter is a complete guide for filtering and sorting, including sections on subqueries, aggregation, compound predicates, and multiple criterion sorting.

Chapter Seven is titled “Tuning Performance and Memory Usage.” The authors share some techniques they use to test and tune performance of real Core Data applications. This chapter includes an excellent section on memory usage and management. This is one area that is easy to forget as a beginner and one that more experienced developers should revise.

Chapter Nine was the most interesting chapter. Topics such as encryption, data change notifications, data seeding, and error handling are discussed.

So what’s the verdict? I found the book to be well written and thorough. My main issue was that the topics covered were still too basic for what I require. Ultimately, I wanted the book to be an extended version of chapters seven and nine. Unfortunately, things like third party tooling, such as the excellent mogenerator were not discussed. The error handling strategy discussed did not suggest a method of recovery, such as maintaining last known good backups or being able to automatically restore to a clean state. There was also no detailed discussion of architectures and common patterns, such as should Managed Object Contexts being explicitly passed or created or encapsulated in singletons for client code. When would each work and when wouldn’t it? Also multi-threaded applications and how to implement Core Data within them were not discussed.

In conclusion, the book is excellent for someone just starting their Core Data journey and requiring deeper understanding of Core Data’s usage. However, for the more advanced engineer, much of what is covered may already be known.

Disclaimer: I was given a free copy for review.

Random Crashes with Xcode 4, LLVM 2.0, and armv6

After recently deploying a simple update to Boxing Timer, I started to get support requests about the app crashing. I couldn’t understand what would cause the crashes as the update was simply adding French localisation. Some quick smoke testing revealed no issues on an iPhone 4 or iPad. However, reverting back to an iPhone 3G or iPod touch G2, I was able to reproduce the crash. What was particularly strange was that the crash could only be reproduced by exercising a very specific code path. In general though, the app seemed to work fine. However, when the app did crash the logs looked something like this:

Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000002
Crashed Thread: 0

Thread 0 Crashed:
0 ??? 0x00000002 0 + 2

Thread 1:
0 libSystem.B.dylib 0x000014b8 mach_msg_trap + 20
1 libSystem.B.dylib 0x00004094 mach_msg + 60
2 CoreFoundation 0x00057002 CFRunLoopRunSpecific + 982
3 CoreFoundation 0x00056c18 CFRunLoopRunInMode + 44
4 WebCore 0x000846f0 RunWebThread(void*) + 412
5 libSystem.B.dylib 0x0002b7b0 _pthread_body + 20

Thread 0 crashed with ARM Thread State:
r0: 0x00000000 r1: 0x00000000 r2: 0x380ab7fc r3: 0x00138a50
r4: 0x00138a50 r5: 0x00019dd0 r6: 0x00138a50 r7: 0x3817b1b4
r8: 0x00170f80 r9: 0x001fc098 r10: 0x00000004 r11: 0x38179ff4
ip: 0x3810a810 sp: 0x2ffff300 lr: 0x30b336c4 pc: 0x00000002

As it turned out the LLVM 2.0 compiler that shipped with Xcode 4.0 and 4.0.1 was responsible for these crashes. Fortunately Xcode 4.0.2 has fixed this issue. I was able to rebuild my app and get an expedited review, which equals happy customers again!

In a nutshell if you’ve been using Xcode 4.0 or 4.0.1 to build your apps with LLVM 2.0, they will most likely experience crashes on armv6 devices. So make sure you’ve upgraded to Xcode 4.0.2.

Ending Background Tasks

iOS 4 bought a host of new features and APIs. One of the most exciting for me was the ability to initiate long running tasks that have the ability to continue execution even after your application has moved into the background, that is once it is no longer running in the foreground.

The primary methods used to trigger this functionality are:

  • beginBackgroundTaskWithExpirationHandler:
  • endBackgroundTask:

Both methods are available on instances of UIApplication. Apple’s documentation for beginBackgroundTaskWithExpirationHandler: states:

Each call to this method must be balanced by a matching call to the endBackgroundTask: method.

These rules for background tasks are analogous to memory management rules within Objective-C, where it is crucial to balance retain and release calls. In either case the consequences are severe if you don’t get it right. For example if you do not call endBackgroundTask: for each task before its’ time expires, the system terminates the app.

If you do not call endBackgroundTask: for each task before time expires, the system terminates the application.

The exact amount of time your app is given is undefined. However, using the backgroundTimeRemaining method on UIApplication, your app can determine how much time is remaining at any point during execution.

The simplest use case may involve only one background task. However, depending upon your app’s requirements and/or complexity you may have many background tasks potentially being managed across disparate areas of your app.

If you’re working with background tasks I recommend you pay special attention to keeping the begin and end calls balanced. One useful strategy is to set a symbolic breakpoint on the UIApplicationEndBackgroundTaskError  function. This function is called when your app calls the endBackgroundTask: method with a backgroundTaskIdentifier that has already been ended or does not exist. You may also place a breakpoint within the expiration handler block that you pass into the beginBackgroundTaskWithExpirationHandler:  method.

These two breakpoints should allow you to catch any unexpected scenarios where you haven’t correctly balanced the two method calls. Just be sure to execute your app with breakpoints on during development!

Time Profiler and iOS 3.2

Time Profiler is one of the tools available under Instruments. It’s only available for iOS 4 apps. I’m currently working on an iPad only app which is being built with iOS 3.2.

What I wanted to do was use Time Profiler to analyse a performance issue with the app. It’s a powerful tool that’s extremely simple to use and has yielded great benefits for me previously. An Apple employee described the tool as “an absolutely wonderful, statistical sampling profiling tool,” and I tend to agree. However, Time Profiler only works on devices running iOS 4 and above. I also didn’t have the option of using iOS 4.2, so it didn’t look like I could use Time Profiler on my iOS 3.2 app.

What I was able to do was use Time Profiler against my app in the simulator. I just needed to link against iOS 4.1 (by changing my target’s Base SDK) and I was able to run my app in the iPad simulator and use Time Profiler to profile it.

So what are the caveats?

• This will only work on the simulator, not for a device running iOS 3.2
• The simulator and the device will have different performance profiles

In the end this work around is not ideal, but it did help highlight exactly where the performance issues were with the app.

iOS 4 and Disabling Multitasking

iOS 4 delivers long awaiting and much anticipated multitasking support for iOS apps. Detailed information on supporting multitasking in your app can be found via Apple’s iPhone Application Programming Guide. If you’ve installed iPhone SDK 4 and are now building apps with it, one very important point to note is:

Applications linked against iPhone OS 4 and later are automatically assumed to support multitasking and to implement the appropriate methods to handle transitions to the background state. However, work is still required to ensure that your application transitions smoothly between the foreground and background.

Therefore, if you set your Xcode project’s target to a Base SDK of 4.0, your application is expected to support multitasking. In some cases having your app moved to the background instead of being terminated may not be appropriate. It is possible to opt out of background execution by adding the UIApplicationExitsOnSuspend key to your project’s Info.plist and setting its’ value to YES. This effectively disables multitasking for your app and will force it to terminate instead of being suspended by the OS.