import Cocoa
-private var pDeckContext = 0
+final class DeckObserver {
+
+ private let deck: Deck
+ private let handler: (Deck) -> Void
+
+ private var observation: [NSKeyValueObservation] = []
+
+ init(deck: Deck, handler: @escaping (Deck) -> Void) {
+
+ self.deck = deck
+ self.handler = handler
+
+ observation += [deck.observe(\Deck.ship_0, changeHandler: observeHandler)]
+ observation += [deck.observe(\Deck.ship_1, changeHandler: observeHandler)]
+ observation += [deck.observe(\Deck.ship_2, changeHandler: observeHandler)]
+ observation += [deck.observe(\Deck.ship_3, changeHandler: observeHandler)]
+ observation += [deck.observe(\Deck.ship_4, changeHandler: observeHandler)]
+ observation += [deck.observe(\Deck.ship_5, changeHandler: observeHandler)]
+ observation += [deck.observe(\Deck.ship_6, changeHandler: observeHandler)]
+
+ handler(deck)
+ }
+
+ private func observeHandler(_: Deck, _:NSKeyValueObservedChange<Int>) {
+
+ handler(deck)
+ }
+}
final class Fleet: NSObject {
let fleetNumber: Int
- private let deckController = NSObjectController()
- private let deckObserveKeys = [
- "selection.ship_0", "selection.ship_1", "selection.ship_2",
- "selection.ship_3", "selection.ship_4", "selection.ship_5"
- ]
+ private var observer: DeckObserver?
+
+ @objc dynamic private(set) var ships: [Ship] = []
+ private var deck: Deck?
+
+ let store = ServerDataStore.default
init?(number: Int) {
guard case 1...4 = number else {
Logger.shared.log("Fleet number out of range")
+
return nil
}
super.init()
- deckController.entityName = Deck.entityName
- deckController.managedObjectContext = ServerDataStore.default.context
- deckController.fetchPredicate = NSPredicate(#keyPath(Deck.id), equal: number)
- let req = NSFetchRequest<NSFetchRequestResult>()
- req.entity = NSEntityDescription.entity(forEntityName: Deck.entityName,
- in: deckController.managedObjectContext!)
- req.predicate = deckController.fetchPredicate
-
- do {
-
- try deckController.fetch(with: req, merge: false)
+ if let deck = store.sync(execute: { self.store.deck(by: number) }) {
- } catch {
-
- Logger.shared.log("Fetch error")
- return nil
+ self.setupDeck(deck: deck)
+ return
}
- deck = deckController.content as? Deck
- deckObserveKeys.forEach { deckController.addObserver(self, forKeyPath: $0, context: &pDeckContext) }
+ ServerDataStore.default
+ .future { _ -> Deck? in
+
+ guard let deck = self.store.sync(execute: { self.store.deck(by: number) }) else {
+
+ return nil
+ }
+
+ return deck
+ }
+ .onSuccess { deck in
+
+ self.setupDeck(deck: deck)
+ }
+ .onFailure { error in
+
+ Logger.shared.log("\(error)")
+ }
}
- deinit {
-
- deckObserveKeys.forEach { deckController.removeObserver(self, forKeyPath: $0) }
+ subscript(_ index: Int) -> Ship? {
+ return store.sync { self.deck?[index] }
}
- @objc override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
+ private func setupDeck(deck: Deck) {
- switch key {
-
- case #keyPath(name): return [#keyPath(deck.name)]
+ self.deck = deck
+ self.observer = DeckObserver(deck: deck) { [weak self] in
- case #keyPath(id): return [#keyPath(deck.id)]
-
- default: return []
+ self?.setupShips(deck: $0)
}
}
- @objc dynamic private(set) var ships: [Ship] = []
- @objc var deck: Deck?
-
- @objc dynamic var name: String? { return deck?.name }
- @objc dynamic var id: NSNumber? { return deck?.id as NSNumber? }
-
- subscript(_ index: Int) -> Ship? { return deck?[index] }
-
- override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
-
- if context == &pDeckContext {
-
- ships = (0..<6).flatMap { return self[$0] }
-
- return
- }
+ private func setupShips(deck: Deck) {
- super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
+ ships = store.sync { deck[0...6] }
}
}