Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions QLoop.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@
DCC759272241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; };
DCC759282241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; };
DCC759292241D04100B4750E /* QLoop+ConvenienceInitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC759262241D04100B4750E /* QLoop+ConvenienceInitTests.swift */; };
DCFACAEB22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
DCFACAEC22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
DCFACAED22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
DCFACAEE22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -250,6 +254,7 @@
DCD9D7C3223DDE0900BBDEE2 /* QLoop.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLoop.md; sourceTree = "<group>"; };
DCD9D7C4223DDF8900BBDEE2 /* QLParallelSegment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLParallelSegment.md; sourceTree = "<group>"; };
DCD9D7C5223DE0C800BBDEE2 /* QLSerialSegment.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = QLSerialSegment.md; sourceTree = "<group>"; };
DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+ErrorGettable.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -386,6 +391,7 @@
DC6FAF5D222F4EF5008BB070 /* QLAnchor.swift */,
DC5E449E224AFC2B0007FEAD /* QLAnchor+ConvenienceInit.swift */,
DC8F2B58223342E000277F70 /* QLPath.swift */,
DCFACAEA22D826C5004D6D7A /* Result+ErrorGettable.swift */,
DCF860BF2239D02B0018C1A1 /* Common */,
DC374A322231F28A006F1272 /* Iterating */,
DCA1FD232230C8E5006015BD /* Segment */,
Expand Down Expand Up @@ -740,6 +746,7 @@
DCA1FD1F2230C8DB006015BD /* QLSegment.swift in Sources */,
DC374A372231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
DCA1FD0C22303D22006015BD /* QLoop.swift in Sources */,
DCFACAEB22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
DC413D23223B191300000480 /* QLCommon.swift in Sources */,
DC6FAF5E222F4EF5008BB070 /* QLAnchor.swift in Sources */,
DC374A412231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
Expand All @@ -764,6 +771,7 @@
DCA1FD202230C8DB006015BD /* QLSegment.swift in Sources */,
DC374A342231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
DCA1FD0D22303D22006015BD /* QLoop.swift in Sources */,
DCFACAEC22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
DC413D24223B191300000480 /* QLCommon.swift in Sources */,
DC6FAF5F222F4EF5008BB070 /* QLAnchor.swift in Sources */,
DC374A3E2231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
Expand All @@ -788,6 +796,7 @@
DCA1FD212230C8DB006015BD /* QLSegment.swift in Sources */,
DC374A352231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
DCA1FD0E22303D22006015BD /* QLoop.swift in Sources */,
DCFACAED22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
DC413D25223B191300000480 /* QLCommon.swift in Sources */,
DC6FAF60222F4EF5008BB070 /* QLAnchor.swift in Sources */,
DC374A3F2231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
Expand All @@ -812,6 +821,7 @@
DCA1FD222230C8DB006015BD /* QLSegment.swift in Sources */,
DC374A362231F2AD006F1272 /* QLoopIteratorContinueNilMax.swift in Sources */,
DCA1FD0F22303D22006015BD /* QLoop.swift in Sources */,
DCFACAEE22D826C5004D6D7A /* Result+ErrorGettable.swift in Sources */,
DC413D26223B191300000480 /* QLCommon.swift in Sources */,
DC6FAF61222F4EF5008BB070 /* QLAnchor.swift in Sources */,
DC374A402231F361006F1272 /* QLoopIteratorContinueNil.swift in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions Sources/QLoop/Common/QLCommon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public struct QLCommon {
return false
#endif
}()

public static var autoThrowResultFailures: Bool = true
}
}

Expand Down
13 changes: 10 additions & 3 deletions Sources/QLoop/QLAnchor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ public final class QLAnchor<Input>: AnyAnchor {
public typealias OnChange = (Input?)->()
public typealias OnError = (Error)->()

lazy var inputQueue = DispatchQueue(label: "\(self).inputQueue")
lazy var inputQueue = DispatchQueue(label: "\(self).inputQueue",
qos: .userInitiated)

public required init(onChange: @escaping OnChange,
onError: @escaping OnError) {
Expand All @@ -24,8 +25,14 @@ public final class QLAnchor<Input>: AnyAnchor {
}
set {
inputQueue.sync { self._value = newValue }
DispatchQueue.main.async {
self.onChange(newValue)
if QLCommon.Config.Anchor.autoThrowResultFailures,
let errGettable = newValue as? ErrorGettable,
let err = errGettable.getError() {
self.error = err
} else {
DispatchQueue.main.async {
self.onChange(newValue)
}
}

if (QLCommon.Config.Anchor.releaseValues) {
Expand Down
12 changes: 12 additions & 0 deletions Sources/QLoop/Result+ErrorGettable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
internal protocol ErrorGettable {
func getError() -> Error?
}

extension Result: ErrorGettable {
func getError() -> Error? {
if case let .failure(err) = self {
return err
}
return nil
}
}
36 changes: 31 additions & 5 deletions Tests/QLoopTests/QLAnchorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,48 @@ final class QLAnchorTests: XCTestCase {
func test_when_input_set_then_it_invokes_onChange() {
var received: Int = -1
let expect = expectation(description: "should set")

let subject = QLAnchor<Int>(onChange: { received = $0!; expect.fulfill() })

subject.value = 99

wait(for: [expect], timeout: 8.0)
XCTAssertEqual(received, 99)
}

func test_when_input_set_is_result_error_then_it_invokes_onError_and_not_onChange() {
var receivedInput: Result<Int, Error>? = nil
var receivedError: Error? = nil
let expect = expectation(description: "should error")
let subject = QLAnchor<Result<Int, Error>>(onChange: { receivedInput = $0; expect.fulfill() },
onError: { receivedError = $0; expect.fulfill() })

subject.value = .failure(QLCommon.Error.Unknown)

wait(for: [expect], timeout: 8.0)
XCTAssertNil(receivedInput)
XCTAssertNotNil(receivedError)
}

func test_when_input_set_is_result_value_then_it_invokes_onChange_and_not_onError_like_normal() {
var receivedInput: Result<Int, Error>? = nil
var receivedError: Error? = nil
let expect = expectation(description: "should value")
let subject = QLAnchor<Result<Int, Error>>(onChange: { receivedInput = $0; expect.fulfill() },
onError: { receivedError = $0; expect.fulfill() })

subject.value = .success(11)

wait(for: [expect], timeout: 8.0)
XCTAssertNotNil(receivedInput)
XCTAssertNil(receivedError)
}

func test_when_error_set_then_it_invokes_onError() {
var receivedError: Error? = nil
let expect = expectation(description: "should set")

let subject = QLAnchor<Int>(onChange: { _ in },
onError: { receivedError = $0; expect.fulfill() })
subject.onChange(nil)

subject.error = QLCommon.Error.Unknown

wait(for: [expect], timeout: 8.0)
Expand All @@ -45,10 +72,9 @@ final class QLAnchorTests: XCTestCase {
func test_when_error_set_nil_then_it_invokes_onError_with_ErrorThrownButNotSet() {
var receivedError: Error? = nil
let expect = expectation(description: "should set")

let subject = QLAnchor<Int>(onChange: { _ in },
onError: { receivedError = $0; expect.fulfill() })
subject.onChange(nil)

subject.error = nil

wait(for: [expect], timeout: 8.0)
Expand Down