https://github.com/p-x9/associatedobject
๐ Swift Macro for allowing variable declarations even in class extensions
https://github.com/p-x9/associatedobject
macros swiftmacros swiftpackage swiftpackagemanager
Last synced: 9 months ago
JSON representation
๐ Swift Macro for allowing variable declarations even in class extensions
- Host: GitHub
- URL: https://github.com/p-x9/associatedobject
- Owner: p-x9
- License: mit
- Created: 2023-06-12T02:12:30.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-11-28T09:31:07.000Z (about 1 year ago)
- Last Synced: 2025-03-29T15:08:20.302Z (9 months ago)
- Topics: macros, swiftmacros, swiftpackage, swiftpackagemanager
- Language: Swift
- Homepage:
- Size: 294 KB
- Stars: 134
- Watchers: 1
- Forks: 4
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# AssociatedObject
Swift Macro for allowing variable declarations even in class extensions.
It is implemented by wrapping `objc_getAssociatedObject`/`objc_setAssociatedObject`.
[](https://github.com/p-x9/AssociatedObject/issues)
[](https://github.com/p-x9/AssociatedObject/network/members)
[](https://github.com/p-x9/AssociatedObject/stargazers)
[](https://github.com/p-x9/AssociatedObject/)
## Installation
#### SPM
```swift
.package(url: "https://github.com/p-x9/AssociatedObject", from: "0.10.3")
```
#### CocoaPods
Add below to your `Podfile`.
```
pod 'AssociatedObject', git: 'https://github.com/p-x9/AssociatedObject', tag: '0.10.3'
```
After `pod install`, you can use this Macro in your project.
Additionally, if you encounter build error like `Expansion of macro 'AssociatedObject' did not produce a non-observing accessor`. You should check your project setting `Build Settings`-`OTHER_SWIFT_FLAGS`.
There should be additional flags like so.

If not, you can add these two lines by yourself.
```
-load-plugin-executable
${PODS_ROOT}/AssociatedObject/Binary/AssociatedObjectPlugin#AssociatedObjectPlugin
```
## Usage
For example, you can add a new stored property to `UIViewController` by declaring the following
```swift
import AssociatedObject
extension UIViewController {
@AssociatedObject(.retain(nonatomic))
var text = "text"
/* OR */
@AssociatedObject(.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
var text = "text"
static var customKey = ""
@AssociatedObject(.OBJC_ASSOCIATION_RETAIN_NONATOMIC, key: customKey)
var somevar = "text"
}
```
Declared properties can be used as follows
```swift
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print(text) // => "text"
text = "hello"
print(text) // => "hello"
}
}
```
### willSet/didSet
Properties defined using `@AssociatedObject` can implement willSet and didSet.
In swift, it is not possible to implement `willSet` and `didSet` at the same time as setter, so they are expanded as follows.
```swift
@AssociatedObject(.copy(nonatomic))
public var hello: String = "ใใใซใกใฏ" {
didSet {
print("didSet")
}
willSet {
print("willSet: \(newValue)")
}
}
// โโโ expand to ... โโโ
public var hello: String = "ใใใซใกใฏ" {
get {
objc_getAssociatedObject(
self,
&Self.__associated_helloKey
) as? String
?? "ใใใซใกใฏ"
}
set {
let willSet: (String) -> Void = { [self] newValue in
print("willSet: \(newValue)")
}
willSet(newValue)
let oldValue = hello
objc_setAssociatedObject(
self,
&Self.__associated_helloKey,
newValue,
.copy(nonatomic)
)
let didSet: (String) -> Void = { [self] oldValue in
print("didSet")
}
didSet(oldValue)
}
}
```
## License
AssociatedObject is released under the MIT License. See [LICENSE](./LICENSE)