-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Using property wrappers like this crashes Xcode
At least as of Xcode 11.5. Here's hoping 12 fixes it.
- Loading branch information
Showing
3 changed files
with
186 additions
and
186 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,37 @@ | ||
import Foundation | ||
|
||
|
||
|
||
@propertyWrapper | ||
public struct Forgetful<Value> { | ||
private var value: Value? | ||
private let factory: () -> Value | ||
|
||
|
||
public var wrappedValue: Value { | ||
mutating get { | ||
guard let someValue = value else { | ||
return given(factory()) { | ||
value = $0 | ||
} | ||
} | ||
return someValue | ||
} | ||
} | ||
|
||
|
||
public init(wrappedValue: @autoclosure @escaping () -> Value) { | ||
factory = wrappedValue | ||
} | ||
|
||
|
||
public mutating func forget() { | ||
value = nil | ||
} | ||
|
||
|
||
public var projectedValue: Self { | ||
get { return self } | ||
set { self = newValue } | ||
} | ||
} | ||
//import Foundation | ||
// | ||
// | ||
// | ||
//@propertyWrapper | ||
//public struct Forgetful<Value> { | ||
// private var value: Value? | ||
// private let factory: () -> Value | ||
// | ||
// | ||
// public var wrappedValue: Value { | ||
// mutating get { | ||
// guard let someValue = value else { | ||
// return given(factory()) { | ||
// value = $0 | ||
// } | ||
// } | ||
// return someValue | ||
// } | ||
// } | ||
// | ||
// | ||
// public init(wrappedValue: @autoclosure @escaping () -> Value) { | ||
// factory = wrappedValue | ||
// } | ||
// | ||
// | ||
// public mutating func forget() { | ||
// value = nil | ||
// } | ||
// | ||
// | ||
// public var projectedValue: Self { | ||
// get { return self } | ||
// set { self = newValue } | ||
// } | ||
//} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,73 @@ | ||
import XCTest | ||
import BagOfTricks | ||
|
||
|
||
|
||
class ForgetfulTests: XCTestCase { | ||
func testFactoryCalls() { | ||
let factoryCalled = expectation(description: "Forgetful has reinitialized its value") | ||
factoryCalled.expectedFulfillmentCount = 2 | ||
|
||
var subject = Forgetful<Int>(wrappedValue: { | ||
factoryCalled.fulfill() | ||
return 42 | ||
}()) | ||
|
||
XCTAssertEqual(subject.wrappedValue, 42) | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
subject.forget() | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
|
||
wait(for: [factoryCalled], timeout: 0) | ||
} | ||
|
||
|
||
func testForgets() { | ||
class Ref { | ||
var value: String = "hello" | ||
} | ||
let ref = Ref() | ||
|
||
var subject = Forgetful(wrappedValue: ref.value) | ||
|
||
XCTAssertEqual(subject.wrappedValue, "hello") | ||
ref.value = "foo" | ||
XCTAssertEqual(subject.wrappedValue, "hello") | ||
subject.forget() | ||
XCTAssertEqual(subject.wrappedValue, "foo") | ||
} | ||
|
||
|
||
func testLazy() { | ||
let subject = Forgetful<Int>(wrappedValue: { | ||
XCTFail() | ||
return 42 | ||
}()) | ||
|
||
XCTAssertNotNil(subject) | ||
} | ||
|
||
|
||
func testLazyForget() { | ||
let factoryCalled = expectation(description: "Forgetful has reinitialized its value") | ||
|
||
var subject = Forgetful<Int>(wrappedValue: { | ||
factoryCalled.fulfill() | ||
return 42 | ||
}()) | ||
|
||
XCTAssertEqual(subject.wrappedValue, 42) | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
XCTAssertEqual(subject.wrappedValue, 42) | ||
subject.forget() | ||
subject.forget() | ||
subject.forget() | ||
subject.forget() | ||
subject.forget() | ||
|
||
wait(for: [factoryCalled], timeout: 0) | ||
} | ||
} | ||
//import XCTest | ||
//import BagOfTricks | ||
// | ||
// | ||
// | ||
//class ForgetfulTests: XCTestCase { | ||
// func testFactoryCalls() { | ||
// let factoryCalled = expectation(description: "Forgetful has reinitialized its value") | ||
// factoryCalled.expectedFulfillmentCount = 2 | ||
// | ||
// var subject = Forgetful<Int>(wrappedValue: { | ||
// factoryCalled.fulfill() | ||
// return 42 | ||
// }()) | ||
// | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// subject.forget() | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// | ||
// wait(for: [factoryCalled], timeout: 0) | ||
// } | ||
// | ||
// | ||
// func testForgets() { | ||
// class Ref { | ||
// var value: String = "hello" | ||
// } | ||
// let ref = Ref() | ||
// | ||
// var subject = Forgetful(wrappedValue: ref.value) | ||
// | ||
// XCTAssertEqual(subject.wrappedValue, "hello") | ||
// ref.value = "foo" | ||
// XCTAssertEqual(subject.wrappedValue, "hello") | ||
// subject.forget() | ||
// XCTAssertEqual(subject.wrappedValue, "foo") | ||
// } | ||
// | ||
// | ||
// func testLazy() { | ||
// let subject = Forgetful<Int>(wrappedValue: { | ||
// XCTFail() | ||
// return 42 | ||
// }()) | ||
// | ||
// XCTAssertNotNil(subject) | ||
// } | ||
// | ||
// | ||
// func testLazyForget() { | ||
// let factoryCalled = expectation(description: "Forgetful has reinitialized its value") | ||
// | ||
// var subject = Forgetful<Int>(wrappedValue: { | ||
// factoryCalled.fulfill() | ||
// return 42 | ||
// }()) | ||
// | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// XCTAssertEqual(subject.wrappedValue, 42) | ||
// subject.forget() | ||
// subject.forget() | ||
// subject.forget() | ||
// subject.forget() | ||
// subject.forget() | ||
// | ||
// wait(for: [factoryCalled], timeout: 0) | ||
// } | ||
//} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,76 @@ | ||
import XCTest | ||
import BagOfTricks | ||
|
||
|
||
private class Ref { | ||
var value: String? | ||
var count: Int = 0 | ||
} | ||
private let ref = Ref() | ||
|
||
|
||
class ForgetfulWrapperTests: XCTestCase { | ||
// This strange formulation of passing the closure in a param instead of as a default value is [required by SR-10950](https://bugs.swift.org/browse/SR-10950). It will probably be fixed in the next Swift release following 5.1. | ||
@Forgetful(wrappedValue: { | ||
ref.count += 1 | ||
return ref.value! | ||
}()) var lazy: String | ||
|
||
|
||
override func setUp() { | ||
ref.value = nil | ||
ref.count = 0 | ||
} | ||
|
||
|
||
func testIsLazy() { | ||
XCTAssertNil(ref.value) | ||
XCTAssertEqual(ref.count, 0) | ||
ref.value = "foo" | ||
XCTAssertEqual(lazy, "foo") | ||
XCTAssertEqual(ref.count, 1) | ||
|
||
_ = lazy | ||
_ = lazy | ||
_ = lazy | ||
XCTAssertEqual(ref.count, 1) | ||
|
||
ref.value = "bar" | ||
|
||
_ = lazy | ||
XCTAssertEqual(lazy, "foo") | ||
XCTAssertEqual(ref.count, 1) | ||
} | ||
|
||
|
||
func testForget() { | ||
ref.value = "foo" | ||
_ = lazy | ||
ref.value = "bar" | ||
|
||
$lazy.forget() | ||
XCTAssertEqual(lazy, "bar") | ||
XCTAssertEqual(ref.count, 2) | ||
} | ||
|
||
|
||
func testForgetIsLazy() { | ||
ref.value = "foo" | ||
_ = lazy | ||
ref.value = "bar" | ||
_ = lazy | ||
XCTAssertEqual(lazy, "foo") | ||
XCTAssertEqual(ref.count, 1) | ||
|
||
$lazy.forget() | ||
XCTAssertEqual(lazy, "bar") | ||
XCTAssertEqual(ref.count, 2) | ||
|
||
_ = lazy | ||
_ = lazy | ||
_ = lazy | ||
XCTAssertEqual(lazy, "bar") | ||
XCTAssertEqual(ref.count, 2) | ||
} | ||
|
||
} | ||
//import XCTest | ||
//import BagOfTricks | ||
// | ||
// | ||
//private class Ref { | ||
// var value: String? | ||
// var count: Int = 0 | ||
//} | ||
//private let ref = Ref() | ||
// | ||
// | ||
//class ForgetfulWrapperTests: XCTestCase { | ||
// // This strange formulation of passing the closure in a param instead of as a default value is [required by SR-10950](https://bugs.swift.org/browse/SR-10950). It will probably be fixed in the next Swift release following 5.1. | ||
// @Forgetful(wrappedValue: { | ||
// ref.count += 1 | ||
// return ref.value! | ||
// }()) var lazy: String | ||
// | ||
// | ||
// override func setUp() { | ||
// ref.value = nil | ||
// ref.count = 0 | ||
// } | ||
// | ||
// | ||
// func testIsLazy() { | ||
// XCTAssertNil(ref.value) | ||
// XCTAssertEqual(ref.count, 0) | ||
// ref.value = "foo" | ||
// XCTAssertEqual(lazy, "foo") | ||
// XCTAssertEqual(ref.count, 1) | ||
// | ||
// _ = lazy | ||
// _ = lazy | ||
// _ = lazy | ||
// XCTAssertEqual(ref.count, 1) | ||
// | ||
// ref.value = "bar" | ||
// | ||
// _ = lazy | ||
// XCTAssertEqual(lazy, "foo") | ||
// XCTAssertEqual(ref.count, 1) | ||
// } | ||
// | ||
// | ||
// func testForget() { | ||
// ref.value = "foo" | ||
// _ = lazy | ||
// ref.value = "bar" | ||
// | ||
// $lazy.forget() | ||
// XCTAssertEqual(lazy, "bar") | ||
// XCTAssertEqual(ref.count, 2) | ||
// } | ||
// | ||
// | ||
// func testForgetIsLazy() { | ||
// ref.value = "foo" | ||
// _ = lazy | ||
// ref.value = "bar" | ||
// _ = lazy | ||
// XCTAssertEqual(lazy, "foo") | ||
// XCTAssertEqual(ref.count, 1) | ||
// | ||
// $lazy.forget() | ||
// XCTAssertEqual(lazy, "bar") | ||
// XCTAssertEqual(ref.count, 2) | ||
// | ||
// _ = lazy | ||
// _ = lazy | ||
// _ = lazy | ||
// XCTAssertEqual(lazy, "bar") | ||
// XCTAssertEqual(ref.count, 2) | ||
// } | ||
// | ||
//} |