[Swift] CoreDataの変化をNotificationで監視する時ちょっとだけ楽する奴


CoreDataの変化をNotificationで監視するのは結構面倒臭い。
例えばこうなる。

### 普通にやるやつ

````swift
class Object: NSManagedObject {}
```

上の`Object`に何か変化があった時何かするスケルトン

```swift
NotificatioCenter.default
    .addObserver(forName: .NSManagedObjectContextObjectsDidChange, object: managedObjectContext, queue: .main) { notification in
        
        guard let userInfo = notification.userInfo else {
            return
        }
        
        let inserted = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject>
        inserted
            .flatMap { $0 as? Object }
            .forEach {
                // do something
        }
        
        let updated = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject>
        updated
            .flatMap { $0 as? Object }
            .forEach {
                // do something
        }
        
        let deleted = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject>
        deleted
            .flatMap { $0 as? Object }
            .forEach {
                // do something
        }
}

```

**ながい！！**
スケルトンなのに**超長い！！！**

### 楽にするやつ
なので楽にするやつを作った。

```swift
extension Notification {
    
    struct ChangedType: OptionSet {
        
        let rawValue: UInt8
        
        static let inserted = ChangedType(rawValue: 0x0001)
        static let updated = ChangedType(rawValue: 0x0002)
        static let deleted = ChangedType(rawValue: 0x0004)
        
        static let all = ChangedType(rawValue: 0x0007)
    }
    
    func insertedManagedObjects<T: NSManagedObject>() -> [T] {
        
        return managedObjects(infoKey: NSInsertedObjectsKey)
    }
    
    func updatedManagedObjects<T: NSManagedObject>() -> [T] {
        
        return managedObjects(infoKey: NSUpdatedObjectsKey)
    }
    
    func deletedManagedObjects<T: NSManagedObject>() -> [T] {
        
        return managedObjects(infoKey: NSDeletedObjectsKey)
    }
    
    func changedManagedObjects<T: NSManagedObject>(type: ChangedType = .all) -> [T] {
        
        let inserted: [T] = type.contains(.inserted) ? insertedManagedObjects() : []
        let updated: [T] = type.contains(.updated) ? updatedManagedObjects() : []
        let deleted: [T] = type.contains(.deleted) ? deletedManagedObjects() : []
        
        return inserted + updated + deleted
    }
    
    private func managedObjects<T: NSManagedObject>(infoKey: String) -> [T] {
        
        guard let userInfo = self.userInfo as? [String: Any] else { return [] }
        
        let inserted = userInfo[infoKey] as? Set<NSManagedObject>
        return inserted?.flatMap({ $0 as? T }) ?? []
    }
}
```

これを使うとスケルトンはこうなる。

```swift
NotificatioCenter.default
    .addObserver(forName: .NSManagedObjectContextObjectsDidChange, object: managedObjectContext, queue: .main) { notification in
        
        notification
            .insertedManagedObjects()
            .forEach { (objcct: Object) in
                // do some
        }
        
        notification
            .updatedManagedObjects()
            .forEach { (objcct: Object) in
                // do some
        }
        
        notification
            .deletedManagedObjects()
            .forEach { (objcct: Object) in
                // do some
        }
}
```

ちょっとだけ短くなった。

### がんばりましょう

型を確定するのが面倒くさい
もうちょっとどうにかしたい