OSDN Git Service

staticプロパティをインスタンスプロパティに変更
[kcd/KCD.git] / KCD / ShipViewController.swift
index c08ec01..a5f0a74 100644 (file)
@@ -11,26 +11,46 @@ import Cocoa
 private enum ViewType: Int {
     
     case exp
+    
     case power
+    
     case power2
+    
     case power3
 }
 
+/// 2018.02.24
+/// #keyPath(Ship.master_ship.soku)がkeyであるNSSortDescriptorが含まれるとクラッシュする可能性があるため
+/// 新設した#keyPath(Ship.soku)をkeyにするように書き換える
+private func exchangeSortKey(original: [NSSortDescriptor]) -> [NSSortDescriptor] {
+    
+    return original
+        .map { sortDesc -> NSSortDescriptor in
+            
+            if sortDesc.key == #keyPath(Ship.master_ship.soku) {
+                
+                return NSSortDescriptor(key: #keyPath(Ship.soku), ascending: sortDesc.ascending)
+            }
+            
+            return sortDesc
+    }
+}
+
 final class ShipViewController: MainTabVIewItemViewController {
     
     @objc let managedObjectContext = ServerDataStore.default.context
     
-    deinit {
-        
-        NotificationCenter.default.removeObserver(self)
-    }
+    @IBOutlet private var shipController: NSArrayController!
+    @IBOutlet private var expTableView: NSScrollView!
+    @IBOutlet private var powerTableView: NSScrollView!
+    @IBOutlet private var power2TableView: NSScrollView!
+    @IBOutlet private var power3TableView: NSScrollView!
+    @IBOutlet private weak var standardDeviationField: NSTextField!
+    
+    private var sortDescriptorsObservation: NSKeyValueObservation?
+    private var arrangedObjectsObservation: NSKeyValueObservation?
     
-    @IBOutlet var shipController: NSArrayController!
-    @IBOutlet var expTableView: NSScrollView!
-    @IBOutlet var powerTableView: NSScrollView!
-    @IBOutlet var power2TableView: NSScrollView!
-    @IBOutlet var power3TableView: NSScrollView!
-    @IBOutlet weak var standardDeviationField: NSTextField!
+    private var notificationObserver = NotificationObserver()
     
     override var nibName: NSNib.Name {
         
@@ -41,17 +61,22 @@ final class ShipViewController: MainTabVIewItemViewController {
     override var selectedShipType: ShipTabType {
         
         didSet {
-            shipController.filterPredicate = shipTypePredicte
+            
+            shipController.filterPredicate = shipTypePredicte(for: selectedShipType)
             shipController.rearrangeObjects()
         }
     }
     
     @objc var standardDeviation: Double {
         
-        guard let ships = shipController.arrangedObjects as? [Ship],
-            !ships.isEmpty,
-            let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double
-            else { return 0.0 }
+        guard let ships = shipController.arrangedObjects as? [Ship], !ships.isEmpty else {
+            
+            return 0.0
+        }
+        guard let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double else {
+            
+            return 0.0
+        }
         
         let total = ships.reduce(0.0) {
             
@@ -63,6 +88,11 @@ final class ShipViewController: MainTabVIewItemViewController {
         return sqrt(total / Double(ships.count))
     }
     
+//    @objc dynamic var sortDescriptors: [NSSortDescriptor] {
+//        get { return UserDefaults.standard[.shipviewSortDescriptors] }
+//        set { UserDefaults.standard[.shipviewSortDescriptors] = sortDescriptors }
+//    }
+    
     private weak var currentTableView: NSView?
     
     override func viewDidLoad() {
@@ -81,19 +111,28 @@ final class ShipViewController: MainTabVIewItemViewController {
             
         }
         
-        shipController.sortDescriptors = UserDefaults.standard[.shipviewSortDescriptors]
-        shipController.addObserver(self, forKeyPath: NSBindingName.sortDescriptors.rawValue, context: nil)
-        shipController.addObserver(self, forKeyPath: "arrangedObjects", context: nil)
+        shipController.sortDescriptors = exchangeSortKey(original: UserDefaults.standard[.shipviewSortDescriptors])
+
+        sortDescriptorsObservation = shipController.observe(\NSArrayController.sortDescriptors) { [weak self] _, _ in
+
+            UserDefaults.standard[.shipviewSortDescriptors] = self?.shipController.sortDescriptors ?? []
+        }
+        arrangedObjectsObservation = shipController.observe(\NSArrayController.arrangedObjects) { [weak self] _, _ in
+            
+            self?.notifyChangeValue(forKey: #keyPath(standardDeviation))
+        }
         
         let tableViews = [expTableView, powerTableView, power2TableView, power3TableView]
         tableViews
             .forEach {
                 
-                NotificationCenter.default
-                    .addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: $0, queue: nil) {
+                notificationObserver
+                    .addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: $0, queue: .main) {
                         
-                        guard let target = $0.object as? NSScrollView
-                            else { return }
+                        guard let target = $0.object as? NSScrollView else {
+                            
+                            return
+                        }
                         
                         let visibleRect = target.documentVisibleRect
                         tableViews
@@ -106,41 +145,32 @@ final class ShipViewController: MainTabVIewItemViewController {
         #endif
     }
     
-    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
-        
-        if keyPath == NSBindingName.sortDescriptors.rawValue {
-            
-            UserDefaults.standard[.shipviewSortDescriptors] = shipController.sortDescriptors
-            
-            return
-        }
-        
-        if keyPath == "arrangedObjects" {
-            
-            notifyChangeValue(forKey: "standardDeviation")
-            
-            return
-        }
-        
-        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
-    }
-    
     private func showView(with type: ViewType) {
         
         let newSelection: NSView = {
             
             switch type {
+                
             case .exp: return expTableView
+                
             case .power: return powerTableView
+                
             case .power2: return power2TableView
+                
             case .power3: return power3TableView
+                
             }
         }()
         
-        if currentTableView == newSelection { return }
+        if currentTableView == newSelection {
+            
+            return
+        }
         
-        guard let tableView = currentTableView
-            else { return }
+        guard let tableView = currentTableView else {
+            
+            return
+        }
         
         newSelection.frame = tableView.frame
         newSelection.autoresizingMask = tableView.autoresizingMask
@@ -159,10 +189,13 @@ final class ShipViewController: MainTabVIewItemViewController {
             return cell?.tag(forSegment: segmented.selectedSegment) ?? -1
             
         case let control as NSControl:
+            
             return control.tag
             
         default:
+            
             return -1
+            
         }
     }
     
@@ -176,8 +209,10 @@ extension ShipViewController: NSTableViewDelegate {
     
     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
         
-        guard let identifier = tableColumn?.identifier
-            else { return nil }
+        guard let identifier = tableColumn?.identifier else {
+            
+            return nil
+        }
         
         return tableView.makeView(withIdentifier: identifier, owner: nil)
     }