Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iOS代码执行错误_Ios_Concurrency_Swift - Fatal编程技术网

iOS代码执行错误

iOS代码执行错误,ios,concurrency,swift,Ios,Concurrency,Swift,我正试图根据TouchID尝试登录的结果更改标签上的文本,但是有一个延迟。当我尝试导航到另一个视图(如此处的视频显示)时,也会发生同样的情况 假设我有一个开关来处理不同的登录错误可能性,在每种情况下,如果我尝试更改标签,就会出现延迟,如果我使用这些情况来更改字符串变量的内容,并尝试将此变量的内容分配给函数末尾的标签,断点显示将变量分配给标签的行在评估登录尝试的块之前执行,代码如下: func requestUserAuthentication() { var myContext:LAC

我正试图根据TouchID尝试登录的结果更改标签上的文本,但是有一个延迟。当我尝试导航到另一个视图(如此处的视频显示)时,也会发生同样的情况

假设我有一个开关来处理不同的登录错误可能性,在每种情况下,如果我尝试更改标签,就会出现延迟,如果我使用这些情况来更改字符串变量的内容,并尝试将此变量的内容分配给函数末尾的标签,断点显示将变量分配给标签的行在评估登录尝试的块之前执行,代码如下:

func requestUserAuthentication() {

    var myContext:LAContext = LAContext()
    var authError:NSError?
    var myLocalizedRasonMessage = "Please authenticate using your fingerprint"

    if (myContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error:&authError)) {
        myContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedRasonMessage) { success, error in

            if (success) {
                self.requestAuthenticationOutput = "Login successful"
            }

            else {
                switch error.code {
                case LAError.AuthenticationFailed.toRaw():
                    self.requestAuthenticationOutput = "Login failed"

                case LAError.UserCancel.toRaw():
                    self.requestAuthenticationOutput = "User canceled"

                case LAError.SystemCancel.toRaw():
                    self.requestAuthenticationOutput = "System canceled"

                case LAError.UserFallback.toRaw():
                    self.requestAuthenticationOutput = "User pressed \"Enter Password\""

                default:
                    self.requestAuthenticationOutput = "TouchID is not configured"
                }
            }

        }
    }
    else {
        switch authError!.code {
        case LAError.TouchIDNotAvailable.toRaw():
            self.requestAuthenticationOutput = "No Touch ID on device"
        case LAError.TouchIDNotEnrolled.toRaw():
            self.requestAuthenticationOutput = "No fingers enrolled"
        case LAError.PasscodeNotSet.toRaw():
            self.requestAuthenticationOutput = "No passcode set"
        default:
            self.requestAuthenticationOutput = "Something went wrong getting local auth"
        }
    }

    self.statusLabel.text = self.requestAuthenticationOutput
}
在案例中,作为输出结果的一种方式,唯一能立即执行的是警报。
我不熟悉iOS编程,但我怀疑它与异步代码执行有关,但我还没有完全理解如何使用GCD/queues/等。如何让函数中的最后一行等待第一部分完成执行?任何想法都将不胜感激。(我使用的是swift,但测试ObjC也得到了同样的结果)

任何时候你看到UI出现这样的问题时,你都应该考虑调用UI更改的线程

正在阅读有关评估政策的文档:。。。您将发现以下有用的注释:

该方法不会阻塞。相反,调用方必须提供一个应答块,以便在评估完成时异步调用。在未指定的线程上下文中,在框架内部的私有队列上执行该块。除此之外,不保证在哪个队列、线程或运行循环上执行块。


因为所有UI调用都必须在主线程上进行,我想如果您将UI调用分派到主线程(通过类似于
dispatch\u async()
)的方式),您将看到更好的结果。

简单的回答是,您不能让代码等待指纹验证成功或失败(前提是设备能够)

获得所需效果的一种方法是在成功/错误块中获得结果后更新UI。由于此代码不在主(UI)线程上执行,因此需要使用GCD在主线程中执行此代码

下面列出了一个函数updateStatusLabel,它实现了这一点。即使在主线程中执行此操作——在API不可用的情况下,也将是完全安全的

func updateStatusLabel()
{
   dispatch_async(dispatch_get_main_queue(), 
      {
        self.statusLabel.text = self.requestAuthenticationOutput
      })
}

var myContext:LAContext = LAContext()
var authError:NSError?
var myLocalizedRasonMessage = "Please authenticate using your fingerprint"

if (myContext.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error:&authError)) {
    myContext.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedRasonMessage) { success, error in

        // ...Other code ommitted to set self.requestAuthenticationOutput

        // Update UI
        self.updateStatusLabel()
    }
}
else {
    switch authError!.code {
    case LAError.TouchIDNotAvailable.toRaw():
        self.requestAuthenticationOutput = "No Touch ID on device"
    case LAError.TouchIDNotEnrolled.toRaw():
        self.requestAuthenticationOutput = "No fingers enrolled"
    case LAError.PasscodeNotSet.toRaw():
        self.requestAuthenticationOutput = "No passcode set"
    default:
        self.requestAuthenticationOutput = "Something went wrong getting local auth"
    }
}

  self.updateStatusLabel()
}

非常感谢你!我已经尝试过使用dispatch_asyn,但是,我已经将所有内容都包装在其中,除了分配标签文本的行,结果证明我应该做完全相反的事情。