2015-06-20 109 views
8

在下面的代碼中,我調用了函數displayMyAlertMessage()兩次。我打電話的第一個工作是完美的,但第二個給我一個錯誤,說該函數只能從主線程調用。我怎麼能在我的情況下做到這一點?函數只能在主線程中調用,爲什麼?

我使用這個代碼:

@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() 
} 

調用這個函數:

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) 
} 

我得到的錯誤:

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) 
+0

只能更改主線程的UI,你試圖把它從後臺線程改變。 – nhgrif

+0

@nhgrif什麼是正確的方式來做我想做的事情? – sdd

回答

12

您必須更新從UI元素主隊列有時候可以工作,但是大多數情況下,當你在應用中出現奇怪的行爲時,編譯器就是w arning你,有時需要數天才能找到這樣的錯誤時,事情只是不工作

使用下面的代碼來調用或解散你的警報意見

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

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

您可以在Grand Central Dispatch (GCD) Reference

查看其詳細
+0

完美,謝謝 – sdd

+0

@sdd很高興我可以幫助你,與你的應用程序很好運! – Icaro

0

你應該把你的進程放到隊列中來讓它執行。

你可以參考下面的例子,當我遇到同樣的問題時,我能如何解決它。

var storyBoard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
var vc: UINavigationController = storyBoard.instantiateViewControllerWithIdentifier("AppViewController") as! UINavigationController 

NSOperationQueue.mainQueue().addOperationWithBlock { 
    self.presentViewController(vc, animated: true, completion: nil) 
    //Above line was generating same exception in my scenario 
    // I got it resolved by using NSOperationQueue.mainQueue().addOperationWithBlock { 
} 
3

您需要先關閉您的警報視圖。使用下面的代碼來做到這一點。

工程與斯威夫特3

DispatchQueue.main.async { 
    your code goes here 
} 
相關問題