ios - 更新 dispatch_sync 队列中的 UI (activityIndi​​cator)( Objective-C )

标签 ios objective-c multithreading grand-central-dispatch dispatch-async

这是我的登录按钮:

- (IBAction)signInButtonAction:(id)sender
{
    if ([self.phoneNumberTextField.text length] == 0 || [self.passwordTextField.text length] == 0) {
        [self initializeAlertControllerForOneButtonWithTitle:@"Alert!" withMessage:kEmptyTextFieldAlertMSG withYesButtonTitle:@"Ok" withYesButtonAction:nil];

    } else {
        if ([self alreadyRegisteredPhoneNumber] == YES) {
            if ([self.password isEqualToString:self.passwordTextField.text]) {
                [self goToHomeViewController];

            } else {
                [self initializeAlertControllerForOneButtonWithTitle:@"Wrong Password!" withMessage:kWrongPasswordMSG withYesButtonTitle:@"Ok" withYesButtonAction:nil];

            }

        } else {
            [self initializeAlertControllerForOneButtonWithTitle:@"Alert!" withMessage:kSignInPhoneNumberDoesnotExistMSG withYesButtonTitle:@"Ok" withYesButtonAction:nil];
        }
    }
}

这是我的 alreadyRegisteredPhoneNumber 方法,我只是在其中检查给定的电话号码是否已注册。

- (BOOL)alreadyRegisteredPhoneNumber
{
    [self.activityIndicator startAnimating];
    __block BOOL isThisPhoneNumberRegistered = NO;

    BlockWeakSelf weakSelf = self;
    SignInViewController *strongSelf = weakSelf;

    dispatch_sync(dispatch_queue_create("mySyncQueue", NULL), ^{
        NSString *PhoneNumberWithIsoCountryCode = [NSString stringWithFormat:@"%@%@", strongSelf.countryCode, strongSelf.phoneNumberTextField.text];
        strongSelf.userModelClass = [[RetrieveDataClass class] retrieveUserInfoForPhoneNumber:PhoneNumberWithIsoCountryCode];
        if ([strongSelf.userModelClass.phone_number length] != 0) {
            strongSelf.phoneNumber = strongSelf.userModelClass.phone_number;
            strongSelf.password = strongSelf.userModelClass.password;
            isThisPhoneNumberRegistered = YES;
            [strongSelf.activityIndicator stopAnimating];
        }
    });

    return isThisPhoneNumberRegistered;
}

使用此方法时,问题是当我按下 Sign In 按钮时 activityIndi​​cator 没有出现。否则它会以同步方式工作,这是完美的。

activityIndi​​cator 没有出现的原因是我必须更新 dispatch_async(dispatch_get_main_queue() 中与 UI 相关的更改(或者不是??)。但是如果我重新安排我的像这样的代码:

- (BOOL)alreadyRegisteredPhoneNumber
{
    [self.activityIndicator startAnimating];
    __block BOOL isThisPhoneNumberRegistered = NO;

    BlockWeakSelf weakSelf = self;
    SignInViewController *strongSelf = weakSelf;

    dispatch_async(dispatch_get_main_queue(), ^{

        dispatch_sync(dispatch_queue_create("mySyncQueue", NULL), ^{
            NSString *PhoneNumberWithIsoCountryCode = [NSString stringWithFormat:@"%@%@", strongSelf.countryCode, strongSelf.phoneNumberTextField.text];
            strongSelf.userModelClass = [[RetrieveDataClass class] retrieveUserInfoForPhoneNumber:PhoneNumberWithIsoCountryCode];
            if ([strongSelf.userModelClass.phone_number length] != 0) {
                strongSelf.phoneNumber = strongSelf.userModelClass.phone_number;
                strongSelf.password = strongSelf.userModelClass.password;
                isThisPhoneNumberRegistered = YES;
                [strongSelf.activityIndicator stopAnimating];
            }
        });
    });

    return isThisPhoneNumberRegistered;
}

activityIndi​​cator 显示完美,但它总是返回 isThisPhoneNumberRegistered = NO,因为它以异步方式工作,其中我的更新 isThisPhoneNumberRegistered = YES最近回来。

所以如果我愿意,这个场景:

  1. 用户按下登录按钮
  2. 然后显示 activityIndi​​cator
  3. 我的服务器调用 (strongSelf.userModelClass = [[RetrieveDataClass class] retrieveUserInfoForPhoneNumber:PhoneNumberWithIsoCountryCode];) 检索数据并设置 isThisPhoneNumberRegistered = YESisThisPhoneNumberRegistered = NO 根据它
  4. 然后将值返回给If else条件

    if ([self alreadyRegisteredPhoneNumber] == YES) {
            if ([self.password isEqualToString:self.passwordTextField.text]) {
                [self goToHomeViewController];
    
    } else {
                [self initializeAlertControllerForOneButtonWithTitle:@"Wrong Password!" withMessage:kWrongPasswordMSG withYesButtonTitle:@"Ok" withYesButtonAction:nil];
    
    }
    

我该怎么做?
非常感谢。

最佳答案

一般来说,您想要使用异步进程,这样您就可以“做其他事情”,例如更新 UI 以让用户知道正在发生的事情。

为了做到这一点,您需要分离您的逻辑。试着用这些术语来思考它:

signInButtonAction {
   if no phone or password entered
      show alert
   else
      showAnimatedSpinner()
      checkForRegisteredPhone()
}

checkForRegisteredPhone {
   // start your async check phone number process
   //  on return from the async call,
   if !registered
      hide spinner
      show kSignInPhoneNumberDoesnotExistMSG message
   else
      checkForMatchingPassword()
}

checkForMatchingPassword {
   if !passwordsMatch
      hide spinner
      show "passwords don't match" message
   else
      hide spinner
      goToHomeViewController
}

换句话说,不要编写代码,以免其“锁定”到进程中,从而阻止其他任何事情发生。

关于ios - 更新 dispatch_sync 队列中的 UI (activityIndi​​cator)( Objective-C ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43722432/

相关文章:

java - Java中如何为特定方法实现Thread?

c++ - 在x86 cpu上进行比较和交流

ios - UIButton 在使用自动布局时在 iPhone6 模拟器中拉伸(stretch)

ios - AVCaptureAudioDataOutputSampleBufferDelegate 未调用 captureOutput

ios - 从 iOS 应用程序将凭据传递到 Safari

ios - 尝试设置弹出窗口时 UITextView 为零

java - 为什么在单独的线程池中将阻塞操作与非阻塞操作分开是一个更好的主意,而不是在一个线程池中执行所有操作?

iphone - rightbarbuttonitem不显示

iphone - 如何删除ios中的导航栏?

ios - 带有部分重复单元格的 UITableView