[英]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.