Overriding the iOS Dynamic Type font family

Written by Emil Loer on Oct 31, 2016 |

Recent versions of iOS provide Dynamic Type: a fantastic system for adding accessible typography to your app. By adopting Dynamic Type the user can define a system-wide font size which will then also be reflected in your own app. Dynamic Type even provides a couple of predefined text styles - such as titles, captions, and footnotes - which you can use to modify the typographical salience of your content.

This marketing blurb makes it sound awesome but also makes you wonder why not all apps support it. Well, it turns out that Dynamic Type currently has a big drawback. In order to make your own app stand out from the crowd you want to use a custom fancy-pants font, but it turns out that Dynamic Type won't allow this. So you have to make a decision... or do you?

Modifying Font Descriptors

Using the UIFontDescriptor class we can get some kind of specification for a given font. The descriptor codifies information such as the font family, font name, weight, style, and a lot of other metadata we don't necessarily care about. Getting a descriptor from a font is simple: just take it from the fontDescriptor property of a UIFont instance. To convert the descriptor back to an actual font we just pass it as an argument to one of the UIFont constructors.

Now, the goal here is that we want to take a font instance created by Dynamic Type and convert it to a font that has our own custom family name but keeps al the other properties intact. This is not easy because if we just change the font family name of a descriptor the font weight will be reset. Furthermore, if we take the font descriptor and we just start modifying things we will get a font descriptor that still contains some properties that on some occasions override our custom font family.

This means we have to be a bit more clever. First we extract the necessary font traits and then we create a new font descriptor from nothing and just specify the exact traits we are interested in. This results in the following snippet of code:

// Get a font from Dynamic Type
var font = UIFont.preferredFont(forTextStyle: UIFontTextStyleHeadline)

// Our overridden font family name
let newFamilyName = "Avenir Next"

// Extract the weight
let weight = (font.fontDescriptor.object(forKey: UIFontDescriptorTraitsAttribute)
    as! NSDictionary)[UIFontWeightTrait]!

// Create a new font traits dictionary
let attributes = [
    UIFontDescriptorTraitsAttribute: [
        UIFontWeightTrait: weight
    ]
]

// Create a new font descriptor
let descriptor = UIFontDescriptor(name: font.fontName, size: font.pointSize)
    .withFamily(newFamilyName)
    .addingAttributes(attributes)

// Find a font that matches the descriptor
font = UIFont(descriptor: descriptor, size: font.pointSize)

Global font family overrides with appearance proxy

The method given above is already really powerful but still requires you to manually set fonts everywhere. We can change the code above to a computed property that can be set globally with the UIAppearance proxy protocol, e.g. on a label. This is done as follows:

/// Extension allowing global UILabel font family overriding via appearance proxy
extension UILabel {
    var fontFamily: String {
        get {
            // Extract the font family from the current descriptor. This is not really
            // necessary but provides a sane value for the required getter.
            return font.fontDescriptor.object(forKey: UIFontDescriptorFamilyAttribute)
                as! String
        }

        set {
            // Extract the weight
            let weight = (font.fontDescriptor.object(forKey: UIFontDescriptorTraitsAttribute)
                as! NSDictionary)[UIFontWeightTrait]!

            // Create a new font traits dictionary
            let attributes = [
                UIFontDescriptorTraitsAttribute: [
                    UIFontWeightTrait: weight
                ]
            ]

            // Create a new font descriptor
            let descriptor = UIFontDescriptor(name: font.fontName, size: font.pointSize)
                .withFamily(newValue)
                .addingAttributes(attributes)

            // Find and set a font that matches the descriptor
            font = UIFont(descriptor: descriptor, size: font.pointSize)
        }
    }
}

Now using only a single line of code we can automatically override the font family of all UILabel instances in our app, while maintaining size and font style from Dynamic Type. Just add this line to your application delegate class:

UILabel.appearance().fontFamily = "Avenir Next"

With this line in place you can configure your labels to use the predefined Dynamic Type style classes for maximum accessibility and still enjoy the typographical fanciness of a custom font!

If you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

Swift 3 migration pitfalls

Written by Emil Loer on Sep 14, 2016 |

Hooray! Swift 3 got released, so let's migrate! In this post I will tell you about my experiences of migrating a 20K lines Swift project to version 3 of the language. In case you're curious, the project is my own implementation of the Cassowary linear constraint solving algorithm most famous for it's use in Auto Layout, but I'm using it for something totally different which I will write about in a future article.

