2015-04-30 4 views
0

Я подключаю свое приложение к API для отдыха, чтобы войти в систему пользователя. Когда процедура входа в систему завершена, я использую NSNotificationCenter, чтобы сообщить контроллеру о успешном входе в систему и для приложения выполнить сеанс, чтобы взять пользователя из главного меню. Вот мой код:iOS программно сгенерированный segue выполняется несколько раз с успехом

//perform log in, or show error message 
-(void)logInAttemptComplete:(NSNotification *)notification 
{ 
Boolean loginSuccessful = (Boolean)[[notification userInfo] objectForKey:@"loginSuccessful"]; 

[SVProgressHUD dismiss]; 
//if the suer was successfully logged in, take him to the main menu 
if(loginSuccessful) 
{ 
    //go to the main menu 
    [self performSegueWithIdentifier:@"logInSuccessfulSegue" sender:self]; 
} 
else 
{ 
    //copy error code and display appropriate error 
    int errorCode = [[[notification userInfo] objectForKey:@"HTTP Message"] intValue]; 
    //404 no server, 401 wrong password/no user 
    if(errorCode==401) 
    { 
     //create and show error alert view 
     UIAlertView *loginErrorAlertView = [[UIAlertView alloc] initWithTitle:@"Log In Failure" message:@"Wrong credentials. Check your Username and/or Password." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     [loginErrorAlertView show]; 
    } 
    else 
    { 
     //create and show error alert view 
     UIAlertView *loginErrorAlertView = [[UIAlertView alloc] initWithTitle:@"Log In Failure" message:@"Failed to contact server, please try again later." delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil]; 
     [loginErrorAlertView show]; 
    } 
} 
} 

Проблема заключается в том, что если журнал в не удается с первой попытки, и скажем, что взять X число попыток, чтобы успешно войти, то переход выполняется X число раз. Конечно, в основном это главное меню, но конечный результат уродлив. Любые идеи, как это исправить? Возможно, мне следует избегать использования segue и программно принимать пользователя hte непосредственно на другой контроллер?

EDIT С ОТВЕТА

Так что я сделал ошибку, добавив строку

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logInAttemptComplete:) name:@"logInNotification" object:nil]; 

внутри функции, нажав журнал в кнопке.

Я зафиксировал его удалением наблюдателя после того, как попытка Войти не удалось

if(loginSuccessful) 
{ 
//go to the main menu 
[self performSegueWithIdentifier:@"logInSuccessfulSegue" sender:self]; 
} 
else 
{ 

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"logInNotification" object:nil]; 

ответ

0

Найдено это:

проблема была, что контроллер держал «прослушивание» даже когда было отправлено сообщение об ошибке из-за

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logInAttemptComplete:) name:@"logInNotification" object:nil]; 

находится внутри функции нажатия кнопки входа в систему.

Все, что я должен был сделать, это добавить строку

[[NSNotificationCenter defaultCenter] removeObserver:self name:@"logInNotification" object:nil]; 

после

if(loginSuccessful) 
{ 
//go to the main menu 
[self performSegueWithIdentifier:@"logInSuccessfulSegue" sender:self]; 
} 
else 
{ 

еще чеки.

1

Я хотел бы использовать два различных уведомлений, этот код кажется более сложным, чем это должно быть.

Вы не указали свой код входа, поэтому я могу отвечать только в целом. Создайте два уведомления (один для успешного и один для входа в систему). Контроллер входа отправляет либо уведомление в зависимости от результата попытки входа в систему.

Вы разделяете описанный выше метод двумя способами, которые вызывают при отправке любого из уведомлений.

Ваш код может выглядеть следующим образом:

[manager GET:stringWithURLforRequest parameters:nil success:^(AFHTTPRequestOperation *task, id responseObject) { 

    // ... 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"LogInSuccessful" object:nil userInfo:nil]; 

} failure:^(AFHTTPRequestOperation *task, NSError *error) { 

    // ...  
    [[NSNotificationCenter defaultCenter] postNotificationName:@"LogInFailure" object:nil userInfo:@{ @"HTTP Message":statusCodeNumber}]; 

}]; 

... и вам просто нужно добавить еще одно уведомление, слушая ваш другой контроллер представления. Если вы это сделаете, у вас будет более безопасная дифференциация между неудачей входа и успехом (лучшая семантика).

+0

Я обновил свой код с помощью регистрационного кода моей модели пользователя ... или, по крайней мере, для входа в систему –

+0

Обновлен мой ответ, чтобы показать, что я имею в виду –

+0

Хорошо ли, если я создаю NSNotification listerner, который никогда не используется? –

0

Если @ «loginSuccessful» в вашем userInfo является NSNumber использования:

BOOL loginSuccessful = [notification.userInfor[@"loginSuccessful"] booleanValue]; 

В исходном коде, если объект не был nil (и если я правильно это всегда понимаю) вы всегда получите loginSuccessful с значение ДА, потому что вы проверили существование объекта, а не его ценность.

Вы используете NSNumber в этой строке:

@{@"loginSuccessful":@YES} 

@YES просто короток для [NSNumber numberWithBool:YES]

Acording к this header Boolean только неподписанные символ так вы подписываете указатель на этот полукокса, и он будет всегда быть правдой (не NULL).

+0

нет, это не NSnumber, это логическое значение –

+0

Пожалуйста, см. Мое редактирование. –

+0

, но я все еще придумал, и он работал правильно, segue не запускался каждый раз, только когда это было да. во всяком случае, я сделал то, что вы рекомендовали, потому что это «более правильно», но проблема все еще существует. –

0

Из того, что я понимаю, вы отправляете уведомление об успехе, и его вызывают слишком много раз, если были попытки.

Однострочное исправление должно состоять в том, чтобы STOP прослушивал это уведомление в методе успеха.

Таким образом, вы бы что-то вдоль этих линий (псевдо код)

- (void)loginAttempt:(NSNotifcation*)notif{ 
    if (success){ 
//Stop listening to that notification, so the method never gets called again 
    performSegueWithIndetifier 
    }else{ 

    //retry 

    } 
} 

Другой грязный один лайнер способ сделать это, чтобы сохранить Ивар числа попыток и вызывать только преформы SEGUE если это число в настоящее время равно нулю.

Я думаю, что мое решение исправит вашу проблему, но если у вас есть время, я предлагаю вам просмотреть свой дизайн таким образом, что вы переходите к вызову только тогда, когда его нужно вызвать или что обратные вызовы других успехов X игнорируются. Простой способ представить, что это не повторить попытку, пока не будет указан предыдущий логин. И поэтому вы не повторить, пока вы на самом деле не знаете, если вы не смогли или нет (кастрированный баран это тайм-аут или успех или что-нибудь еще)