Search code examples
swiftextension-methodsxibswift5

objc_getAssociatedObject and Runtime attributes


I have the following extension which was used to automatically save/retrieve runtime attributes unique to a UIImageView:

import UIKit

var imgAttributeKey:String? = nil

extension UIImageView {
    
    var imgAttribute: String? {
        get { return objc_getAssociatedObject(self, &imgAttributeKey) as? String }
        set { objc_setAssociatedObject(self, &imgAttributeKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
    }
    
}

enter image description here

This was working fine but after trying the code again recently, the getters were always returning nil. Did something change in Swift 5 version that could be breaking this implementation? Any suggestions on how to go about it?


Solution

  • Thanks to Tarun Tyagi for pointing out the correct fix.

    @objc needs to be added to the property reference in the extension. Incorrectly marking the outside property results in a objc can only be used with members of classes, @objc protocols, and concrete extensions of classes error.

    Working code is as follows:

    import UIKit
    
    var imgAttributeKey:String? = nil
    
    extension UIImageView {
        
        @objc var imgAttribute: String? {
            get { return objc_getAssociatedObject(self, &imgAttributeKey) as? String }
            set { objc_setAssociatedObject(self, &imgAttributeKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
        }
        
    }
    

    The reason why this was needed it that this project was originally written in Swift 3 but starting from Swift 4, an explicit annotation @objc for dynamic Objective-C features (such as User Defined Runtime Attributes) is required.