2016-04-02 4 views
1

У меня есть этот методПытаясь понять асинхронные вызовы

- (NSString*) createUserWithName:(NSString*)TheName 
{ 
    NSURL *URL =someUrlthatIncludesTheName 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; 
    [request setHTTPMethod:@"GET"]; 
    NSURLSession *session = [NSURLSession sharedSession]; 
    NSURL *URL = [NSURL URLWithString:url]; 
    NSURLSessionTask *task = [session dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     if (response) { 
      NSError* error = nil; 
      NSArray *output = [NSJSONSerialization JSONObjectWithData:data 
                   options:NSJSONReadingMutableContainers 
                   error:&error]; 
      myID = [[output objectAtIndex:0] objectForKey:@"UserID"]; 
     } 
    }]; 
    [task resume]; 
    return myID; 
} 

и другой метод

-(void)doSomethingWith: (NSString*) anID 

Где-то в моем коде, я называю эти методы впоследствии, как это:

[self createUserWithName:@"John"]; 
[self doSomethingWith:myID]; 

Однако из-за того, что NSURLSession в createUserWithName: является асинхронным, doSomethingWith: увольняется с myID = (null).

Каков наилучший способ приблизиться к этой проблеме, не обязательно возвращаясь к устаревшему синхронному NSURLConnection?

Заранее спасибо

+0

Это происходит потому, что 'createUserWithName' не закончил, а метод' [само doSomethingWith: MyId] 'выполняется. Вы можете вызвать '[self doSomethingWith: myID];' в 'createUserWithName' или использовать CompletionBlock – vroldan

ответ

4

рабочий процесс должен быть

- (void)createUserWithName:(NSString*)TheName 
{ 
    NSURL *URL =someUrlthatIncludesTheName 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; 
    [request setHTTPMethod:@"GET"]; 
    NSURLSession *session = [NSURLSession sharedSession]; 
    NSURL *URL = [NSURL URLWithString:url]; 
    NSURLSessionTask *task = [session dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     if (response) { 
      NSError* error = nil; 
      NSArray *output = [NSJSONSerialization JSONObjectWithData:data 
                   options:NSJSONReadingMutableContainers 
                   error:&error]; 
      myID = [[output objectAtIndex:0] objectForKey:@"UserID"]; 
      [self doSomethingWith:myID]; 
     } 
    }]; 
    [task resume]; 
} 

И вызов просто

[self createUserWithName:@"John"]; 

Метод doSomethingWith: асинхронно выполняется в блоке завершения.

В качестве альтернативы использовать блок пользовательского завершения

- (void)createUserWithName:(NSString *)theName completion:^(NSString *identifier)completion 
{ 
    NSURL *URL =someUrlthatIncludesTheName 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; 
    [request setHTTPMethod:@"GET"]; 
    NSURLSession *session = [NSURLSession sharedSession]; 
    NSURL *URL = [NSURL URLWithString:url]; 
    NSURLSessionTask *task = [session dataTaskWithURL:URL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
     if (response) { 
      NSError* error = nil; 
      NSArray *output = [NSJSONSerialization JSONObjectWithData:data 
                  options:NSJSONReadingMutableContainers 
                  error:&error]; 
      myID = [[output objectAtIndex:0] objectForKey:@"UserID"]; 
      completion(myID); 
     } 
    }]; 
    [task resume]; 
} 

и назвать его

[self createUserWithName:@"John" completion:^(NSString *identifier) { 
    [self doSomethingWith:identifier]; 
}]; 
+0

Я предполагаю, что это трюк. Ради этого вопроса я упростил свой код. Фактически, «doSomethingWith:» принимает кучу других аргументов. Поэтому я должен передать все эти аргументы в «createUserWithName», что делает код нечитаемым. – Sjakelien

+1

Альтернативой является дополнительный блок завершения в вашем методе 'createUserWithName:'. Затем вы можете захватить другие параметры в блоке. – vadian

Смежные вопросы