With Swift 2.2 using the Objective-C runtime is a lot easier. An improved way of working with Selector
s 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 UIView
s. 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.