The Swift Migrator

The first step was to convert my project by running the Swift Migrator from Xcode. The migrator caught most of the things I had to change, so it saved me a lot of work. There were a few things I had to change afterwards. The two most interesting ones were permission changes (the new permission model default to making public classes and methods open, but I wanted to limit this in most cases) and a binary search function that I had to rewrite because of changes to the way collection index manipulation works. No big deal though.

Nothing has changed

As is tradition now with any new Swift release my first compilation attempt segfaulted the compiler. The compiler log did output a list of errors before segfaulting and after I worked on these the crash disappeared and I was good to go.

The compilation errors I had to fix were related to two language changes that the migrator did not catch. I will highlight these in the next two sections.

New Ranges

The first class of errors had to do with semantic changes to the Range structure. In Swift 3 ranges are now represented using four different structs to distinguish between countable/uncountable ranges and open/closed ranges. In Swift 2 open and closed ranges were represented using the same struct, so if you had some code that had to work on both types this needs some changes.

Consider this valid Swift 2 example:

func doSomething(with range: Range<Int>) {
    for number in range {
        ...
    }
}

doSomething(with: 0..<10)
doSomething(with: 0...10)

In Swift 2 this would work for both half-open and closed countable ranges. The migrator did not convert the struct name, so after migration this does not work anymore. In Swift 3 Range represents a half-open uncountable range. Since uncountable ranges don't support iteration we have to change this, and it would also be nice if we can make it work on both half-open and closed ranges. The solution is to either convert the input to an half-open countable range or use generics to make it work on both. This makes use of the fact that countable ranges implement the Sequence protocol.

Here is a Swift 3 version that works:

func doSomething<IterableRange>(for range: IterableRange) 
    where IterableRange: Sequence, IterableRange.Iterator.Element == Int {
    for number in range {
        ...
    }
}

doSomething(with: 0..<10)
doSomething(with: 0...10)

Tuple Conversion

Another thing the compiler complained about was named tuple conversion. The following is a piece of valid Swift 2 code:

typealias Tuple = (foo: Int, bar: Int)

let dict: [Int: Int] = [1: 100, 2: 200]

for tuple: Tuple in dict {
    print("foo is \(tuple.foo) and bar is \(tuple.bar)")
}

The migrator left this code untouched, but the compiler complains about the for loop's typecast to Tuple. When iterating over that dictionary the iterable element type is (key: Int, value: Int) and in Swift 2 it was perfectly fine to assign this directly to a variable having a named tuple type with the same member types but different names. Well, not anymore!

Although I think that this stricter typing is in general a good idea, it does mean that we now have to explicitly convert the tuple to our target type. We can replace the loop with the following code to make it work again:

for tuple in dict {
    let tuple: Tuple = (foo: tuple.key, bar: tuple.value)
    print("foo is \(tuple.foo) and bar is \(tuple.bar)")
}

Of course this is a contrived example, but if you're passing this tuple around or whatever it can keep the code more understandable if you're using semantically valid names instead of key/value, which are only relevant to the dictionary.

PaintCode and Core Graphics

Something else worth mentioning is Core Graphics. Swift 3 introduces objectification of Core Foundation-style references, meaning that you can now use them as if they were Swift objects instead of a group of C functions. This is really neat for keeping your code readable. This new feature is most often seen with Core Graphics calls. The migrator converts most of these calls, but some of the lesser used functions (e.g. arc drawing) are not converted and have to be done manually.

In my projects I make a lot of use of PaintCode. With PaintCode's code generation being notorious for not fully supporting the most recent Swift syntax (the current version still produces warnings on Swift 2.3 even though it is a trivial issue to solve) I was afraid my graphics code might not convert properly. Fortunately the code gods smiled upon me because no additional issues were encountered after migration. You might still want to change the visibility from open to internal though to benefit from more compiler optimisations. (I have a script that does this with some regexing)

Performance

Overall I noticed no significant changes in compilation time in my projects after migration. My benchmarking unit tests showed a slight performance drop in dictionary-heavy code, but otherwise nothing significant. My constraint solver still works in real-time. :)

Final Thoughts

