1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//
// EventSubscription.swift
// Observable-Swift
//
// Created by Leszek Ślażyński on 21/06/14.
// Copyright (c) 2014 Leszek Ślażyński. All rights reserved.
//
// Implemented as a class, so it can be compared using === and !==.
// There is no way for event to get notified when the owner was deallocated,
// therefore it will be invalidated only upon next attempt to trigger.
// Event subscriptions are neither freed nor removed from events upon invalidation.
// Events remove invalidated subscriptions themselves when firing.
// Invalidation immediately frees handler and owned objects.
/// A class representing a subscription for `Event<T>`.
public class EventSubscription<T> {
public typealias HandlerType = (T) -> ()
private var _valid: () -> Bool
/// Handler to be caled when value changes.
public private(set) var handler: HandlerType
/// array of owned objects
private var _owned = [AnyObject]()
/// When invalid subscription is to be notified, it is removed instead.
public func valid() -> Bool {
if !_valid() {
invalidate()
return false
} else {
return true
}
}
/// Marks the event for removal, frees the handler and owned objects
public func invalidate() {
_valid = { false }
handler = { _ in () }
_owned = []
}
/// Init with a handler and an optional owner.
/// If owner is present, valid() is tied to its lifetime.
public init(owner o: AnyObject?, handler h: @escaping HandlerType) {
if o == nil {
_valid = { true }
} else {
_valid = { [weak o] in o != nil }
}
handler = h
}
/// Add an object to be owned while the event is not invalidated
public func addOwnedObject(_ o: AnyObject) {
_owned.append(o)
}
/// Remove object from owned objects
public func removeOwnedObject(_ o: AnyObject) {
_owned = _owned.filter{ $0 !== o }
}
}