Skip to content

Commit 5f6c746

Browse files
committed
Unregistration of @EventMethod is impossible
We cannot unregister or modify an `@EventMethod` once it is registered... so the code to try this has been removed.
1 parent 8f41434 commit 5f6c746

File tree

6 files changed

+90
-115
lines changed

6 files changed

+90
-115
lines changed

Sources/EventDrivenSwift/Event/Wrappers/EventMethod.swift

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ public protocol EventMethodContainer {
2020
associatedtype TEventType: Eventable
2121
associatedtype TOwner: AnyObject
2222

23-
var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType> { get set }
23+
var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType>? { get set }
2424

25-
var owner: AnyObject? { get set }
26-
27-
mutating func unregister()
25+
mutating func prepare(owner: AnyObject)
2826
}
2927

3028
/**
@@ -34,57 +32,29 @@ public protocol EventMethodContainer {
3432
*/
3533
@propertyWrapper
3634
public struct EventMethod<TOwner: AnyObject, TEventType: Eventable>: EventMethodContainer {
37-
mutating public func unregister() {
38-
lock.wait()
39-
if token != nil {
40-
TEventType.removeListener(token!)
41-
token = nil
42-
}
43-
lock.signal()
44-
}
35+
public var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType>?
36+
public var executeOn: ExecuteEventOn
4537

46-
private var token: UUID? = nil
47-
private var lock = DispatchSemaphore(value: 1)
38+
private weak var owner: AnyObject? = nil
4839

49-
public var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType> {
50-
didSet {
51-
reRegsiterListener()
52-
}
53-
}
54-
public var executeOn: ExecuteEventOn {
55-
didSet {
56-
reRegsiterListener()
40+
private func callback(event: TEventType, priority: EventPriority) {
41+
if let typedOwner = owner as? TOwner {
42+
wrappedValue?(typedOwner, event, priority)
5743
}
5844
}
5945

60-
public var owner: AnyObject? {
61-
didSet {
62-
reRegsiterListener()
63-
}
46+
public init(wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType>?, executeOn: ExecuteEventOn = .requesterThread) {
47+
self.wrappedValue = wrappedValue
48+
self.executeOn = executeOn
6449
}
6550

66-
private func callback(event: TEventType, priority: EventPriority) {
51+
mutating public func prepare(owner: AnyObject) {
6752
if let typedOwner = owner as? TOwner {
68-
wrappedValue(typedOwner, event, priority)
69-
}
70-
}
71-
72-
mutating private func reRegsiterListener() {
73-
lock.wait()
74-
if token != nil {
75-
TEventType.removeListener(token!)
76-
}
77-
if owner != nil {
78-
token = TEventType.addListener(
79-
owner,
53+
self.owner = owner
54+
TEventType.addListener(
55+
typedOwner,
8056
callback,
8157
executeOn: executeOn)
8258
}
83-
lock.signal()
84-
}
85-
86-
public init(wrappedValue: @escaping EventMethodTypedEventCallback<TOwner, TEventType>, executeOn: ExecuteEventOn = .requesterThread) {
87-
self.wrappedValue = wrappedValue
88-
self.executeOn = executeOn
8959
}
9060
}

Sources/EventDrivenSwift/EventHandler/EventHandler.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ open class EventHandler: ObservableThread, EventHandling {
127127
var eventStacks = [EventPriority:[any Eventable]]()
128128
_stacks.withLock { stacks in
129129
eventStacks = stacks
130-
stacks.removeAll(keepingCapacity: true)
130+
stacks.removeAll()
131131
}
132132

133133
for priority in EventPriority.inOrder {
@@ -147,7 +147,7 @@ open class EventHandler: ObservableThread, EventHandling {
147147
var eventQueues = [EventPriority:[any Eventable]]()
148148
_queues.withLock { queues in
149149
eventQueues = queues
150-
queues.removeAll(keepingCapacity: true)
150+
queues.removeAll()
151151
}
152152

153153
for priority in EventPriority.inOrder {
@@ -173,7 +173,7 @@ open class EventHandler: ObservableThread, EventHandling {
173173
- Version: 1.0.0
174174
*/
175175
public override func main() {
176-
while isExecuting {
176+
while isExecuting && !isCancelled {
177177
eventsPending.wait() // This will make the Thread effectively "sleep" until there are Events pending
178178
processAllEvents() // Once there's at least one Event waiting, we will Process it/them.
179179
}

Sources/EventDrivenSwift/EventListener/EventListening.swift

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,6 @@ public protocol EventListening: AnyObject {
2323
````
2424
*/
2525
func registerListeners()
26-
27-
/**
28-
Invoke this method to automatically unregister any Event Listener callback bearing the `@EventMethod` wrapper.
29-
- Author: Simon J. Stuart
30-
- Version: 4.1.0
31-
*/
32-
func unregisterListeners()
3326
}
3427

3528
/**
@@ -42,16 +35,7 @@ public extension EventListening {
4235
let mirror = Mirror(reflecting: self)
4336
for child in mirror.children {
4437
if var child = child.value as? (any EventMethodContainer) {
45-
child.owner = self
46-
}
47-
}
48-
}
49-
50-
func unregisterListeners() {
51-
let mirror = Mirror(reflecting: self)
52-
for child in mirror.children {
53-
if var child = child.value as? (any EventMethodContainer) {
54-
child.unregister()
38+
child.prepare(owner: self)
5539
}
5640
}
5741
}

Sources/EventDrivenSwift/EventThread/EventThread.swift

Lines changed: 33 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ public protocol ThreadEventMethodContainer {
2020
associatedtype TEventType: Eventable
2121
associatedtype TOwner: EventThread
2222

23-
var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType> { get set }
23+
var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType>? { get set }
2424

25-
var owner: AnyObject? { get set }
26-
27-
mutating func unregister()
25+
mutating func prepare(owner: AnyObject)
2826
}
2927

3028
/**
@@ -34,11 +32,13 @@ public protocol ThreadEventMethodContainer {
3432
- 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)
3533
*/
3634
open class EventThread: EventReceiver, EventThreadable {
35+
public typealias EventMethodTypedEventCallback<TOwner: EventThread, TEvent: Any> = (_ sender: TOwner, _ event: TEvent, _ priority: EventPriority) -> ()
3736
/**
3837
Property Wrapper to simplify the registration of Event Callbacks in `EventThread`-inheriting types.
3938
- Author: Simon J. Stuart
4039
- Version: 4.1.0
4140
- Note: Any Event Callback implemented this way will be automatically registered for you.
41+
- Note: You cannot unregister or modify the Callback in any way. They are immutable.
4242
````
4343
@EventMethod<MyEventThreadType, MyEventType>
4444
private var onMyEvent = {
@@ -49,47 +49,25 @@ open class EventThread: EventReceiver, EventThreadable {
4949
*/
5050
@propertyWrapper
5151
public struct EventMethod<TOwner: EventThread, TEventType: Eventable>: ThreadEventMethodContainer {
52-
public typealias EventMethodTypedEventCallback<TOwner: EventThread, TEvent: Any> = (_ sender: TOwner, _ event: TEvent, _ priority: EventPriority) -> ()
53-
54-
mutating public func unregister() {
55-
if token == nil { return }
56-
if let typedOwner = owner as? TOwner {
57-
typedOwner.removeEventCallback(token: token!)
58-
}
59-
}
60-
61-
private var token: UUID? = nil
62-
private var lock = DispatchSemaphore(value: 1)
63-
64-
public var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType> {
65-
didSet {
66-
reRegsiterListener()
67-
}
68-
}
52+
public var wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType>?
6953

70-
public var owner: AnyObject? {
71-
didSet {
72-
reRegsiterListener()
73-
}
74-
}
54+
private var owner: AnyObject? = nil
7555

7656
@inline(__always) private func callback(event: TEventType, priority: EventPriority) {
7757
if let typedOwner = owner as? TOwner {
78-
wrappedValue(typedOwner, event, priority)
58+
wrappedValue?(typedOwner, event, priority)
7959
}
8060
}
61+
62+
public init(wrappedValue: EventMethodTypedEventCallback<TOwner, TEventType>?) {
63+
self.wrappedValue = wrappedValue
64+
}
8165

82-
mutating private func reRegsiterListener() {
83-
lock.wait()
66+
mutating public func prepare(owner: AnyObject) {
8467
if let typedOwner = owner as? TOwner {
85-
unregister()
86-
token = typedOwner.addEventCallback(callback, forEventType: TEventType.self)
68+
self.owner = owner
69+
typedOwner.addEventCallback(callback, forEventType: TEventType.self)
8770
}
88-
lock.signal()
89-
}
90-
91-
public init(wrappedValue: @escaping EventMethodTypedEventCallback<TOwner, TEventType>) {
92-
self.wrappedValue = wrappedValue
9371
}
9472
}
9573

@@ -113,6 +91,7 @@ open class EventThread: EventReceiver, EventThreadable {
11391
- Note: We use the Qualified Type Name as the Key because Types are not Hashable in Swift
11492
*/
11593
@ThreadSafeSemaphore private var eventCallbacks = [String:[EventCallbackContainer]]()
94+
@ThreadSafeSemaphore private var tokens = [UUID]()
11695

11796
/**
11897
Invoke the appropriate Callback for the given Event
@@ -168,6 +147,9 @@ open class EventThread: EventReceiver, EventThreadable {
168147

169148
dispatcher.addReceiver(self, forEventType: forEventType)
170149

150+
_tokens.withLock { tokens in
151+
tokens.append(callbackContainer!.token)
152+
}
171153
return callbackContainer!.token
172154
}
173155

@@ -236,9 +218,10 @@ open class EventThread: EventReceiver, EventThreadable {
236218
*/
237219
internal func registerWrappedListeners() {
238220
let mirror = Mirror(reflecting: self)
221+
239222
for child in mirror.children {
240-
if var child = child.value as? (any ThreadEventMethodContainer) {
241-
child.owner = self
223+
if var typedValue = child.value as? (any ThreadEventMethodContainer) {
224+
typedValue.prepare(owner: self)
242225
}
243226
}
244227
}
@@ -264,12 +247,18 @@ open class EventThread: EventReceiver, EventThreadable {
264247
- Author: Simon J. Stuart
265248
- Version: 4.1.0
266249
*/
267-
deinit {
268-
let mirror = Mirror(reflecting: self)
269-
for child in mirror.children {
270-
if var child = child.value as? (any ThreadEventMethodContainer) {
271-
child.unregister()
272-
}
250+
open func unregisterWrappedListeners() {
251+
var snapTokens = [UUID]()
252+
_tokens.withLock { tokens in
253+
snapTokens = tokens
254+
tokens.removeAll()
255+
}
256+
for token in snapTokens {
257+
removeEventCallback(token: token)
273258
}
274259
}
260+
261+
deinit {
262+
unregisterWrappedListeners()
263+
}
275264
}

Tests/EventDrivenSwiftTests/BasicEventListenerTests.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ final class BasicEventListenerTests: XCTestCase, EventListening {
5757
XCTAssertEqual(self.myFoo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(self.myFoo)")
5858

5959
TestEventTypeOne.removeListener(listenerToken!)
60-
unregisterListeners()
6160
}
6261

6362
func testEventListenerOnTaskThread() throws {
@@ -76,6 +75,5 @@ final class BasicEventListenerTests: XCTestCase, EventListening {
7675
XCTAssertEqual(self.myFoo, testOne.foo, "Expect new value of eventThread.foo to be \(testOne.foo), but it's \(self.myFoo)")
7776

7877
TestEventTypeOne.removeListener(listenerToken!)
79-
unregisterListeners()
8078
}
8179
}

0 commit comments

Comments
 (0)