Overall, migration to Swift 3 was quite easy. The migrator helped me get through most of the changes, and the remaining stuff was easy to fix. It might be different if you're still a bit new to Swift though, so your mileage may vary.

A final tip that really helps: make sure you have plenty of unit tests for the algorithmic parts of your project (never a bad idea!) so you can verify that no semantic changes were introduced during migration, and if they were then you can locate them!

If you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

An easy way to convert Swift structs to JSON

Written by Emil Loer on May 24, 2016 |

One of the real powers of Swift is that it allows you to define custom value types by using structs. However, sometimes you also need to send these types off to some external web service (e.g. as JSON) and this is where things get tricky. To convert things to JSON we can use Foundation's NSJSONSerialization. Unfortunately this only works if whatever you are converting is an NSArray or NSDictionary so it can't be used directly.

In this article I propose a solution that is able to convert any Swift struct into a JSON object by just adding a protocol to the struct declaration. A protocol extension and clever use of the Swift reflection API does the rest. Let's see how it works.

Representable

The first thing we have to do is to define a protocol that tells us how the conforming type can be represented as input compatible to NSJSONSerialization. We will use this protocol later to easily convert our own types to their JSON representation.

protocol JSONRepresentable {
    var JSONRepresentation: AnyObject { get }
}

The result of the JSONRepresentation computed property may be one of the following: NSNull, NSString, NSNumber, NSArray, (with values mentioned in this list) or NSDictionary (with NSString keys and values mentioned in this list).

Serializable

The next step is to define a protocol that indicates that the conforming struct can be serialized.

protocol JSONSerializable: JSONRepresentable {
}

To convert the struct we have to first provide its JSON representation by implementing JSONRepresentable. This is done with a protocol extension.

extension JSONSerializable {
    var JSONRepresentation: AnyObject {
        var representation = [String: AnyObject]()

        for case let (label?, value) in Mirror(reflecting: self).children {
            switch value {
                case let value as JSONRepresentable:
                    representation[label] = value.JSONRepresentation

                case let value as NSObject:
                    representation[label] = value

                default:
                    // Ignore any unserializable properties
                    break
            }
        }

        return representation
    }
}

The trick here is that we are using the Swift reflection API (the Mirror struct) to discover and iterate over the list of properties in the struct. If the property itself conforms to JSONRepresentable then we return its JSON representation (and thus implement nested struct serialization). If not then we check if the property can be cast as an NSObject and output that in the resulting dictionary. Note that for the sake of this example's simplicity we are not checking explicitly whether the property is one of the types allowed by NSJSONSerialization. This is left as a (somewhat trivial) exercise to the reader.

Now that we have a way to represent the struct in JSON we actually have to provide some code to serialize it. This can be done with a second method in the protocol extension:

extension JSONSerializable {
    func toJSON() -> String? {
        let representation = JSONRepresentation

        guard NSJSONSerialization.isValidJSONObject(representation) else {
            return nil
        }

        do {
            let data = try NSJSONSerialization.dataWithJSONObject(representation, options: [])
            return String(data: data, encoding: NSUTF8StringEncoding)
        } catch {
            return nil
        }
    }
}

The toJSON function basically checks if the JSON representation of itself is valid and then serializes it and returns the result as a string. The function returns nil when the struct is not serializable.

Protocol usage

Consider the following example structs:

struct Owner {
    var name: String
}

struct Car {
    var manufacturer: String
    var model: String
    var mileage: Float

    var owner: Owner
}

Suppose we want to serialize instances of these structs into JSON. The only thing we have to do is to add JSONSerializable as a protocol to the struct and start using it. Just like this:

struct Owner: JSONSerializable {
    var name: String
}

struct Car: JSONSerializable {
    var manufacturer: String
    var model: String
    var mileage: Float

    var owner: Owner
}

let car = Car(manufacturer: "Tesla", model: "Model T", mileage: 1234.56, owner: Owner(name: "Emil"))

if let json = car.toJSON() {
    print(json)
}

This prints the following line:

{"owner":{"name":"Emil"},"manufacturer":"Tesla","mileage":1234.56,"model":"Model T"}

And presto! Super simple JSON struct serialization!

Bonus: adding JSON representations

The serialization function given above works perfectly for structs and the types supported by NSJSONSerialization. But what to do if a property is of another type, e.g. NSDate?

