2014-01-22 6 views
1

У меня есть класс, который обрабатывает взаимодействие с внешним API, и я пытаюсь найти лучший способ разбить их на дескриптивные фрагменты.Лучший способ создания вложенных обратных вызовов в ObjectiveC

На данный момент, это выглядит примерно так:

- (BOOL) testCredentialsWithUsername:(NSString *)username password:(NSString *)password { 
    acUsername = username; 
    acPassword = password; 
    [self loadLoginPage]; 
    return YES; 
} 

- (void)loadLoginPage { 
    [NSURLConnection sendAsynchronousRequest:... 
          completionHandler:^(...) { 
           [self logIntoMyAPI:response]; 
          }]; 
} 

- (void)logIntoMyAPI:(NSURLResponse *)response { 
    [NSURLConnection sendAsynchronousRequest:... 
          completionHandler:^(...) { 
           [self recieveLoginResponse:response data:data]; 
          }]; 
} 

- (void)recieveLoginResponse:(NSURLResponse *) response data:(NSData *)data { 
    if (...) { 
     NSLog(@"Logged into MyAPI!"); 
    } else if (...) { 
     NSLog(@"Invalid username or password"); 
    } else if (...) { 
     NSLog(@"Locked account"); 
    } else { 
     NSLog(@"An unexpected error"); 
    } 
} 

В принципе, я хочу, чтобы позвонить testCredtionalsWithUsername:password: из моего View Controller и, возможно, с использованием блоков успех/провал, знаете результат.

Каков наилучший способ сделать это без привязки обратных вызовов к тесту testCredtionalsWithUsername:password:?

+1

Давида, может иметь отношение ... http://stackoverflow.com/questions/21775023/is-there-any -way-to-wait-here-in-code-just-like-a-empty-loop И не забывайте о группах отправки. http://stackoverflow.com/questions/10643797/wait-until-multiple-operations -executed-including-completion-block-afnetworki/10644282 # 10644282 – Fattie

+1

@JoeBlow Теперь, когда я перешел на более сложные части приложения ... это именно то, что я хочу! Благодаря! –

+0

фантастический !!!!! – Fattie

ответ

1

Вам нужно подождать, пока ваш сервер ответит, прежде чем вы получите результат теста, так что нет никакой реальной точки в возвращении BOOL из testCredentialsWithUsername: password: кажется.

Элегантное решение состоит в том, чтобы иметь завершающий блок, который вызывается всякий раз, когда у вас есть ответ. Как это:

- (void) testCredentialsWithUsername:(NSString *)username password:(NSString *)password completion:(void (^)(BOOL success, NSError *error))completion { 
    acUsername = username; 
    acPassword = password; 
    _validationCompletion = completion; // Save this as an instance variable 
    [self loadLoginPage]; 
} 

Когда вы получите результат от сервера:

- (void)recieveLoginResponse:(NSURLResponse *) response data:(NSData *)data { 
    BOOL success = data != nil; //or whatever you criteria is. 

    if (_completion != nil) { 

     NSError = success ? nil : [NSError new]; // create an appropriate error object 

     _completion(success, error) 
     _completion = nil; 
    } 
} 
+0

Да, вернувшийся BOOL не имеет смысла больше видеть, поскольку он асинхронный. Установка блока завершения в качестве переменной экземпляра была по линиям, которые я думал, но не был уверен, что делать это было лучше всего. –

+0

Удивительный. Получил это уик-энд сегодня с большим успехом. Благодаря! –

0

Вы можете добавить два свойства для блока успеха и блока отказов в этот класс и вызвать его, когда запрос будет завершен. В вашем представлении контроллер выделяет экземпляр этого класса и передает ему два блока. Вы также можете добавить initWithSuccessBlock: failureBlock: метод к этому классу, и в вашем контроллере просмотра просто вызовите этот метод при инициализации этого класса.

Надеюсь, что эта помощь.

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