iOS Swift 只有 运行 应用程序的主线程错误
iOS Swift Only run on the main thread error for app
我是 swift 的新手,我有一个登录页面,它获取用户凭据并检查它是否是正确的凭据。我认为 return JSON 中的响应如果它是正确的凭据,那么我会尝试转到新的 ViewController 。当我尝试转到新的视图控制器时出现此错误,我关闭它,所以我不知道为什么会遇到这个问题。这是我的代码
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!'
此行出现该错误:
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.
只需在 main queue
中调用您的闭包,如下所示。
DispatchQueue.main.async {
completion(true)
}
您也可以在 main queue
中仅执行 UI 更改,如下所示。
DispatchQueue.main.async {
let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
self.present(next, animated: true, completion: nil)
}
@rmaddy 感谢您的宝贵建议。
在你的代码中,我看到你在主队列中发起了网络调用。这确保了数据任务的创建和启动将在主线程上执行。但它不保证完成闭包也会在主线程上被调用。
因此我建议从 DispatchQueue.main.async
块中删除网络调用。然后请在DispatchQueue.main.async block
中执行执行UI更新的代码如下。
DispatchQueue.main.async {
let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
self.present(next, animated: true, completion: nil)
}
我是 swift 的新手,我有一个登录页面,它获取用户凭据并检查它是否是正确的凭据。我认为 return JSON 中的响应如果它是正确的凭据,那么我会尝试转到新的 ViewController 。当我尝试转到新的视图控制器时出现此错误,我关闭它,所以我不知道为什么会遇到这个问题。这是我的代码
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!'
此行出现该错误:
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.
只需在 main queue
中调用您的闭包,如下所示。
DispatchQueue.main.async {
completion(true)
}
您也可以在 main queue
中仅执行 UI 更改,如下所示。
DispatchQueue.main.async {
let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
self.present(next, animated: true, completion: nil)
}
@rmaddy 感谢您的宝贵建议。
在你的代码中,我看到你在主队列中发起了网络调用。这确保了数据任务的创建和启动将在主线程上执行。但它不保证完成闭包也会在主线程上被调用。
因此我建议从 DispatchQueue.main.async
块中删除网络调用。然后请在DispatchQueue.main.async block
中执行执行UI更新的代码如下。
DispatchQueue.main.async {
let next = self.storyboard?.instantiateViewController(withIdentifier: "AccountC") as! AccountC
self.present(next, animated: true, completion: nil)
}