Well, we can add serialization for any other type by just conforming to JSONRepresentable. This is how to do it:

extension NSDate: JSONRepresentable {
    var JSONRepresentation: AnyObject {
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"

        return formatter.stringFromDate(self)
    }
}

And now you can also serialize structs with dates:

struct Event: JSONSerializable {
    var name: String
    var timestamp: NSDate
}

let event = Event(name: "Something happened", timestamp: NSDate())

if let json = event.toJSON() {
    print(json)
}

This prints the following output:

{"timestamp":"2016-05-26T17:47:03.709","name":"Something happened"}

Final thoughts

In this article I've shown you how to serialize your own structs to JSON without heavy modifications to the structs themselves, keeping their code nice and clean. I hope it may be of use in your Swift endeavours.

If you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

Embedding PyPy in a C application

Written by Emil Loer on May 15, 2016 |

At the PyGrunn 2016 conference last Friday I gave a talk about the Python cffi package and how to leverage it to embed PyPy into a C application. A video of this talk will be published later when it becomes available.

With the release of cffi 1.5.0 and its subsequent inclusion in PyPy 5 it becomes possible to embed PyPy. This is done by compiling the Python code into a dynamic library which can then be used in any other language. In this article I will show you how to do this.

The embedded API

The first step is to define some kind of interface that defines how the C application should call our Python code. We have to specify this using C function prototypes. For our example we will expose a function that performs some kind of computation, but this can of course be anything you want.

float compute(float first, float second);

Now we have to actually implement this computation in Python:

from my_library import ffi, lib

@ffi.def_extern()
def compute(first, second):
    """ Compute the absolute distance between two numbers. """
    return abs(first - second)

This implementation snippet contains a few special things to make it embed properly. The first line imports the ffi and lib objects from the dynamic library. By doing this the implementation gets access to functions provided by cffi and these can be used for more complicated tasks, such as memory allocation. The name my_library is defined below and corresponds to the name of our dynamic library.

The second thing we notice in the snippet is the @ffi.def_extern decorator. This tells cffi that the decorated function is to be exposed in the public API of the generated C library. The decorated functions will be mapped to the prototypes given in the API definition and their arguments and return values will be converted automatically.

Library generator script

Now that we have our API and its implementation to embed we actually have to embed it somewhere. For this we are using a script that generates the dynamic library. The embedding script requires the two snippets given above to be in the files api.h and implementation.py.

import cffi
ffi = cffi.FFI()

ffi.embedding_api(open("api.h").read())
ffi.embedding_init_code(open("implementation.py").read())

ffi.set_source("my_library", "")
ffi.compile(verbose=True)

The embedding script is pretty straightforward. We have to specify our external API and provide an implementation. Both are read from disk and correspond to the two snippets given in the previous section.

After specifying the source we have to tell cffi the name of our library, which is my_library in our example. Additionally this is the place to add extra C source to provide types for the API header file, e.g. by including the proper header files (which is not allowed in embedding_api). All that remains is compiling the sources to create our library file.

Running the script produces some output and generates our library:

$ pypy embed.py
generating ./my_library.c
running build_ext
building 'my_library' extension
...

$ ls my_library.dylib
-rwxr-xr-x  1 djinn  staff  9856 May 15 14:46 my_library.dylib

All that remains is to use it somewhere!

Host application

Using the embedded Python code is actually really simple. It can be done with just the following code:

#include <stdio.h>
#include "api.h"

int main(void) {
    float result = compute(12.34f, 10.0f);
    printf("The result: %f\n", result);

    return 0;
}

As you can see there is hardly any work required to call our Python code. With the CPython embedding API you would have had to fire up an interpreter and do lots of parameter and return value conversions. But not with cffi! The generated library takes care of all that so you can focus on actually building stuff.

The final thing I have to show you is how to compile and run it:

$ clang -o test test.c my_library.dylib

$ ./test
The result: 2.340000

And there you have it! With only a few lines of code we have written a C program that fires up a PyPy interpreter and runs our Python code as if it was a native C function. Of course I've only shown you the basics here, but the technology is really powerful. For more information please have a look at the cffi documentation.

If you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

Change of Office

Written by Emil Loer on Apr 6, 2016 |

Big announcement today! I'm moving and setting up a new office in the Dutch city of Leeuwarden. This is a big step forward, both for the company and me personally, so I'm really excited!

