This is commonly done with a dictionary. ("Commonly" meaning "when the ObjC runtime isn't available." As Charles Srstka notes, the correct tool here for a view controller is definitely objc_getAssociatedObject
. There is no particular virtue in avoiding the runtime once you've already inherited from NSObject
.)
It leaks some memory (since there's no automatic way to clean out unused values), but the cost is usually small (or you have to add a mechanism to "garbage collect" which isn't too hard).
private var lastValues: [ObjectIdentifier: Int] = [:]
extension ViewController {
private var lastValue: Int {
get {
return lastValues[ObjectIdentifier(self)] ?? 0
}
set {
lastValues[ObjectIdentifier(self)] = newValue
}
}
func checkIfBiggerThanLastNumber(_ number: Int) -> Bool {
let savedLast = lastValue
lastValue = number
return number > savedLast
}
}
I haven't tested this extensively, but this an example of how you might build an auto-garbage collecting version of this to clean up memory if you had a lot of objects that come and go. It garbage collects every time you modify it, but you could do it other ways depending on need:
// A simple weak dictionary. There are probably better versions out there.
// I just threw this together.
struct WeakDict<Key: AnyObject, Value>: ExpressibleByDictionaryLiteral {
struct Box<T: AnyObject>: Hashable {
let identifier: ObjectIdentifier
weak var value: T?
init(_ value: T) {
self.identifier = ObjectIdentifier(value)
self.value = value
}
static func ==(lhs: Box<T>, rhs: Box<T>) -> Bool {
return lhs.identifier == rhs.identifier
}
var hashValue: Int { return identifier.hashValue }
}
private var dict: [Box<Key>: Value]
init(dictionaryLiteral elements: (Key, Value)...) {
dict = Dictionary(uniqueKeysWithValues: elements.map { (Box($0), $1) })
}
private mutating func garbageCollect() {
dict = dict.filter { (key, _) in key.value != nil }
}
subscript(_ key: Key) -> Value? {
get {
return dict[Box(key)]
}
set {
garbageCollect()
dict[Box(key)] = newValue
}
}
}
With that, usage is almost identical:
private var lastValues: WeakDict<ViewController, Int> = [:]
extension ViewController {
private var lastValue: Int {
get { return lastValues[self] ?? 0 }
set { lastValues[self] = newValue }
}
func checkIfBiggerThanLastNumber(_ number: Int) -> Bool {
let savedLast = lastValue
lastValue = number
return number > savedLast
}
}