import Cocoa
-fileprivate var DeckContext = 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)
+ }
+}
-class Fleet: NSObject {
+final class Fleet: NSObject {
+
let fleetNumber: Int
- 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 1...4 ~= number
- else {
- print("Fleet number out of range")
- return nil
+
+ guard case 1...4 = number else {
+
+ Logger.shared.log("Fleet number out of range")
+
+ return nil
}
+
fleetNumber = number
- deckController = NSObjectController()
+
super.init()
- deckController.entityName = "Deck"
- deckController.managedObjectContext = ServerDataStore.default.managedObjectContext
- deckController.fetchPredicate = NSPredicate(format: "id = %ld", number)
- let req = NSFetchRequest<NSFetchRequestResult>()
- req.entity = NSEntityDescription.entity(forEntityName: "Deck", 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) }) {
+
+ self.setupDeck(deck: deck)
+
+ return
}
- catch {
- print("Fetch error")
- return nil
+
+ 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)")
}
- deck = deckController.content as? KCDeck
- deckObserveKeys.forEach { deckController.addObserver(self, forKeyPath: $0, context: &DeckContext) }
}
- deinit {
- deckObserveKeys.forEach { deckController.removeObserver(self, forKeyPath: $0) }
- }
-
- dynamic private(set) var ships: [KCShipObject] = []
- private let deckController: NSObjectController
- private weak var deck: KCDeck?
- dynamic var name: String? { return deck?.name }
- func keyPathsForValuesAffectingName() -> Set<String> {
- return ["deck.name"]
- }
- dynamic var id: NSNumber? { return deck?.id as NSNumber? }
- func keyPathesForValuesAffectiongId() -> Set<String> {
- return ["deck.id"]
+ subscript(_ index: Int) -> Ship? {
+
+ return store.sync { self.deck?[index] }
}
- subscript(_ index: Int) -> KCShipObject? { return deck?[index] }
-
- override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
- if context == &DeckContext {
- ships = (0..<6).flatMap { return self[$0] }
- return
+ private func setupDeck(deck: Deck) {
+
+ self.deck = deck
+ self.observer = DeckObserver(deck: deck) { [weak self] in
+
+ self?.setupShips(deck: $0)
}
- super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
+ }
+
+ private func setupShips(deck: Deck) {
+
+ ships = store.sync { deck[0...6] }
}
}