函数只能在主线程中调用,为什么? [英] Function can only be called in the main thread, why?

查看:169
本文介绍了函数只能在主线程中调用,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我调用了函数displayMyAlertMessage()两次。我打电话的第一个工作是完美的,但第二个给我一个错误,说该函数只能从主线程调用。我怎么能在我的情况下做到这一点?



我使用以下代码:

  @IBAction func loginButtonTapped sender:AnyObject){
result2Value =
let userEmail = userEmailTextField.text
let userPassword = userPasswordTextField.text
$ b $ if userPassword.isEmpty || userPassword.isEmpty {
displayMyAlertMessage(所有字段都是必需的)
return;
}
//将用户数据发送到服务器端
let myUrl = NSURL(string:http://www.avanta.com/extra/test-userLogin.php)
let request = NSMutableURLRequest(URL:myUrl!)
request.HTTPMethod =POST

let postString =email = \(userEmail)& password = \(userPassword )
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

let task = NSURLSession.sharedSession()。dataTaskWithRequest(request){
data,response,error in
if error!= nil {
println(error \(error))
return
}
var err:NSError?
var json = NSJSONSerialization.JSONObjectWithData(data,options:.MutableContainers,error:& err)as? NSDictionary
如果让parseJSON = json {
var resultValue:String = parseJSON [status] as!串!
println(result:\(resultValue))

if(resultValue ==Success){
//登录成功
NSUserDefaults.standardUserDefaults ).setBool(true,forKey:isUserLogin)
NSUserDefaults.standardUserDefaults()。synchronize()

self.dismissViewControllerAnimated(true,completion:nil)
//返回

else {
self.displayMyAlertMessage(错误的名称或密码)
}
}
}
task.resume()
}

调用这个函数:

  func displayMyAlertMessage(userMessage:String){
var myAlert = UIAlertController(title:Alert,message:userMessage,preferredStyle:UIAlertControllerStyle.Alert)
让okAction = UIAlertAction(title:Ok,style:UIAlertActionStyle.Default,handler:nil)
myAlert.addAction(ok Action)
self.presentViewController(myAlert,animated:true,completion:nil)
}

我得到的错误: $ b

  2015-06-20 14:44: 41.646 UserLoginAndRegistration [6064:750474] ***声明失败 -  [UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished],/SourceCache/UIKit/UIKit-3318.16.14/Keyboard/UIKeyboardTaskQueue.m:374 
2015-06-20 14:44: 41.657 UserLoginAndRegistration [6064:750474] ***终止应用程序,由于未捕获的异常'NSInternalInconsistencyException',原因:' - [UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished]只能从主线程调用'
***第一个抛出调用堆栈:
(0x186551e48 0x196c4c0e4 0x186551d08 0x1873d5554 0x18ad2b0a8 0x18ad2b734 0x18ad24a1c 0x18b251564 0x18b0156a8 0x18b0169e4 0x18b0188dc 0x18adee0b4 0x100028f9c 0x10002b500 0x10002b5f4 0x10002b624 0x10002b68c 0x185ee6540 0x187407508 0x187358c94 0x18734861c 0x18740a2 6c 0x1005a4df0 0x1005af854 0x1005a8120 0x1005b175c 0x1005b2f18 0x19746d2e4 0x19746cfa8)
libc ++ abi.dylib:以NSException类型的未捕获异常终止
(lldb)


解决方案

您必须始终从主队列中更新UI元素,有时可以在您不需要时工作,但大多数时候您有奇怪的行为你的应用程序,你的运气,编译器警告你,有时需要几天时间才能发现错误,如果事情不起作用的话。使用以下代码调用和解除你的提醒视图

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ dispatch_async(dispatch_get_main_queue()){
self.dismissViewControllerAnimated(true,completion:nil)

$ b dispatch_async(dispatch_get_main_queue()){
self.displayMyAlertMessage(错误的名称或密码)
}

您可以在 Grand Central Dispatch(GCD)参考资料


In this code below I am calling the function displayMyAlertMessage() twice. the first I am calling works perfect, but the second one gives me an error saying that the function may only be called from the main thread. How can I do this in my situation?

I am using this code:

@IBAction func loginButtonTapped(sender: AnyObject) {
    result2Value = ""
    let userEmail = userEmailTextField.text
    let userPassword = userPasswordTextField.text

    if userPassword.isEmpty || userPassword.isEmpty {
        displayMyAlertMessage("All fields are required")
return;
    }
    //send user data to server side
    let myUrl = NSURL(string: "http://www.avanta.com/extra/test-userLogin.php")
    let request = NSMutableURLRequest(URL:myUrl!)
    request.HTTPMethod = "POST"

    let postString = "email=\(userEmail)&password=\(userPassword)"
    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
        data, response, error in
        if error != nil{
            println("error\(error)")
            return
        }
        var err:NSError?
        var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err) as? NSDictionary
        if let parseJSON = json { 
            var resultValue:String = parseJSON["status"] as! String!
            println("result: \(resultValue)")

            if (resultValue == "Success") {
            //login succesful
                NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isUserLogin")
                NSUserDefaults.standardUserDefaults().synchronize()

                self.dismissViewControllerAnimated(true, completion: nil)
               // return
            }
            else{
              self.displayMyAlertMessage("Wrong name or password")
            }
        }
    }
    task.resume()
}

To call this function:

func displayMyAlertMessage(userMessage:String){
    var myAlert = UIAlertController(title:"Alert", message:userMessage, preferredStyle: UIAlertControllerStyle.Alert)
    let okAction = UIAlertAction(title:"Ok", style:UIAlertActionStyle.Default, handler:nil)
    myAlert.addAction(okAction)
    self.presentViewController(myAlert, animated:true, completion:nil)
}

The error I am getting:

2015-06-20 14:44:41.646 UserLoginAndRegistration[6064:750474] *** Assertion        failure in -[UIKeyboardTaskQueue waitUntilAllTasksAreFinished],    /SourceCache/UIKit/UIKit-3318.16.14/Keyboard/UIKeyboardTaskQueue.m:374
2015-06-20 14:44:41.657 UserLoginAndRegistration[6064:750474] *** Terminating   app due to uncaught exception 'NSInternalInconsistencyException', reason: '- [UIKeyboardTaskQueue waitUntilAllTasksAreFinished] may only be called from the  main thread.'
*** First throw call stack:
(0x186551e48 0x196c4c0e4 0x186551d08 0x1873d5554 0x18ad2b0a8 0x18ad2b734  0x18ad24a1c 0x18b251564 0x18b0156a8 0x18b0169e4 0x18b0188dc 0x18adee0b4 0x100028f9c 0x10002b500 0x10002b5f4 0x10002b624 0x10002b68c 0x185ee6540 0x187407508 0x187358c94 0x18734861c 0x18740a26c 0x1005a4df0 0x1005af854 0x1005a8120 0x1005b175c 0x1005b2f18 0x19746d2e4 0x19746cfa8)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

解决方案

You must always update UI elements from the main queue, sometimes works when you don't but most the time you have weird behaviours in your app, you luck that the compiler is warning you, sometimes take days to find mistakes like that when things just don't work

Use the code below to call and dismiss your alert views

dispatch_async(dispatch_get_main_queue()) {
    self.dismissViewControllerAnimated(true, completion: nil)
} 

dispatch_async(dispatch_get_main_queue()) {
    self.displayMyAlertMessage("Wrong name or password")
}

You can see more detail about it at Grand Central Dispatch (GCD) Reference

这篇关于函数只能在主线程中调用,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