document `weak(self, in:)` and add more tests
This commit is contained in:
parent
b2ca11115d
commit
560220369a
|
@ -171,6 +171,12 @@ Unwrap collection, shorthand for `compactMap { $0 }`:
|
|||
let nonOptionals = optionalsCollection.compact
|
||||
```
|
||||
|
||||
Avoid retain cycles when passing a member function as an @escaping closure:
|
||||
|
||||
```swift
|
||||
var closure = weak(self, in: MyClass.someFunction)
|
||||
```
|
||||
|
||||
### TimeInterval
|
||||
|
||||
Standard time intervals:
|
||||
|
|
|
@ -61,9 +61,11 @@ extension IndexSet: DefaultConstructible {}
|
|||
extension CharacterSet: DefaultConstructible {}
|
||||
extension NSObject: DefaultConstructible {}
|
||||
|
||||
/// Pass a member function as an @escaping closure without retaining its object.
|
||||
// based on https://sveinhal.github.io/2016/03/16/retain-cycles-function-references/
|
||||
|
||||
/// Sweeter: Pass a member function as an @escaping closure without retaining its object.
|
||||
///
|
||||
/// Example: `var fooRef = weak(self, in: MyClass.foo)`
|
||||
/// Example: `var closure = weak(self, in: MyClass.someFunction)`
|
||||
public func weak<T: AnyObject>(_ instance: T, in classFunction: @escaping (T) -> () -> Void) -> () -> Void {
|
||||
return { [weak instance] in
|
||||
guard let instance = instance else { return }
|
||||
|
@ -71,9 +73,9 @@ public func weak<T: AnyObject>(_ instance: T, in classFunction: @escaping (T) ->
|
|||
}
|
||||
}
|
||||
|
||||
/// Pass a member function as an @escaping closure without retaining its object.
|
||||
/// Sweeter: Pass a member function as an @escaping closure without retaining its object.
|
||||
///
|
||||
/// Example: `var fooRef = weak(self, in: MyClass.foo)`
|
||||
/// Example: `var closure = weak(self, in: MyClass.someFunction)`
|
||||
public func weak<T: AnyObject, U>(_ instance: T, in classFunction: @escaping (T) -> (U) -> Void) -> (U) -> Void {
|
||||
return { [weak instance] arguments in
|
||||
guard let instance = instance else { return }
|
||||
|
@ -81,9 +83,9 @@ public func weak<T: AnyObject, U>(_ instance: T, in classFunction: @escaping (T)
|
|||
}
|
||||
}
|
||||
|
||||
/// Pass a member function as an @escaping closure without retaining its object.
|
||||
/// Sweeter: Pass a member function as an @escaping closure without retaining its object.
|
||||
///
|
||||
/// Example: `var fooRef = weak(self, in: MyClass.foo)`
|
||||
/// Example: `var closure = weak(self, in: MyClass.someFunction)`
|
||||
public func weak<T: AnyObject, V: DefaultConstructible>(_ instance: T, in classFunction: @escaping (T) -> () -> V) -> () -> V {
|
||||
return { [weak instance] in
|
||||
guard let instance = instance else { return V() }
|
||||
|
@ -91,9 +93,9 @@ public func weak<T: AnyObject, V: DefaultConstructible>(_ instance: T, in classF
|
|||
}
|
||||
}
|
||||
|
||||
/// Pass a member function as an @escaping closure without retaining its object.
|
||||
/// Sweeter: Pass a member function as an @escaping closure without retaining its object.
|
||||
///
|
||||
/// Example: `var fooRef = weak(self, in: MyClass.foo)`
|
||||
/// Example: `var closure = weak(self, in: MyClass.someFunction)`
|
||||
public func weak<T: AnyObject, U, V: DefaultConstructible>(_ instance: T, in classFunction: @escaping (T) -> (U) -> V) -> (U) -> V {
|
||||
return { [weak instance] arguments in
|
||||
guard let instance = instance else { return V() }
|
||||
|
|
|
@ -28,11 +28,22 @@ class SwiftTests: XCTestCase {
|
|||
func testWeakSelfInMemberFunction() {
|
||||
class Foo: DefaultConstructible {
|
||||
static var refCount = 0
|
||||
|
||||
func foo() {}
|
||||
func fooWithParam(n: Int) {}
|
||||
func fooWithReturn() -> String { "" }
|
||||
func fooWithParamAndReturn(array: [Character]) -> Double { 0 }
|
||||
|
||||
lazy var fooRef = weak(self, in: Foo.foo)
|
||||
lazy var fooWithParamRef = weak(self, in: Foo.fooWithParam)
|
||||
lazy var fooWithReturnRef = weak(self, in: Foo.fooWithReturn)
|
||||
lazy var fooWithParamAndReturnRef = weak(self, in: Foo.fooWithParamAndReturn)
|
||||
|
||||
required init() {
|
||||
fooRef()
|
||||
fooWithParamRef(7)
|
||||
_ = fooWithReturn()
|
||||
_ = fooWithParamAndReturnRef([])
|
||||
Foo.refCount += 1
|
||||
}
|
||||
|
||||
|
@ -41,6 +52,8 @@ class SwiftTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
XCTAssertEqual(Foo.refCount, 0)
|
||||
|
||||
for _ in 0 ..< 3 {
|
||||
let aFoo = Foo()
|
||||
aFoo.foo()
|
||||
|
|
Loading…
Reference in New Issue