LoginSignup
2
2

More than 5 years have passed since last update.

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

Posted at

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

普通にやるやつ

class Object: NSManagedObject {}

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

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
        }
}

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

楽にするやつ

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

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 }) ?? []
    }
}

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

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
        }
}

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

がんばりましょう

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

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2