简体   繁体   English

iOS Swift仅在应用程序的主线程错误上运行

[英]iOS Swift Only run on the main thread error for app

I am new to swift and I have a login page that takes the users credentials and check if it's the right credentials .我是 swift 的新手,我有一个登录页面,可以获取用户凭据并检查它是否是正确的凭据。 I think return the response in JSON if it's the right credentials then I try to go to a new ViewController .I got this error when I try to go to a new View Controller, I have this in a closure so I do not know why I am getting this issue.我认为如果它是正确的凭据,则返回 JSON 中的响应,然后我尝试转到一个新的 ViewController 。当我尝试转到一个新的 ViewController 时出现此错误,我将其放在一个闭包中,所以我不知道为什么我我得到这个问题。 This is my code这是我的代码

func LoginClosure(completion:@escaping (Bool) ->Void) {
    var check = 0
    let url:URL = URL(string:ConnectionString+"login")!

    if submitEmail == nil || submitPassword == nil {
        submitEmail = email.text!
        submitPassword = password.text!
    }

    let session = URLSession.shared
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    let parameter = "Email=\(submitEmail!)&password=\(submitPassword!)"
    request.httpBody = parameter.data(using: String.Encoding.utf8)
    DispatchQueue.main.async {
        session.dataTask(with:request, completionHandler: { (data, response, error) in
            if error != nil {
                // print(error)
            } else {
                do {
                    let parsedData = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:Any]

                    if let Streams = parsedData?["Profile"] as? [AnyObject]  {
                        // check for misspelled words
                        for Stream in Streams {
                            if let rr = Stream["result"] as? Bool {
                                self.result = rr
                            } else {
                                self.result = true
                            }

                            if let id = Stream["id"] as? Int {
                                self.defaults.setValue(id, forKey: "my_id")
                                // Success
                                MYID = id
                                completion(true)
                                return
                            }
                        }

                        if check == 0 {
                            // Bad credentials
                            completion(false)
                        }
                    }
                } catch let error as NSError {
                    print(error)
                }
            }
        }).resume()
    }
}

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!' *** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“仅在主线程上运行!”

That error occurs with this line:此行发生该错误:

let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
self.present(next, animated: true, completion: nil)

As per apple standards, you have to perform UI activity in the main queue only.根据苹果标准,您只需在主队列中执行 UI 活动。

Just call your closure in the main queue as below.只需在main queue调用您的闭包,如下所示。

DispatchQueue.main.async {
    completion(true)
}

You can also perform only UI changes in the main queue as below.您还可以在main queue仅执行 UI 更改,如下所示。

DispatchQueue.main.async {
    let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
    self.present(next, animated: true, completion: nil)
}

@rmaddy Thanks for the valuable suggestion. @rmaddy 感谢您的宝贵建议。

In your code, I see that you have initiated the network call in the main queue.在您的代码中,我看到您已在主队列中发起网络调用。 That makes sure that creation of the data task and starting it off will be performed on the main thread.这确保数据任务的创建和启动将在主线程上执行。 But it doesn't guarantee that the completion closure will also be called on the main thread.但它并不能保证在主线程上也会调用完成闭包。

Therefore I would suggest removing the network call from the DispatchQueue.main.async block.因此,我建议从DispatchQueue.main.async块中删除网络调用。 Then please execute the code that performs UI updation in a DispatchQueue.main.async block as follows.然后请在DispatchQueue.main.async block中执行执行 UI 更新的代码,如下所示。

DispatchQueue.main.async {    
    let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
    self.present(next, animated: true, completion: nil)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Xcode 9.0 Swift 04(由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序,原因:“仅在主线程上运行!”) - Xcode 9.0 Swift 04 (Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!') 'NSInternalInconsistencyException',原因:'只在主线程上运行!' 错误 - 'NSInternalInconsistencyException', reason: 'Only run on the main thread!' error swift 4错误:' - [UIKeyboardTaskQueue waitUntilAllTask​​sAreFinished]可能只能从主线程调用 - swift 4 error : '-[UIKeyboardTaskQueue waitUntilAllTasksAreFinished] may only be called from the main thread 仅在主线程上运行异常 - Only run on the main thread exception iOS,Swift,无法访问NSURLSession中的主线程 - IOS, Swift, No way to access main thread in NSURLSession Swift / iOS子视图未立即显示在主线程上 - Swift/iOS Subview Not Showing Immediately, on Main Thread iOS快速背景线程阻塞了主线程 - iOS swift background threads blocking the main thread Closure不会在swift的主线程中运行 - Closure does not run in the main thread in swift “仅在主线程上运行”异常仅限于模拟器 - “Only run on the main thread” exception is simulator only Swift 本地通知检查器仅主线程 - Swift Local Notifications Checker Main Thread Only
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM