-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathAssociation.swift
More file actions
78 lines (68 loc) · 3.21 KB
/
Copy pathAssociation.swift
File metadata and controls
78 lines (68 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//
// Association.swift
// Rex
//
// Created by Neil Pankey on 6/19/15.
// Copyright (c) 2015 Neil Pankey. All rights reserved.
//
import ReactiveSwift
/// Attaches a `MutableProperty` value to the `host` object using KVC to get the initial
/// value and write subsequent updates from the property's producer. Note that `keyPath`
/// is a `StaticString` because it's pointer value is used as key value when associating
/// the property.
///
/// This can be used as an alternative to `DynamicProperty` for creating strongly typed
/// bindings on Cocoa objects.
public func associatedProperty(_ host: AnyObject, keyPath: StaticString) -> MutableProperty<String> {
let initial: (AnyObject) -> String = { host in
host.value(forKeyPath: keyPath.description) as? String ?? ""
}
let setter: (AnyObject, String) -> () = { host, newValue in
host.setValue(newValue, forKeyPath: keyPath.description)
}
return associatedProperty(host, key: keyPath.utf8Start, initial: initial, setter: setter)
}
/// Attaches a `MutableProperty` value to the `host` object using KVC to get the initial
/// value and write subsequent updates from the property's producer. Note that `keyPath`
/// is a `StaticString` because it's pointer value is used as key value when associating
/// the property.
///
/// This can be used as an alternative to `DynamicProperty` for creating strongly typed
/// bindings on Cocoa objects.
public func associatedProperty<T>(_ host: AnyObject, keyPath: StaticString, placeholder: () -> T) -> MutableProperty<T> {
let setter: (AnyObject, T) -> () = { host, newValue in
host.setValue(newValue, forKeyPath: keyPath.description)
}
return associatedProperty(host, key: keyPath.utf8Start, initial: { host in
host.value(forKeyPath: keyPath.description) as? T ?? placeholder()
}, setter: setter)
}
/// Attaches a `MutableProperty` value to the `host` object under `key`. The property is
/// initialized with the result of `initial`. Changes on the property's producer are
/// monitored and written to `setter`.
///
/// This can be used as an alternative to `DynamicProperty` for creating strongly typed
/// bindings on Cocoa objects.
public func associatedProperty<Host: AnyObject, T>(_ host: Host, key: UnsafeRawPointer, initial: (Host) -> T, setter: @escaping (Host, T) -> (), setUp: (MutableProperty<T>) -> () = { _ in }) -> MutableProperty<T> {
return associatedObject(host, key: key) { host in
let property = MutableProperty(initial(host))
setUp(property)
property.producer.startWithValues { [weak host] next in
if let host = host {
setter(host, next)
}
}
return property
}
}
/// On first use attaches the object returned from `initial` to the `host` object using
/// `key` via `objc_setAssociatedObject`. On subsequent usage, returns said object via
/// `objc_getAssociatedObject`.
public func associatedObject<Host: AnyObject, T>(_ host: Host, key: UnsafeRawPointer, initial: (Host) -> T) -> T {
var value = objc_getAssociatedObject(host, key) as? T
if value == nil {
value = initial(host)
objc_setAssociatedObject(host, key, value, .OBJC_ASSOCIATION_RETAIN)
}
return value!
}