Thomas Denney

Circle Draw 2

Today I’ve released Circle Draw 2 which refreshes the UI and adds support for newer iPhones.

More importantly, however, the critical cats that score the circles are now higher resolution.

You can download the free update to Circle Draw from the App Store today.

Apps that include an app extension and a framework must support arm64

Yesterday I was finally shipping an update to one of my apps, but each time I tried submitting to iTunes Connect I got back error -9000:

Invalid architecture: Apps that include an app extension and a framework must support arm64

Googling didn’t reveal too much (the project was set up fine to build for both 32-bit and 64-bit), but the following seemed to fix the issue:

  • Going through project.pbxproj and manually replacing IPHONEOS_DEPLOYMENT_TARGET = 7.0; with IPHONEOS_DEPLOYMENT_TARGET = 8.0; (I had set 8.0 in the UI, no idea why the file hadn’t updated)
  • Ensuring that the ‘Build Active Architectures Only’ was set to NO for release builds (again, I had set this in the UI, but checked it in the project.pbxproj file)
  • Deleting an old static library from the Frameworks group. This is the weird one, but I suspect it was what was causing the issue. The app had previously linked to a static library that had been 32-bit only, but I had long since deleted it. The app itself didn’t link against it, but there was still a link showing up for it in the Xcode project (it showed in red though, it didn’t actually exist)

The phrasing of the error isn’t great; there ought to be an ‘or’ rather than an ‘and’ in there (my app only contains a framework, not an extension).

Word Finder 2

After two years of no updates I have now updated Word Finder with new features, significant performance enhancements, and support for new iPhones. Word Finder allows you win (cheat?!) many common word games with wild card search, anagram search, Boggle search, and Letterpress search.

  • A brand new query execution engine that ensures all queries now execute instantly (the old version could take several seconds)
  • Search history
  • Easy entry mode for Boggle and Letterpress grids and improved entry for anagrams
  • Sorting options
  • Save your favourite words
  • View definitions for thousands of words via Wiktionary or the built in Apple dictionary
  • Modernised user interface

You can download the latest version of Word Finder for free from the App Store.

Nim on iOS

The Nim programming language is simple, clean language with a style that will be familiar to Python programmers, but has the performance benefit of compiling down to C. The C the compiler generates is different depending on whether you have 32-bit or 64-bit code, which makes compiling for iOS (which has to target both 32-bit and 64-bit) awkward.

In this blog post I’ll summarise how you can use Nim for components of your app. I’ve got a working version of this project available on GitHub.

Firstly, if you haven’t already, grab the compiler and compile it (don’t worry, this is easy). Then create a new Objective-C project in Xcode. I’ve called mine nim-ios-demo:

Creating a new project

Next you’ll want to create two directories: scripts and src. Your folder structure should look like this:

Creating script folders

The src folder is where you’ll be placing your Nim source files. In scripts you need to place my xcode_prebuild.sh script (I modified it from work by Grzegorz Hankiewicz). This script compiles the Nim source files to C and creates the merged 32-bit/64-bit files. You need to add this script as a build phase in Xcode:

Script build phase

There are two minor changes that you’ll need to make to the script to use it in your project:

  • Set the PROJECT_DIR variable
  • Set the PATH_TO_NIM variable

Add your Nim source files in the ‘src’ directory. In this example I’m going to use a very simple function:

# Saved as backend.nim in the src directory
proc hello*(name: cstring): cstring {.exportc.} =
    result = "Hello " & $name

You can optionally add this to your Xcode project, but make sure that you don’t have Xcode set to copy or compile it! Note that we need the asterisk after the function name so that it gets exported, and {.exportc.} ensures that the name doesn’t get mangled. We also have to use cstring rather than string (Nim’s native string type) but they get bridged automatically at no cost.

Build your project. This will run the Nim compiler and generate the C files you need to include in Xcode. Go ahead and add the contents of src/build/nimcache to your project:

Adding to the project

If you build now you’ll get a lot of warnings (50+). If you want to avoid these, add the -w flag to the files in their compile stage:

Compiling

Before you can use the Nim function you’ll need to configure the Garbage Collector. Add the call to NimMain in main.m:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "backend.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NimMain();
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

For my example, I’ve created a simple app that echoes the user’s name. To call the function, you’ll need to import backend.h:

#import "ViewController.h"
#import "backend.h"

@interface ViewController ()
- (IBAction)textChanged:(UITextField *)sender;
@property (weak, nonatomic) IBOutlet UILabel *label;

@end

@implementation ViewController

- (IBAction)textChanged:(UITextField *)sender {
    char * helloName = hello((char*)sender.text.UTF8String);
    self.label.text = [NSString stringWithUTF8String:helloName];
}

@end

By using [NSString stringWithUTF8String:] we can copy the contents of the string, which ensures that when Nim cleans up the memory later (helloName) we don’t lose the string.

Finally, you can build and run the app:

Once you’re up and running it is trivial to add new Nim code to your project. So far I’ve been very impressed with the language, and I may even use it in the future in my apps.

Programming Language of the Month

When Apple announced Swift last summer I was excited to learn a new programming language. After having programmed almost exclusively in Objective-C (with a bit of Go, JavaScript, C#, Java, and C++ on the side) for two years I thoroughly enjoyed picking up Swift’s new concepts such as functional programming, generics, and values.

Having enjoyed my experiences with Swift, I decided to play with a new programming language each month, so since July 2014 I’ve had a Programming Language of the Month:

The amount of work I’ve done in each language has varied hugely. I only did a small amount of work in Prolog to familiarise myself with the basic concepts, but I’ve written semi-large programs in all of the others.

Learning, or at least experimenting with, a new language is a tremendous adventure for any programmer. Its been a valuable experience picking up ideas in a variety of functional, imperative and declarative programming languages. If you’ve got the time, I’d give a PLoTM a try.

Objective-C and Swift equivalencies

Swift has encouraged many developers to consider Cocoa and Cocoa Touch development, but the vast majority of resources are still written in Objective-C. I’ve done a huge summary over on GitHub of many common patterns.

Use categories to avoid rewriting classes in Swift

It may be tempting to rewrite existing classes in Swift, however this will generally be a waste of engineering resources. A better approach is to add functionality to existing Objective-C classes by writing categories for them in Swift. This way, if you choose, you can write all future code in Swift whilst avoiding unnecessary extra work.

Cake Day 2

Cake Day, my iOS app that reminds you once a year of your reddit cake day (birthday), has been updated with a new UI and iPad support.

Changes:

  • Completely removed the hamburger menu. Apple discourages these and it didn’t work brilliantly, so I decided it would be best if it went
  • Changed the app’s default font (now using Open Sans)
  • Rewrite of the app in Swift. I hadn’t originally planned to do this as part of the update, but I wanted to see whether or not Swift could improve my programmer productivity. Overall I found that the amount of code that I had to write was similar - although I now have a lot more database could for dealing with SQlite.swift than I had before when using FMDB
  • The app is now open source you can contribute or post issues at GitHub

You can download Cake Day for free from the App Store.

Keep Calm 4.1 with PDF export

I’ve published an update to Keep Calm for iOS just in time for Christmas. This version adds PDF export for Pro users, which is great if you want to print your posters from your computer later. PDFs can be either opened in another app (Kindle, iBooks, Dropbox, etc) or shared directly (email, iMessage).

You can download Keep Calm for free from the App Store. The Pro upgrade costs $0.99.

OpenGL.swift

It is a little bit of a pain to use OpenGL with Swift as GLKit is barely compatible. This is because GLKit’s math functions and types are all based off of unions, which Swift doesn’t support because they are designed to be unsafe. You are left with two choices: roll your own matrix library in Swift (which may miss out on the ARM NEON or Intel SSE performance enhancements) or hide GLKit behind some Objective-C.

I decided to go for the latter, and the product is OpenGL.swift. Instead of using unions I have used structs which contain one member:

typedef struct {
    GLfloat m[16];
} TDMatrix4;

I then wrapped all of GLKit’s math functions and I internally cast my matrix and vector types to the GLKit types in Objective-C code. As all of my functions and all of the GLKit functions get inlined there is no performance cost to this. My code was all generated by a Ruby script directly from the GLKit headers.

Once I had wrapped all of the GLKit math functions and types I then wrapped all of the uses of matrices and vectors in GLKit classes, so you can actually use them from Swift:

let aspect = GLfloat(CGRectGetWidth(self.view.bounds) / CGRectGetHeight(self.view.bounds))
let projectionMatrix = TDMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0)
self.effect?.transform.td_projectionMatrix = projectionMatrix

At this point I then added operator overloading using all of the standard methods, so in Swift you can concisely do matrix math:

let mvpMatrix = projectionMatrix * modelViewMatrix

As well as this I also added wrappers around the standard uniform functions so it is much simpler to submit matrix and vertex data to the GPU:

//Submitting vertex data
glBufferData(GLenum(GL_ARRAY_BUFFER), vertexData, GLenum(GL_STATIC_DRAW))
//Setting uniform data
glUniformMatrix4fx(mvpMatrixSlot, TDFalse, mvpMatrix)

You can get the source for OpenGL.swift on GitHub (there are instructions for dropping it into your project there as well).