简体   繁体   中英

Unpacking an array in Reactive Cocoa

I have a method that looks something like this:

- (RACSignal*)savedObjectsOfEntityType:(NSEntityDescription*)entity
{
    return [[[[NSNotificationCenter defaultCenter] rac_addObserverForName:NSManagedObjectContextDidSaveNotification object:nil] map:^id(NSNotification *notification) {
        NSMutableArray *allSaves = [NSMutableArray array];
        [allSaves addObjectsFromArray:notification.userInfo[NSInsertedObjectsKey]];
        [allSaves addObjectsFromArray:notification.userInfo[NSUpdatedObjectsKey]];
        [allSaves addObjectsFromArray:notification.userInfo[NSDeletedObjectsKey]];
        return allSaves;
    }] filter:^BOOL(NSArray *allSaves) {
        // Can filter only if I get individual objects
    }];
}

I am mapping the notification objects returned by an observer on the notification center. Each notification contains several array that I merge together in the allSaves array. On the next step I would need to filter the individual objects in that array. The problem is the object I get from the map is the array of objects and it doesn't make sense to filter on it. Instead I would need the map to send the objects in allSaves one by one. The map operator doesn't do this, but is there another operator that can take an array and pass out individual objects from it one by one?

RACSignal *saves = [[NSNotificationCenter defaultCenter] rac_addObserverForName:NSManagedObjectContextDidSaveNotification object:nil]; // you should include the managed object context you want to watch here, but that's a separate issue
return [[[saves map:^(NSNotification *notification) {
    NSMutableArray *allSaves = [NSMutableArray array];
    [allSaves addObjectsFromArray:notification.userInfo[NSInsertedObjectsKey]];
    [allSaves addObjectsFromArray:notification.userInfo[NSUpdatedObjectsKey]];
    [allSaves addObjectsFromArray:notification.userInfo[NSDeletedObjectsKey]];
    return [[allSaves rac_sequence] signal];
}] switchToLatest] filter:^BOOL(NSManagedObject *savedObject) {

}];

We convert the array of objects, allSaves , into an RACSequence . Then we convert the RACSequence into an RACSignal and return that (there's no way to go directly from array to signal AFAIK). So we're mapping "signal of saves" into "signal of objets saved in a particular step".

switchToLatest takes that second signal and subscribes to it, such that the next filter , instead of receiving "signal of objects saved", receives each "object saved." switchToLatest turns a Signal<Signal<T>> into a Signal<T> , conceptually. So it's like we're unwrapping the inner signal.

There's another way we could do this, with flattenMap instead of map / switchToLatest . I believe in this case it behaves identically, since the inner signal is finite and will complete soon, so you could save yourself a few characters that way. But check that I'm right first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM