Last active
March 9, 2020 13:41
-
-
Save dnedrow/ebb68dbc0a38f78a063a60445ca233d4 to your computer and use it in GitHub Desktop.
"Stored properties" for Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Created by Nedrow, David E on 2/21/18. | |
| // This work is licensed under Attribution 4.0 International (CC 4.0) | |
| import Foundation | |
| /// Mechanism that provides something resembling stored properties for extensions. | |
| /// | |
| /// Usage: | |
| /// | |
| /// 1. Extend your class with the PropertyStoring protocol. | |
| /// 2. Create a private struct containing the properties to be used. | |
| /// 3. Implement a public var{get{} set{}} for each of the private properties. | |
| /// | |
| /// Example: | |
| /// ``` | |
| /// protocol ToggleProtocol { | |
| /// func toggle() | |
| /// } | |
| /// | |
| /// enum ToggleState { | |
| /// case on | |
| /// case off | |
| /// } | |
| /// | |
| /// extension UIButton: ToggleProtocol, PropertyStoring { | |
| /// | |
| /// private struct CustomProperties { | |
| /// static var toggleState = false | |
| /// } | |
| /// | |
| /// var toggleState: ToggleState { | |
| /// get { | |
| /// return getAssociatedObject(&CustomProperties.hidden, defaultValue: CustomProperties.hidden) | |
| /// } | |
| /// set { | |
| /// return objc_setAssociatedObject(self, &CustomProperties.hidden, newValue, .OBJC_ASSOCIATION_RETAIN) | |
| /// } | |
| /// } | |
| /// | |
| /// func toggle() { | |
| /// toggleState = toggleState == .on ? .off : .on | |
| /// | |
| /// if toggleState == .on { | |
| /// // Shows background for status on | |
| /// } else { | |
| /// // Shows background for status off | |
| /// } | |
| /// } | |
| /// } | |
| /// ``` | |
| protocol PropertyStoring { | |
| /// Returns the value associated with a given object for a given key. | |
| /// | |
| /// - Parameters: | |
| /// - object: The source object for the association. | |
| /// - key: The key for the association. | |
| /// - defaultValue: Value to return if association not found. | |
| /// - Returns: The value associated with the key for the object. | |
| /// - SeeAlso: | |
| /// [objc_getAssociatedObject](https://developer.apple.com/documentation/objectivec/1418865-objc_getassociatedobject) | |
| func getAssociated<T>(_ object: Any!, _ key: UnsafeRawPointer!, defaultValue: T) -> T | |
| /// Sets an associated value for a given object using a given key and association policy. | |
| /// | |
| /// - Parameters: | |
| /// - object: The source object for the association. | |
| /// - value: The value to associate with the key key for object. Pass nil to clear an existing association. | |
| /// - associativeKey: The key for the association. | |
| /// - policy: The policy for the association. For possible values, see [Associated Objects](http://nshipster.com/associated-objects/) | |
| /// SeeAlso: | |
| /// [objc_setAssociatedObject](https://developer.apple.com/documentation/objectivec/1418509-objc_setassociatedobject) | |
| func setAssociated<T>(object: AnyObject, value: T, associativeKey: UnsafeRawPointer, policy: objc_AssociationPolicy) | |
| } | |
| extension PropertyStoring { | |
| func getAssociated<T>(_ object: Any!, _ key: UnsafeRawPointer!, defaultValue: T) -> T { | |
| guard let value: T = objc_getAssociatedObject(object, key) as? T else { | |
| return defaultValue | |
| } | |
| return value | |
| } | |
| func setAssociated<T>(object: AnyObject, value: T, associativeKey: UnsafeRawPointer, policy: objc_AssociationPolicy) { | |
| objc_setAssociatedObject(object, associativeKey, value, policy) | |
| } | |
| } | |
| // This work is licensed under Attribution 4.0 International (CC 4.0) | |
| // You are free to: | |
| // Share — copy and redistribute the material in any medium or format | |
| // Adapt — remix, transform, and build upon the material | |
| // for any purpose, even commercially. | |
| // | |
| // This license is acceptable for Free Cultural Works. | |
| // The licensor cannot revoke these freedoms as long as you follow the license terms. | |
| // See https://creativecommons.org/licenses/by/4.0/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment