Swift 2.2 and the Objective-C Runtime

With Swift 2.2 using the Objective-C runtime is a lot easier. An improved way of working with Selectors allows for the ditching of the old 'stringly' typed handling of Selector in Swift and adds the new #selector(Class.method). This new syntax does have it's quirks though:

  • Functions for use as a Selector must be exposed to Objective-C. You can do this by marking the function as @objc like this: @objc func buttonTapped() { … }

  • The Selector must be tied to the class under which it exists. For example, a common use case would be calling removeFromSuperview on each UIView in an array of UIViews. In Objective-C it would look like this: [subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    and now in Swift 2.2, it looks like this: subviews.makeObjectsPerformSelector(#selector(UIView.removeFromSuperview))

The biggest help for my personal needs is the return of accessing the memory address of a variable using the classic &. This stopped working and I noticed it with Swift 2.1, but I don't know when it happened. Now though, we can once again do this:

var associatedKey = "associatedKey"

objc_setAssociatedObject(self, &associatedKey, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

Before 2.2 I was noticing problems with the automatic bridging of a Swift String to an NSString. A Swift String is a struct but accessing the memory address of a variable only works with classes. The reason it would work with a String is because of the automatic bridging to NSString, but this would mean that the memory address of the NSString was different on each use, and so the associated object could not be reliably fetched using the key. Previously I got around this by explicitly marking the key as an NSString, bypassing the bridging. However, this too has been resolved, but I don't know how because from my debugging the memory address is still different each time. If anybody knows what's going on I would genuinely love to know.