2012-05-20 16 views
7

में पूरा करने के लिए मैं AFNetworking साथ एक JSON अनुरोध कर रहा हूँ और उसके बाद संचालन और सफलता या विफलता ब्लॉक पर प्रतीक्षा करने के लिए फोन [waitUntilFinished आपरेशन] प्रतीक्षा कर रहा है। लेकिन, यह सही है, हालांकि गिर लगता है - लॉग संदेशों के मामले में के बजाय "0", "1", "3"पूरा होने के ब्लॉक एक AFNetworking अनुरोध

NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://google.com"]]; 
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 
httpClient.parameterEncoding = AFFormURLParameterEncoding; 
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:@"query", @"q", nil]; 
NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:[url path] parameters:params]; 
NSLog(@"0"); 
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *innerRequest, NSHTTPURLResponse *response, id JSON) { 
NSLog(@"1"); 
gotResponse = YES; 
} failure:^(NSURLRequest *innerRequest, NSHTTPURLResponse *response, NSError *error, id JSON) { 
    NSLog(@"2"); 
    gotResponse = YES; 
}]; 
NSLog(@"Starting request"); 
[operation start]; 
[operation waitUntilFinished]; 
NSLog(@"3"); 
+0

ऐसा लगता है कि '[ऑपरेशन प्रतीक्षाUntilFinished] 'पर कॉल पूरा होने वाले ब्लॉक पर प्रतीक्षा नहीं करता है। AFJSONRequestOperation.m उन्हें 'dispatch_async' के साथ निष्पादित करता है जो मुझे लगता है कि एक अलग ऑपरेशन का हिस्सा बन जाता है। क्या यह सही है और इसके आसपास एक रास्ता है? – Kamran

उत्तर

14

इस से काम करता है अनुरोधों को स्थापित करने के लिए AFNetworking का उपयोग करके, लेकिन एक सिंक्रोनस कॉल करने के बाद मैन्युअल रूप से पूर्णता ब्लॉक को संभालना। बहुत आसान। AFNetworking इस https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-FAQ का समर्थन नहीं कर रहा है, हालांकि आसपास के काम काफी सरल हैं।

#import "SimpleClient.h" 

#import "AFHTTPClient.h" 
#import "AFJSONRequestOperation.h" 
#import "AFJSONUtilities.h" 

@implementation SimpleClient 

+ (void) makeRequestTo:(NSString *) urlStr 
     parameters:(NSDictionary *) params 
     successCallback:(void (^)(id jsonResponse)) successCallback 
     errorCallback:(void (^)(NSError * error, NSString *errorMsg)) errorCallback { 

    NSURLResponse *response = nil; 
    NSError *error = nil; 

    NSURL *url = [NSURL URLWithString:urlStr]; 

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url]; 

    httpClient.parameterEncoding = AFFormURLParameterEncoding; 

    NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:[url path] parameters:params]; 
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; 

    if(error) { 
     errorCallback(error, nil); 
    } else { 
     id JSON = AFJSONDecode(data, &error); 
     successCallback(JSON); 
    } 
} 

@end 
0

, मैं "0", "3", "1" यही कारण है कि (लगभग) काम करना चाहिए।

NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET" path:[url path] parameters:params]; 

को आपका कॉल शायद path: पैरामीटर के लिए [url path] पारित नहीं करना चाहिए। एएफनेटवर्किंग भूमि में, वह पथ बेस यूआरएल के बाद सबकुछ है (उदाहरण के लिए बेस यूआरएल "http://google.com" और पथ "/ जीमेल" या जो कुछ भी हो सकता है)।

कहा जा रहा है, यह शायद waitUntilFinished साथ एक धागा-अवरुद्ध तुल्यकालिक आपरेशन में अतुल्यकालिक आपरेशन बनाने के लिए एक अच्छा विचार नहीं है, लेकिन मुझे यकीन है कि आप अपने कारणों ... है कर रहा हूँ;)

+0

पथ में बदल गया: @ "/", लेकिन परिणाम वही है। – Kamran

0

मुझे बस एक ही समस्या थी और एक अलग समाधान मिला। मेरे पास दो ऑपरेशन थे जो एक दूसरे पर निर्भर करते हैं, लेकिन समानांतर में लोड हो सकते हैं। हालांकि, पहले ऑपरेशन के समापन ब्लॉक समाप्त होने से पहले दूसरे ऑपरेशन के समापन ब्लॉक को निष्पादित नहीं किया जा सकता है।

कॉलिन के रूप में बताया, यह एक वेब अनुरोध ब्लॉक बनाने के लिए एक बुरा विकल्प हो सकता है। यह मेरे लिए आवश्यक था, इसलिए मैंने इसे असंकालिक रूप से किया।/अपलोडिंग पूरा करता

// This is our lock 
@interface SomeController() { 
    NSLock *_dataLock; 
} 
@end 

@implementation 

// This is just an example, you might as well trigger both operations in separate 
// places if you get the locking right 
// This might be called e.g. in awakeFromNib 
- (void)someStartpoint { 
    AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:[NSURLRequest requestWithURL:url1] 
                         success:^(NSURLRequest *request, NSHTTPURLResponse *response, id data) { 
     // We're done, we unlock so the next operation can continue its 
     // completion block 
     [_dataLock unlock]; 
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) { 
     // The request has failed, so we need to unlock for the next try 
     [_dataLock unlock]; 
    }]; 

    AFJSONRequestOperation *operation2 = [AFJSONRequestOperation JSONRequestOperationWithRequest:[NSURLRequest requestWithURL:url2] 
                         success:^(NSURLRequest *request, NSHTTPURLResponse *response, id data) { 
     // The completion block (or at least the blocking part must be run in a 
     // separate thread 
     [NSThread detachNewThreadSelector:@selector(completionBlockOfOperation2:) toTarget:self withObject:data]; 
    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) { 
     // This second operation may fail without affecting the lock 
    }]; 

    // We need to lock before both operations are started 
    [_dataLock lock]; 

    // Order does not really matter here 
    [operation2 start]; 
    [operation1 start]; 
} 

- (void)completionBlockOfOperation2:(id)data { 
    // We wait for the first operation to finish its completion block 
    [_dataLock lock]; 

    // It's done, so we can continue 

    // We need to unlock afterwards, so a next call to one of the operations 
    // wouldn't deadlock 
    [_dataLock unlock]; 
} 

@end 
+0

एसिंक अनुरोध का उपयोग क्यों करें इसे अवरुद्ध करने के लिए मजबूर करें? अनलॉक स्टेटमेंट पर जाने से पहले यदि आप कॉलबैक से वापस आ सकते हैं तो यह त्रुटि प्रवण है। – Kamran

+0

यह अनुरोध नहीं है कि अवरुद्ध है। यह लैम्ब्डा फ़ंक्शन है जिसे अनुरोध समाप्त होने के बाद बुलाया जाता है। यह सुनिश्चित करता है कि दूसरे (आश्रित) अनुरोध की प्रतिक्रिया का मूल्यांकन तब तक नहीं किया जाता जब तक कि पहला पूरा नहीं हो जाता। अनुरोध स्वयं समानांतर में किए जाते हैं। – Koraktor

0

उपयोग प्रतिनिधि विधि कॉल

ब्लॉक के अंदर विधि जब डाउनलोड जो अपने आप कॉल करेंगे रखो:

यह मेरा समाधान है।