我正在努力解决使用 AFNetworking 和 Reactive Cocoa 处理对 Web 服务的多个请求的方式。在这种情况下,用户要求 API 为字符/整数搜索输入提供一堆建议,以从列表中选择一个城市。
这是我的代码:
首先是当用户输入超过 3 个字符/整数时立即执行的方法
- (void)fetchData:(NSString *)searchText
{
NSLog(@"%@", searchText);
if ([searchText validateStringwithPattern:BKPostcodeRegEx]) {
self.searchURL = [NSString stringWithFormat:@"%@location/postalCode/%@/%@", BKBaseURL, self.countryCode, searchText];
} else if ([searchText validateStringwithPattern:BKCityRegEx]) {
self.searchURL = [NSString stringWithFormat:@"%@location/city/%@/%@", BKBaseURL, self.countryCode, searchText];
} else {
NSLog(@"Error Alert - No Valid Input");
return;
}
RAC(self, searchResults) = [[[self postRequest] map:^(NSDictionary *json) {
NSArray *results = json[@"data"][@"locations"];
return results;
}] catch:^(NSError *error) {
return [RACSignal return:@[]];
}];
}
现在这是我实际创建信号并将其传递回 self.searchResults
的地方:
- (RACSignal *)postRequest
{
return [[[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[self.requestOperationManager GET:self.searchURL parameters:self.params success:^(AFHTTPRequestOperation *operation, id responseObject) {
[subscriber sendNext:responseObject];
[subscriber sendCompleted];
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[subscriber sendError:error];
}];
return [RACDisposable disposableWithBlock:^{
[self.requestOperationManager.operationQueue cancelAllOperations];
}];
}] doError:^(NSError *error) {
NSLog(@"error: %@", [error description]);
}] throttle:0.5];
}
我认为问题是,我在当前信号完成之前的信号之前开始订阅信号,因此在我尝试再次订阅时导致异常。
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Signal name: [[[[+createSignal:] -doError:] -throttle: 0.500000] -map:] -catch: is already bound to key path "searchResults" on object , adding signal name: [[[[+createSignal:] -doError:] -throttle: 0.500000] -map:] -catch: is undefined behavior'
我的猜测是我必须在 postRequest 方法中尝试这样的事情,但这似乎不是开箱即用的:
if (self.requestOperationManager.operationQueue.operationCount == 1) {
NSLog(@"cancel all operations");
[self.requestOperationManager.operationQueue cancelAllOperations];
[subscriber sendCompleted];
}
最佳答案
您只能在任何给定对象的键路径上调用一次 RAC()
。看起来 -fetchData:
可以被多次调用,这将导致 RAC()
在同一对象和关键路径上被多次调用。
通常,您在某种设置方法(例如初始化程序或-[UIViewController loadView]
)中调用RAC()
,这样它只会被调用一次。不要等到用户键入超过 3 个字符然后调用 -fetchData:
,而是考虑如何创建一个信号,当用户键入超过 3 个字符时发送一个值,并分配该信号到 RAC()
的属性。例如(完全未经测试):
- (void)someInitializationMethod
{
RACSignal *moreThan3 = [[myTextField rac_textSignal] filter:^(NSString *text) {
return [text length] > 2;
}];
RAC(self, searchResults) = [self rac_liftSelector:@selector(fetchData:) withSignals:moreThan3];
}
- (void)fetchData:(NSString *)searchText
{
if ([searchText validateStringwithPattern:BKPostcodeRegEx]) {
// ... etc ...
}
return [[[self postRequest] map:^(NSDictionary *json) {
NSArray *results = json[@"data"][@"locations"];
return results;
}] catch:^(NSError *error) {
return [RACSignal return:@[]];
}];
}
- (RACSignal *)postRequest
{
// ... etc ...
关于ios - Reactive Cocoa 和短时间内的多个 AFNetworking 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23059512/