Isaac Overacker

maker of things

Integrating Test Dependencies With CocoaPods

Most Xcode projects should have some level of test coverage, and any time unit tests are involved it’s nice to have a framework for generating mock objects. However, we don’t want to bloat our production app package with these test frameworks, so it’s nice to link these libraries only with the test target. Configuring this properly can be tricky, and the CocoaPods documentation isn’t very clear on exactly how to accomplish this in the podfile.

The cleanest solution I’ve found to this problem involves specifying the pods for each target individually and using a Ruby function to import the common pods. Here is a sample podfile that accomplishes this:

Podfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
platform :ios, '7.0'

def import_common_pods
   pod 'AFNetworking'
end

target 'MyAppTarget' do
   import_common_pods
end

target 'MyAppTestTarget' do
   import_common_pods
   pod 'OCMock'
end

Note that you may run into a few issues with this if you’re adding this to an existing project and the previous podfile did not explicitly specify the non-test target. In that case, you may need to delete the old Pods.xcconfig and libPods.a files then regenerate your workspace with pod install.

Update

As of CocoaPods 0.34, there’s a cleaner solution built-in:

Podfile
1
2
3
4
5
6
7
8
9
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '7.0'

pod 'AFNetworking'

target "MyAppTestTarget", :exclusive => true do
   pod 'OCMock'
end

Architecture Headaches With CocoaPods

I recently inherited an iOS project from another developer. This project was not using CocoaPods for dependency management, so naturally, I converted it to using CocoaPods as soon as I could. When I first installed the pods, I received this warning in the console:

Terminal
1
2
3
[!] Found multiple values (`armv7`, `armv7s`) for the
architectures (`ARCHS`) build setting for the `Pods` 
target definition. Using the first.

It seemed harmless enough, and the project built without problems for the iPhone simulator. I carried on for a few weeks working on new features, and then I tried to build a version of the app targeting the iOS devices. Suddenly, I had linker errors.

1
2
3
4
"_OBJC_CLASS_$_FBSession", referenced from:
  objc-class-ref in MySourceFile.m
  ...
ld: symbol(s) not found for architecture armv7s

I looked around for solutions, but of course with linker errors it’s can be very difficult to find answers for a particular issue. Finally, after many hours of searching, reading, and highly scientific trial and error, I decided to look into the multiple architecture warning from CocoaPods, and that’s where I found my issue. In this particular case, the Pods-* targets in my Pods project were targeting armv7 (which is pretty obvious from the CocoaPods warning, but a few weeks had passed), whereas my main app target architectures included both armv7 and armv7s, hence the linker error above.

The solution was to update the target architectures for the app to $(ARCHS_STANDARD_32_BIT) instead of manually specifying both armv7 and armv7s. Then, when running pod install, the $(ARCHS_STANDARD_32_BIT) is set for the Pods-* projects as well and everything is happy.

Note: the reason armv7 and armv7s architectures had been specified for the app is that there is a dependency on a library that does not yet support 64-bit architectures. It looks like $(ARCHS_STANDARD_32_BIT) is a much better way to handle that situation.

The Death of FlightPath and the Future of iOS Usage Statistics

As a longtime user of TestFlight for both test build distribution and usage analytics, I was extremely disappointed to find that they have cancelled their FlightPath beta program for tracking usage statistics in your live app once distributed via the App Store. It was great to be able to reuse the same checkpoint infrastructure to collect usage statistics. Alas, they claim to be focusing more on their core product, which might be a good thing in the end.

As a replacement, I have started working with Flurry, which provides a great deal of usage statistics, including an event infrastructure similar to TestFlight’s checkpoint system.

Make sure to sign up for a free account and copy your application key. Let’s get started!

Renaming an App on the App Store

Renaming an app on the iOS app store is a relatively simple thing to do. The biggest point of confusion is that you cannot rename your app unless it is in an editable state. You’re probably going to want to change the display name for your app, so the easiest way to put your app in an editable state is to upload a new binary.

Bundle Identifier

If you want to rename your Xcode project to reflect the new app name, you won’t want your bundle identifier to change along with the project name since this is the unique identifier for your app on the device. By default, the bundle identifier includes ${PRODUCT_NAME} or a variant thereof, e.g. ${PRODUCT_NAME:rfc1034identifier}. You won’t want the Bundle Identifier to change when you rename your project, so the first thing you’ll want to do is copy your Bundle Identifier from iTunes Connect and paste that in the Bundle Identifier field in the info.plist file for your app.

Rename Project

The fastest (and most thorough) way to rename your app is to simply rename the project in Xcode. Slowly double-click on the project file in Xcode so that the name becomes editable and change the name. After pressing enter, a dialog will pop up asking if you’d like to rename project content items. You probably want to keep all of these in sync, so choose Rename.

Upload Binary

Login to iTunes Connect and create a new version of your app. When you edit the metadata for the new version of your app, you can now edit the name of the app. Enter the new name for your app, create your new binary, and upload. If you make it through the review process, your app will be ready to launch under a new name! As long as you don’t change the Bundle Identifier, existing users will receive the update.

Embedding Video With the Mnml Theme

I released a small update to the mnml Octopress theme recently to resolve an issue experienced by one of the users of mnml. Cole Nordin opened an issue on GitHub which captures a common issue when embedding videos in posts wherein the video will not be resized with the window and therefore does not fit within the bounds of the screen on certain mobile devices.

To address this, I added CSS from the octopress-responsive-video-embed plugin to the theme. (Unfortunately, I couldn’t find a way to embed the plugin in the theme, so if you know of a way to do that please post in the comments below.) When you need to embed a video, you can do it one of two ways.

Use the embed-video-container div

You can take advantage of the CSS directly if you don’t want to mess with plugins. Simpily wrap your embed code in the embed-video-container div like this:

1
2
3
<div class="embed-video-container">
    <iframe width="1600" height="1200" src="//www.youtube.com/embed/_QP5X6fcukM" frameborder="0" allowfullscreen></iframe>
</div>

Or, if you’d like a markdown-friendly approach…

Install the octopress-responsive-video-embed plugin

Copy youtube.rb from the octopress-responsive-video-embed plugin to your /plugins directory. When you want to embed a youtube video, use the following markdown:

1
{% youtube _QP5X6fcukM %}

Replace the video id with the video id you’d like to post, of course. (Make sure not to confuse this with the video plugin included with Octopress, which is used to embed mp4 files.)