-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Introduced `UIEventReceiver` - Eliminated the need to implement a boilerplate Closure to invoke `callTypedEventCallback` in order to type-qualify an `Eventable` for a Callback call. This is now done internally for you. - Updated the README.MD file to reflect the above
- Loading branch information
Showing
6 changed files
with
174 additions
and
18 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
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
19 changes: 19 additions & 0 deletions
19
Sources/EventDrivenSwift/UIEventReceiver/UIEventReceivable.swift
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 |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// | ||
// UIEventReceivable.swift | ||
// Copyright (c) 2022, Flowduino | ||
// Authored by Simon J. Stuart on 11th August 2022 | ||
// | ||
// Subject to terms, restrictions, and liability waiver of the MIT License | ||
// | ||
|
||
import Foundation | ||
|
||
/** | ||
Protocol describing anything that Receives Events on the UI Thread | ||
- Author: Simon J. Stuart | ||
- Version: 2.1.0 | ||
- Note: Inherits from `EventReceivable` | ||
*/ | ||
public protocol UIEventReceivable: AnyObject, EventReceivable { | ||
|
||
} |
26 changes: 26 additions & 0 deletions
26
Sources/EventDrivenSwift/UIEventReceiver/UIEventReceiver.swift
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 |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// UIEventReceiver.swift | ||
// Copyright (c) 2022, Flowduino | ||
// Authored by Simon J. Stuart on 11th August 2022 | ||
// | ||
// Subject to terms, restrictions, and liability waiver of the MIT License | ||
// | ||
|
||
import Foundation | ||
|
||
/** | ||
Abstract Base Type for all `UIEventRecevier` Thread Types. | ||
- Author: Simon J. Stuart | ||
- Version: 2.1.0 | ||
- Note: Inherit from this to implement a discrete unit of code designed specifically to operate upon specific `Eventable` types containing information useful to its operation(s) | ||
- Note: Your Event Handlers/Listeners/Callbacks will be executed on the UI Thread every time. | ||
*/ | ||
open class UIEventReceiver: EventReceiver, UIEventReceivable { | ||
override internal func callTypedEventCallback<TEvent: Eventable>(_ callback: @escaping TypedEventCallback<TEvent>, forEvent: Eventable, priority: EventPriority) { | ||
Task { /// Have to use a Task because this method is not `async` | ||
await MainActor.run { /// Forces the call to be invoked on the `MainActor` (UI Thread) | ||
super.callTypedEventCallback(callback, forEvent: forEvent, priority: priority) | ||
} | ||
} | ||
} | ||
} |
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
114 changes: 114 additions & 0 deletions
114
Tests/EventDrivenSwiftTests/UIEventReceiverTests.swift.swift
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 |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// | ||
// UIEventReceiverTests.swift.swift | ||
// | ||
// | ||
// Created by Simon Stuart on 11/08/2022. | ||
// | ||
|
||
import XCTest | ||
import ThreadSafeSwift | ||
@testable import EventDrivenSwift | ||
|
||
final class UIEventReceiverTests_swift: XCTestCase { | ||
struct TestEventTypeOne: Eventable { | ||
var foo: Int | ||
} | ||
|
||
class TestEventThread: UIEventReceiver { | ||
@ThreadSafeSemaphore var foo: Int = 0 | ||
|
||
internal func eventOneCallback(_ event: TestEventTypeOne, _ priority: EventPriority) { | ||
foo = event.foo | ||
} | ||
|
||
override func registerEventListeners() { | ||
addEventCallback(self.eventOneCallback, forEventType: TestEventTypeOne.self) | ||
} | ||
} | ||
|
||
let expectedTestOneFoo: Int = 1000 | ||
|
||
/** | ||
I need to find a way of Unit Testing the `UIEventReceiver`. | ||
It works, this I know, but Unit Tests operate on the UI Thread, which means they are blocking the `UIEventReceiver` callback until *after* the Test Method has already returned (thus failed) | ||
*/ | ||
|
||
/* | ||
func testEventDispatchQueueDirect() throws { | ||
let testOne = TestEventTypeOne(foo: expectedTestOneFoo) // Create the Event | ||
let eventThread = TestEventThread() // Create the Thread | ||
XCTAssertEqual(eventThread.foo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(eventThread.foo)") | ||
eventThread.queueEvent(testOne, priority: .normal) // Now let's dispatch our Event to change this value | ||
sleep(5) | ||
XCTAssertEqual(eventThread.foo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(eventThread.foo)") | ||
} | ||
func testEventDispatchQueueCentral() throws { | ||
let testOne = TestEventTypeOne(foo: expectedTestOneFoo) // Create the Event | ||
let eventThread = TestEventThread() // Create the Thread | ||
XCTAssertEqual(eventThread.foo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(eventThread.foo)") | ||
EventCentral.queueEvent(testOne, priority: .normal) // Now let's dispatch our Event to change this value | ||
sleep(5) | ||
XCTAssertEqual(eventThread.foo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(eventThread.foo)") | ||
} | ||
func testEventDispatchQueueTransparent() throws { | ||
let testOne = TestEventTypeOne(foo: expectedTestOneFoo) // Create the Event | ||
let eventThread = TestEventThread() // Create the Thread | ||
XCTAssertEqual(eventThread.foo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(eventThread.foo)") | ||
testOne.queue() // Now let's dispatch our Event to change this value | ||
sleep(5) | ||
XCTAssertEqual(eventThread.foo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(eventThread.foo)") | ||
} | ||
func testEventDispatchStackDirect() throws { | ||
let testOne = TestEventTypeOne(foo: expectedTestOneFoo) // Create the Event | ||
let eventThread = TestEventThread() // Create the Thread | ||
XCTAssertEqual(eventThread.foo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(eventThread.foo)") | ||
eventThread.stackEvent(testOne, priority: .normal) // Now let's dispatch our Event to change this value | ||
sleep(5) | ||
XCTAssertEqual(eventThread.foo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(eventThread.foo)") | ||
} | ||
func testEventDispatchStackCentral() throws { | ||
let testOne = TestEventTypeOne(foo: expectedTestOneFoo) // Create the Event | ||
let eventThread = TestEventThread() // Create the Thread | ||
XCTAssertEqual(eventThread.foo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(eventThread.foo)") | ||
EventCentral.stackEvent(testOne, priority: .normal) // Now let's dispatch our Event to change this value | ||
sleep(5) | ||
XCTAssertEqual(eventThread.foo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(eventThread.foo)") | ||
} | ||
func testEventDispatchStackTransparent() throws { | ||
let testOne = TestEventTypeOne(foo: expectedTestOneFoo) // Create the Event | ||
let eventThread = TestEventThread() // Create the Thread | ||
XCTAssertEqual(eventThread.foo, 0, "Expect initial value of eventThread.foo to be 0, but it's \(eventThread.foo)") | ||
testOne.stack() // Now let's dispatch our Event to change this value | ||
sleep(5) | ||
XCTAssertEqual(eventThread.foo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(eventThread.foo)") | ||
} | ||
*/ | ||
} |