During the move I might be a bit slower to respond to support inquiries, but I will be back to full speed in about three weeks. Thanks for your patience!

Simple Core Data Full Text Search With Swift and SQLite

Written by Emil Loer on Mar 22, 2016 |

In this article I want to show you my approach to providing full text search for Core Data models. It was designed for iOS apps but should work fine on OS X too.

Core Data is really awesome, but there is one part where it really lacks: searching. With NSFetchRequest you can provide a LIKE predicate to search for a substring of a property, but this is not quite flexible. The fetch request also only works on a single entity, so if you want to search within a group of entity classes you either have to use inheritance with a shared property or you're out of luck.

The good thing is that Core Data is built on SQLite and SQLite itself provides a full text search engine. So we can create a search index ourselves and use it in concert with Core Data.

Dependencies

The first thing we have to to is ensure we have access to SQLite in our project. To keep things simple I will be using the FMDB framework which provides a nice Swift/Objective-C wrapper around SQLite. FMDB can be installed with Carthage or CocoaPods, whichever you prefer.

Searchables

After inserting FMDB into our project we have to define some kind of interface for searching. To be able to index any kind of Core Data model we need a couple of extra properties, so let's introduce a protocol for this.

protocol Searchable {
    /// A list of strings that should be indexed.
    var searchableStrings: [String] { get }

    /// An NSURL that can uniquely identify this searchable object.
    var URIRepresentation: NSURL { get }
}

The Searchable protocol will tell our search index what strings should be indexed for our model. Furthermore it provides an URI which is a unique identifier for our model. This means we can fetch the model without knowing the entity. The fetching mechanism provided below can even be extended to fetch non-Core Data objects, so in theory it can be used for anything.

To use the Searchable protocol with NSManagedObject without writing too much code I made a protocol extension that provides the value for URIRepresentation.

extension Searchable where Self: NSManagedObject {
    var URIRepresentation: NSURL {
        return objectID.URIRepresentation()
    }
}

Now any NSManagedObject can be made searchable by adopting this protocol and providing the searchableStrings. An example will be given below.

The search index

In the previous section we've defined what it means to be a searchable object, but we still have to create the full text search index. For this I made the following class:

class SearchIndex {
    let databaseQueue: FMDatabaseQueue

    init() {
        let path = NSFileManager.defaultManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask)[0].URLByAppendingPathComponent("SearchIndex.sqlite").path!
        databaseQueue = FMDatabaseQueue(path: path)

        databaseQueue.inTransaction { database, rollback in
            do {
                try database.executeUpdate("CREATE VIRTUAL TABLE IF NOT EXISTS documents USING fts4(tokenize=unicode61, identifier, contents);", values: [])
            } catch {
                print("Warning: Search Index create failed: \(error)")
            }
        }
    }
}

Upon instantiation the SearchIndex class creates or opens a SearchIndex.sqlite file in the app's library directory. It then creates the full text search table if it doesn't exist already. This table is a virtual table, which means that it is actually a group of tables behind the scenes, but we don't have to worry about that.

Now we have an index, but we still have to insert something into it. So let's create a method for this.

/// Insert the searchable object into the index. Updates the searchable if it was already indexed.
func insertSearchable(object: Searchable) {
    databaseQueue.inDatabase { database in
        do {
            try database.executeUpdate("DELETE FROM documents WHERE identifier = ?;", values: [object.URIRepresentation.absoluteString])
            try database.executeUpdate("INSERT INTO documents (identifier, contents) VALUES(?, ?);", values: [object.URIRepresentation.absoluteString, object.searchableStrings.joinWithSeparator(" ")])
        } catch {
            print("Warning: Search Index insert failed: \(error)")
        }
    }
}

The insertSearchable: method inserts a Searchable into the index. Because the FTS engine in SQLite does not support INSERT OR REPLACE we have to remove any existing model from the index first. The automatic replacement of models becomes very useful later on.

Deleting an object from the index is done in the same way:

/// Delete the searchable object from the index.
func deleteSearchable(object: Searchable) {
    databaseQueue.inDatabase { database in
        do {
            try database.executeUpdate("DELETE FROM documents WHERE identifier = ?;", values: [object.URIRepresentation.absoluteString])
        } catch {
            print("Warning: Search Index insert failed: \(error)")
        }
    }
}

