2013-04-03 7 views
32

'da bağımlı sinyaller zincirleme ReactiveCocoa'da, birden fazla bağımlı sinyali zincirliyorsak, zincirdeki bir sonraki sinyal için subscribeNext: 'u kullanmalıyız (örneğin, senkronize olmayan bir çalışmanın sonucu). Yani bir süre sonra, kodu (gereksiz ayrıntılar atlanmıştır) böyle bir şey dönüşür:ReactiveCocoa

RACSignal *buttonClickSignal = [self.logIn rac_signalForControlEvents:UIControlEventTouchUpInside]; 

[buttonClickSignal subscribeNext:^(UIButton *sender) { // signal from a button click 
    // prepare data 

    RACSignal *loginSignal = [self logInWithUsername:username password:password]; // signal from the async network operation 

    [loginSignal subscribeNext:^void (NSDictionary *json) { 
     // do stuff with data received from the first network interaction, prepare some new data 

     RACSignal *playlistFetchSignal = [self fetchPlaylistForToken:token];   // another signal from the async network operation 

     [playlistFetchSignal subscribeNext:^(NSDictionary *json) { 
      // do more stuff with the returned data 
     }]; 

     // etc 
    }]; 
}]; 

Bu giderek artan yuvalama belgelerinde verilen reaktif olmayan örnek çok daha iyi görünmüyor:

[client logInWithSuccess:^{ 
    [client loadCachedMessagesWithSuccess:^(NSArray *messages) { 
     [client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMessages) { 
      NSLog(@"Fetched all messages."); 
     } failure:^(NSError *error) { 
      [self presentError:error]; 
     }]; 
    } failure:^(NSError *error) { 
     [self presentError:error]; 
    }]; 
} failure:^(NSError *error) { 
    [self presentError:error]; 
}]; 

ReactiveCocoa'da zincirleme bağımlı çalışmaya daha iyi bir örnek var mı?

cevap

47

Bu, RACStream ve RACSignal işleçlerinin gerçekten işe yaramaya başladığında ortaya çıkar. senin özel örnekte, yeni sinyallere içine sonuçlarını birleştirmek için -flattenMap: kullanabilirsiniz: Eğer herhangi bir aşamada sonuçlarını gerekmiyorsa

[[[buttonClickSignal 
    flattenMap:^(UIButton *sender) { 
     // prepare 'username' and 'password' 
     return [self logInWithUsername:username password:password]; 
    }] 
    flattenMap:^(NSDictionary *json) { 
     // prepare 'token' 
     return [self fetchPlaylistForToken:token]; 
    }] 
    subscribeNext:^(NSDictionary *json) { 
     // do stuff with the returned playlist data 
    }]; 

, sen ancak bir için (yerine benzer bir etki için -sequenceMany: veya -sequenceNext: kullanabilirsiniz niyetin daha net ifadesi).

+1

Bu çözüm benim için çalışıyor. Bu yaklaşımı açıklayan bir [blog makalesi] (http://www.techsfo.com/blog/2013/08/managing-nested-asynchronous-callbacks-in-objective-c-using-reactive-cocoa/) yazdım. daha fazla detay. –

+0

@Justin, yol boyunca hata işlemeyi gerçekleştirmenin doğru yolu hakkında daha fazla bilgi verir misiniz? – DogpatchTech

+0

@DogpatchTech Bunun için '-catch:' veya '-catchTo:' komutunu kullanabilirsiniz. Bkz. [Bu açıklama] (http://stackoverflow.com/questions/19439636/difference-between-catch-and-subscribeerror/19439687#19439687). –