Building iOS dependencies with Carthage

In all my iOS projects I use and strongly prefer Carthage. It is easy to use, does not do any changes to your project, all the dependencies are built just once and then linked to the project as dynamic frameworks. There are many good posts about the advantages of Carthage compared to CocoaPods so in this post I will just focus on the actual usage, mainly in CI.

Carthage basics

All your Carthage dependencies are listed in the Cartfile file in the root of your project. In case you split your app into multiple projects like I do, there is a Cartfile for every project in the workspace. Next to every Cartfile there is a Cartfile.resolved file pinning all your dependencies to a specific version.

You just need to keep those two files in your source control and then run carthage bootstrap when you clone the project so Carthage downloads and builds all the dependencies. This happens just once for a developer, but it is slow and time consuming. If you use a CI for automatic builds, it becomes a real time waste rebuilding all the dependencies before each build.

Carthage approaches

Developers typically try to speed things up with multiple approaches

  • Keeping Carthage/Checkouts in source control. This makes the repository bigger by keeping unnecessary files, the checkout is faster but the build is still slow.
  • Keeping Carthage/Build in source control. This also makes the repository bigger, potentially much bigger if you update your dependencies often, but the build times are super fast as there is nothing to actually build.
  • Caching the Carthage builds in CI. This does not make the repository bigger and can be really fast when done properly
  • Caching the Carthage builds using tools like Rome. This does not make the repository bigger and can be very powerful and flexible, but typically requires a paid 3rd party storage service like Amazon S3.

[Read More]
swift  ios  xcode 

Checking for missing translations in iOS projects

When you work on an iOS app localized into multiple languages one of the biggest challenges is making sure that everything is translated, no string is missing in any language. Xcode does not provide any tool to make this easier for you, but there are some 3rd party tools that you can integrate into your workflow.

verify-string-files

I have recently found a quite old project called verify-string-files. It is a command line tool take takes you base localization file and compares it to all the translations, informing you about missing strings. Altough the last commit to this project was way back in 2014 it still works reliably, there have not been any changes to the way iOS does localization.

The best thing about this tool is that you can integrate it to your build process.

Build process integration

The tool is available only as source code, so you have to build it first. I put the built binary to a support folder of my projects.

Then I have a Build-Phases folder with all the script used in the build process. I think it is a much better solution than embedding the script right into the Xcode project.

To integrate verify-string-files you just need a really simple script, providing the path to the base localization file

${PROJECT_DIR}/support/verify-string-files -master ${SRCROOT}/iOSSampleApp/Resources/Base.lproj/Localizable.strings

In Xcode, just add a new Run scrip phase and call $SRCROOT/Build-Phases/check-strings where check-strings is the script name. Just do not forget to chmod +x the actual file.

This will result in build errors when there are missing string, shown directly in the base localization file

[Read More]
swift  ios  xcode 

Automating your iOS app development and distribution workflow

I am a big fan of automation in software development so when I started doing iOS development one of my goals was to automate everything on the iOS project.

No more manual versioning, manual build distribution… let the computers do the work for me. Here is the setup I ended up with.

Separate app ids for development and distribution

Let’s say your app id is com.company.app. You can use that app id when developing the app, running it in the simulator or on your device and also when distribution the app using services like TestFlight or uploading it to the AppStore.

With just one app id you cannot have both the AppStore version and a development version installed on your device. This a problem when working on an app that you use daily for communication with your colleagues, but you are working on a feature that requires you to use a different server, or some MDM, etc.

There is also another problem you will encounter if you use push notifications. When you create a push notification certificate for production, push notifications for your app will work with AppStore builds, with ad-hoc builds in TestFlight and other services but you will not get any notifications when running the app on your device deployed from Xcode. At least not easily.

To counter that, I use separate app ids

  • com.company.app with push notifications set to production for AppStore and ad-hoc distribution
  • com.company.app.dev with push notifications set to sandbox for development

This of course requires your backend to support it by choosing the right push notifications certificate depending on the app id.

With this setup, I can

  • use the AppStore version and the development version of the app on my device at the same time
  • have push notifications working also in the development version of the app

Automatic builds and tests with Gitlab

The iOS project I work on uses self-hosted Gitlab instance, so using Gitlab CI was the obvious choice. You just need a machine with macOS that is always online, install the Gitlab runner, connect it to the Gitlab instance and you are done. Everything else is just a matter of configuration in a file in your repository.

[Read More]
swift  ios  xcode 

Creating and using your own Xcode file templates

Working on an iOS or macOS project in Xcode you typically create classes with the same structure over and over again.

I use coordinators so I am creating new UIViewControllers, each time referencing RxSwift, having methods for setting up UI, bindings .. most of the time also containing a delegate for the coordinator.

Having to create files with the same structure over and over again manually is a waste of time, a much better solution is creating Xcode file templates for those files.

Xcode file templates

File template location

All the Xcode custom file templates are located in ~/Library/Developer/Xcode/Templates/File Templates and grouped into sections by their folder name. If you want Xcode to show a “Custom” section at the bottom of the new file dialog, just create a ~/Library/Developer/Xcode/Templates/File Templates/Custom folder.

File template structure

Each file template is a separate folder with a name ending in .xctemplate. If you want to create a simple “Swift Class” file template, you have to create a folder named Swift Class.xctemplate in ~/Library/Developer/Xcode/Templates/File Templates/Custom.

Each file template folder should contain at least 3 files:

  • TemplateInfo.plist - describing the template
  • TemplateIcon.png - icon shown in the Xcode new file dialog
  • ___FILEBASENAME___.swift - the actual template file

[Read More]
swift  ios  xcode 

More readable XCode build output for CI

If you use Continuous Integration (CI) builds or build your app from the command line using xcodebuild you know that the output is not pretty and not very readable. Reading the build output is important when a CI build breaks, but it is not easy when it looks like this

Many iOS developers were not satisfied with this so the xcpretty project was created. Xcpretty is a fast and flexible formatter that turn the output from screnshot above to this neatly formatted output

[Read More]
ios  macos  xcode 

iOS tip: Wireless debugging from XCode

One of the best XCode 9 features is the ability to deploy and debug iOS app on your device over WiFi, with no need to have the device connected to you computer by a cable. The only requirement is that the device runs iOS 11.

Setting it up is really easy. Connect the device using a cable like you normally do and go to Window | Devices and Simulators. You will see a new checkbox next to your iOS 11 devices called Connect via Network (see screenshot below), so check it. Now you can disconnect the cable and debug on your device over WiFi, the device has to be on the same network as your computer of course.

[Read More]
ios  macos  xcode 

Formatting Swift code in XCode

When I started using XCode I was really surprised about the really poor implementation of its code formatting functionality. It kind of formats the alignment of the code but ignores unnecessary spaces and a lot of other things. Formatting the source code and keeping the style consistent is really important to me so I was looking for a solution. I found some linters like SwiftLint but I was interested in a tool that will actually format the source code for me on demand. I found SwiftFormat.

SwiftFormat

SwiftFormat is a code library and command-line tool for reformatting swift code. It applies a set of rules to the formatting and space around the code, leaving the meaning intact.

[Read More]
ios  xcode  swift