Now the only thing that remains is to search for objects. This can be done using the MATCH operator in the following way:

func searchForURIsWithQuery(query: String) -> [NSURL] {
    var objects = [NSURL]()

    databaseQueue.inDatabase { database in
        let results: FMResultSet

        do {
            results = try database.executeQuery("SELECT identifier FROM documents WHERE contents MATCH ?;", values: [query])
        } catch {
            print("Warning: Search Index query failed: \(error)")
            return
        }

        while results.next() {
            objects.append(NSURL(string: results.stringForColumn("identifier"))!)
        }
    }

    return objects
}

The searching itself is actually pretty straight forward. We perform a SELECT query on the virtual table and collect the results in an array which we return. If you want you can improve this method by adding relevance sorting and whatever you like.

When using the query method given above we are left with an array of NSURL instances. We will still have to convert these into NSManagedObject instances (or anything else if you're using some other kind of storage). For this I provide another method that searches directly for Core Data models:

func searchForManagedObjectsWithQuery(query: String, inManagedObjectContext managedObjectContext: NSManagedObjectContext) -> [NSManagedObject] {
    return searchForURIsWithQuery(query).flatMap { uri in
        if let objectID = managedObjectContext.persistentStoreCoordinator?.managedObjectIDForURIRepresentation(uri) {
            return managedObjectContext.objectWithID(objectID)
        } else {
            return nil
        }
    }
}

And that is the entire search index class.

Usage

Now we have our search index ready to use. Let's use it on this example entity:

class Item: NSManagedObject {
    @NSManaged var name: String?
    @NSManaged var description: String?
}

First we have to make the Item searchable by adopting the Searchable protocol.

extension item: Searchable {
    var searchableStrings: [String] {
        return [
            name,
            description
        ].flatMap { $0 }
    }
}

Now we can use it with a search index:

let item: Item // some Item created elsewhere

let index = SearchIndex()

// Insert the item into the index
index.insertSearchable(item)

// Remove the item from the index
index.removeSearchable(item)

// Search the index
let results = index.searchForManagedObjectsWithQuery("hello", inManagedObjectContext: managedObjectContext)

Note that results contains an array of NSManagedObject instances, because our index is capable of searching for multiple classes. This means that you might have to use if let binding to check for the proper types.

Final thoughts

Here I've shown you my approach to adding full text search to a Core Data app. This approach is very flexible because it can be used to search for multiple models simultaneously, and can easily be adapted to suit your specific needs.

If you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

MidiSpy 1.1 released

Written by Emil Loer on Mar 15, 2016 |

Today I'm announcing the release of MidiSpy version 1.1, now available in the Mac App Store. This update adds better compatibility on OS X El Capitan and a few cosmetic changes.

Go get it now!

Extending UITabBarItem with IBInspectable PaintCode icons

Written by Emil Loer on Mar 8, 2016 |

One of my most used tools outside of Xcode is an app called PaintCode. With PaintCode you can draw artwork that gets converted into Objective-C or Swift code to actually draw the art at runtime. This enables you to make great custom views and by making use of parameters you can even make the drawing code react to your application's state.

In this article I want to explore a particular example of how I use PaintCode in one of my iOS projects. In this project the root view controller is a UITabBarController whose tabs are extended to support PaintCode images.

If you look at Apple's apps you can see that a typical tab-based app has separate images for the selected and unselected states. These images then have to be available in 1x, 2x and 3x versions, meaning that we have to design a total of six images. And if there is a slight change in the design we have to recreate all six of them again. In my opinion this is a perfect situation for procedural images.

Creating a PaintCode canvas

The first thing we have to do is to create a canvas in PaintCode that contains our image. For this example I'm going to design a settings icon. The settings icon will use a style in which the selected state has a thicker outline. An alternative would be to change the icon's fill color which is perfectly possible using this approach too.

Let's start with creating the shape of the icon. Use a 25x25 canvas for the best results.

The shape of the icon

Now we want to create two states for this icon: the selected and the unselected state. For this we are going to introduce a boolean parameter:

The selected parameter

The parameter will be exposed to our image drawing method and we can use it in code to select which state we want to draw. However, the boolean value itself is not very useful to our shape, as we want to change the stroke width. So let's create a derived expression for this:

The stroke width expression

The variable width property now reflects the stroke width for the current selection state and we can use it in our icon as the stroke width for the outer shape.

The stroke width applied to the shape

Now when we tick the checkbox of the selected parameter we should see the icon changing between these two images:

The selected and unselected icons

The icon is now ready to be used. Make sure you export the image into a StyleKit using an image method in template mode:

StyleKit drawing method

Using the icon in UITabBarItem

Now that we have a procedurally generated icon we have to use it. Normally to do this one can subclass a view and override the drawRect: method to draw the StyleKit image from there. However, UITabBarItem is not a view and thus has no drawing methods.

From the documentation we can see that a tab bar item has an image and a selectedImage property and we can use these to provide the proper images. The simplest way to do this is to subclass the tab bar item like this:

class PaintCodeTabItem: UITabBarItem {
    override func awakeFromNib() {
        super.awakeFromNib()

        selectedImage = StyleKit.imageOfSettingsWithSelected(true)
        image = StyleKit.imageOfSettingsWithSelected(false)
    }
}

Of course you can omit the subclassing and create tab items procedurally from e.g. a view controller.

PaintCode also provides a way to set the images using outlets. This means you have to insert a StyleKit object inside every view controller that you want to access images from and drag two outlets per tab item. This feature works but is in my opinion not very flexible if you do a lot of Interface Builder work. For example, if you move views between view controllers you have to reconnect the outlets and such.

A smarter UITabBarItem

What I really wanted to do was to think of a solution that did not force me to write code for every custom tab image that I create and limit the work I have to do in Interface Builder. It turns out that Xcode has a very powerful feature called IBInspectable that we can leverage here. The general idea of inspectables is that you can tag a property to become available inside interface builder. This allows us to reuse a class for every icon and just type in the name of the icon inside the inspector.

Creating such a reusable class is not very straightforward because we have to dynamically decide which method of the StyleKit to call. That problem has already been solved though, so we can use the extractMethodFrom:selector: function from my previous article: Calling methods from strings in Swift.

Here's the implementation of the class:

class PaintCodeTabItem: UITabBarItem {
    /// The name of the PaintCode image in the form that is represented in the
    /// StyleKit method name, i.e. use "Settings" for "imageOfSettingsWithSelected:".
    @IBInspectable var name: String = ""

    override func awakeFromNib() {
        super.awakeFromNib()

        let selector = NSSelectorFromString("imageOf" + name + "WithSelected:")

        if let imageWithSelected = extractBoolMethodFrom(StyleKit.self, selector: selector) {
            selectedImage = imageWithSelected(true)
            image = imageWithSelected(false)
        } else {
            print("Warning: StyleKit does not respond to selector \(selector)")
        }
    }
}

Now when you assign the PaintCodeTabItem class to a UITabBarItem in Interface Builder you can see the following property in the inspector:

The inspectable tab item

And when we run our app we see the icon as designed in PaintCode:

The final icon

So there you have it! Simple and maintainable PaintCode tab bar icons. Of course you can extend this technique to any other user interface element. You can even create a UIView subclass that can call a StyleKit method by name in the drawRect: method. The possibilities are limitless!

If you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

Calling methods from strings in Swift

Written by Emil Loer on Feb 24, 2016 |

In this article I want to explore the various ways you can invoke a method when the only thing you have is a string containing the method's name. This can be useful when you have to decide at run-time which method to call. An example where I use this is to select the proper image method in a PaintCode StyleKit from an IBInspectable value.

Note that Swift currently only supports dynamic method invocation on objects deriving from NSObject.

Selectors from strings

The first thing we have to do is to obtain a selector from our string. A selector is basically the runtime's way of describing the name of a method. In Swift selectors are represented by the Selector type.

Because Selector adopts the StringLiteralConvertible protocol converting a string to a selector is real easy:

let selector: Selector = "addSubview:"

This however doesn't help us if we want to provide the selector from something that isn't a string literal, e.g. a string in a variable. For this we can use NSSelectorFromString:

let name = "addSubview:"
let selector = NSSelectorFromString(name)

PerformSelector

Now that we have a selector we can use it to invoke a method. For this we can use the performSelector: method family of NSObject. This method comes in three variants:

func performSelector(_ aSelector: Selector) -> Unmanaged<AnyObject>!

func performSelector(_ aSelector: Selector, withObject object: AnyObject!) -> 
    Unmanaged<AnyObject>!

func performSelector(_ aSelector: Selector, withObject object1: AnyObject!,
    withObject object2: AnyObject!) -> Unmanaged<AnyObject>!

The first version can be used to call a method expecting zero arguments and returning a object. The second version expects a single object argument and the third version expects two object arguments.

Note the use of an Unmanaged return type. When you dynamically invoke a method the compiler can't infer if the return value should be interpreted as a +1 or +0 reference. For more information about unmanaged references see this article on NSHipster.

Non-object arguments

There is a big gotcha with performSelector: and friends: it can only be used with arguments and return values that are objects! So if you have something that takes e.g. a boolean you're out of luck.

An experienced Objective-C programmer in the room would now stand up and say: "No sweat! Just use NSInvocation instead!". But try this and you get the following line of disappointment:

error: 'NSInvocation' is unavailable in Swift: NSInvocation and related APIs not available

Runtime trickery

Leveraging the power of the Objective-C runtime we can still make this work. For this example I am going to assume the method we are calling has the following signature: Bool -> UIImage, but it can be anything as long as it isn't variadic.

The first thing we have to do is do a lookup on the object for the required method. For this we can use the class_getInstanceMethod and class_getClassMethod, depending on the type of method we are looking for.

If we have an owner of type AnyObject then we can use the fact that AnyClass conforms to AnyObject to detect if we have to lookup a class or instance method:

let method: Method
if owner is AnyClass {
    method = class_getClassMethod(owner as! AnyClass, selector)
} else {
    method = class_getInstanceMethod(owner.dynamicType, selector)
}

Both functions take a class as a first argument, so in the case of an instance method we have to dynamically infer its type first. The resulting method may be nil, so don't forget to check for that with a guard method != nil clause or things will behave unexpectedly.

The Method type is an opaque struct, so the next step is to get something useful out of this. We can use method_getImplementation to get a value of type IMP. In Swift this IMP type is an opaque pointer, so not very useful. But in Objective-C this type is actually a function pointer to the method's implementation. It has two additional (hidden) arguments prefixed: a reference to self and the selector.

This means that our example Bool -> UIImage function can be mapped onto the implementation function pointer in the following way:

typealias Function = @convention(c) (AnyObject, Selector, Bool) -> Unmanaged<UIImage>

Note that here we also have to use unmanaged return values so we can manually tell Swift how to handle the reference counts.

We can obtain our method by bit casting the implementation to our function pointer type.

let implementation = method_getImplementation(method)
let function = unsafeBitCast(implementation, Function.self)

Below is the combined code for a function that takes an owner and a selector and returns a method that can be called. For ease of use the owner and selector are curried into the method implementation and the unmanaged result is interpreted as a +0 reference. The function returns nil if the method wasn't found.

func extractMethodFrom(owner: AnyObject, selector: Selector) -> (Bool -> UIImage)? {
    let method: Method
    if owner is AnyClass {
        method = class_getClassMethod(owner as! AnyClass, selector)
    } else {
        method = class_getInstanceMethod(owner.dynamicType, selector)
    }

    guard method != nil else {
        return nil
    }

    let implementation = method_getImplementation(method)

    typealias Function = @convention(c) (AnyObject, Selector, Bool) -> Unmanaged<UIImage>
    let function = unsafeBitCast(implementation, Function.self)

    return { bool in function(owner, selector, bool).takeUnretainedValue() }
}

How to use

To use this as-is you can do something like this:

let name = "imageWithBorder:" // e.g. from somewhere else
if let method = extractMethodFrom(imageGenerator, name) {
    let image = method(true)
    // Use image here
}

Of course you can freely modify the extractMethodFrom:selector: function to match any method signature you need. You can use any number of arguments and any kind of return value, just as long as you make sure that you treat the return value as unmanaged if it is an object. Optionals work fine too.

In the next post I will go more into details about how I use this technique to make the integration between UIKit and PaintCode more seamless.

In the meantime, if you've enjoyed this post please follow me on Twitter or Facebook. I'd really appreciate it!

ChordFinder 1.4.0 released

Written by Emil Loer on Feb 17, 2016 |

Today I'm announcing the release of ChordFinder version 1.4.0. This is a compatibility update bringing better support for OS X El Capitan.

Go get it now!

« Previous | 1 | Next »