由于未捕获的异常 'NSInternalInconsistencyException' 问题而终止应用程序
Terminating app due to uncaught exception 'NSInternalInconsistencyException' problem
我正在尝试实现一个 table 视图,在每个单元格中显示图书信息。我从 API 获得这些信息。这是我的代码:
class ViewController: UIViewController {
@IBOutlet weak var allBooksTable: UITableView!
var bookList:myList? = nil {
didSet {
allBooksTable.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.allBooksTable.dataSource = self
self.allBooksTable.delegate = self
let url = URL(string: "https://ipvefa0rg0.execute-api.us-east-1.amazonaws.com/dev/books?lang=fr&term=self")!
var request = URLRequest(url: url)
request.setValue(
"jFXzWHx7SkK6",
forHTTPHeaderField: "api-key"
)
request.httpMethod = "GET"
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error.localizedDescription)
} else if let data = data {
do {
let decodedData = try JSONDecoder().decode(myList.self,
from: data)
self.bookList = decodedData
print("user: ", decodedData.list[0].imageLinks.thumbnail)
print("===================================")
} catch let DecodingError.dataCorrupted(context) {
print(context)
} catch let DecodingError.keyNotFound(key, context) {
print("Key '\(key)' not found:", context.debugDescription)
//print("codingPath:", context.codingPath)
} catch let DecodingError.valueNotFound(value, context) {
print("Value '\(value)' not found:", context.debugDescription)
print("codingPath:", context.codingPath)
} catch let DecodingError.typeMismatch(type, context) {
print("Type '\(type)' mismatch:", context.debugDescription)
print("codingPath:", context.codingPath)
} catch {
print("error: ", error)
}
} else {
// Handle unexpected error
}
}
task.resume()
}
}
extension ViewController: UITableViewDataSource , UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell") as! bookTableViewCell
cell.bookName.text = bookList?.list[indexPath.row].title
if bookList?.list[indexPath.row].imageLinks.smallThumbnail != nil{
//cell.img.load(url: (bookList?.list[indexPath.row].imageLinks.smallThumbnail)!)
print((bookList?.list[indexPath.row].imageLinks.smallThumbnail)!)
cell.img.downloaded(from: (bookList?.list[indexPath.row].imageLinks.smallThumbnail)!)
}
return cell
}
}
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
当我 运行 应用程序时,它只显示我的第一本书,然后崩溃并出现以下错误。
2020-10-15 23:12:00.953424+1100 MSA[50129:2517792] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff2043a126 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20177f78 objc_exception_throw + 48
2 CoreAutoLayout 0x00007fff58010d41 -[NSISEngine tryToOptimizeReturningMutuallyExclusiveConstraints] + 0
3 CoreAutoLayout 0x00007fff58010fcd -[NSISEngine withBehaviors:performModifications:] + 25
4 UIKitCore 0x00007fff24ac64ad -[UIView(AdditionalLayoutSupport) _recursiveUpdateConstraintsIfNeededCollectingViews:forSecondPass:] + 112
5 UIKitCore 0x00007fff24ac6136 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 827
6 UIKitCore 0x00007fff24ac6a08 __100-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke + 85
7 UIKitCore 0x00007fff24ac6594 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 154
8 UIKitCore 0x00007fff24ac7482 -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] + 393
9 UIKitCore 0x00007fff24ba9ad6 -[UIView _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 275
10 UIKitCore 0x00007fff24bbda37 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2979
11 QuartzCore 0x00007fff27a3dd87 -[CALayer layoutSublayers] + 258
12 QuartzCore 0x00007fff27a44239 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 575
13 UIKitCore 0x00007fff24ba8fe9 -[UIView(Hierarchy) layoutBelowIfNeeded] + 573
14 UIKitCore 0x00007fff24bb0479 +[UIView(Animation) performWithoutAnimation:] + 84
15 UIKitCore 0x00007fff248954d0 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1300
16 UIKitCore 0x00007fff2485e8bb -[UITableView _updateVisibleCellsNow:] + 2942
17 UIKitCore 0x00007fff2487e6e6 -[UITableView layoutSubviews] + 237
18 UIKitCore 0x00007fff24bbd9ce -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2874
19 QuartzCore 0x00007fff27a3dd87 -[CALayer layoutSublayers] + 258
20 QuartzCore 0x00007fff27a44239 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 575
21 QuartzCore 0x00007fff27a4ff91 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 65
22 QuartzCore 0x00007fff27990078 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 496
23 QuartzCore 0x00007fff279c6e13 _ZN2CA11Transaction6commitEv + 783
24 QuartzCore 0x00007fff279c7616 _ZN2CA11Transaction14release_threadEPv + 210
25 libsystem_pthread.dylib 0x00007fff5dcda054 _pthread_tsd_cleanup + 551
26 libsystem_pthread.dylib 0x00007fff5dcdc512 _pthread_exit + 70
27 libsystem_pthread.dylib 0x00007fff5dcd9ddd _pthread_wqthread_exit + 77
28 libsystem_pthread.dylib 0x00007fff5dcd8afc _pthread_wqthread + 481
29 libsystem_pthread.dylib 0x00007fff5dcd7b77 start_wqthread + 15
)
libc++abi.dylib: terminating with uncaught exception of type NSException
你能帮我理解这是怎么回事吗?我已经查看过类似的线程,但大多数解决方案都是针对该问题的。
问题是您从后台线程设置 bookList
(因为 URLSession.dataTask
在后台线程上调用它的完成)并且在 bookList
的 didSet
中,你更新 UI。您应该将 UI 更新分派到主线程。
var bookList:myList? = nil {
didSet {
DispatchQueue.main.async {
allBooksTable.reloadData()
}
}
}
您可以像下面这样在主线程上设置 bookList
...
DispatchQueue.main.async {
self.bookList = decodedData
}
如果 UI 元素在后台线程中得到更新,这就是应用程序崩溃的原因,所以无论何时你想更新 UI 你都需要在主线程中更新那个 UI 元素,并且您的会话数据任务在后台线程中是 运行 并且您设置了值 bookList
但是当设置 bookList
时有一个 属性 观察者在后台线程中重新加载表视图所以有两个解决方案。
- 在您的 api 调用函数中,您需要像这样在主线程中设置 属性:-
DispatchQueue.main.async {
self.bookList = decodedData
}
- 在你的 属性 观察者中你需要这样做
var bookList:myList? = nil {
didSet {
DispatchQueue.main.async {
allBooksTable.reloadData()
}
}
}
享受:-
我正在尝试实现一个 table 视图,在每个单元格中显示图书信息。我从 API 获得这些信息。这是我的代码:
class ViewController: UIViewController {
@IBOutlet weak var allBooksTable: UITableView!
var bookList:myList? = nil {
didSet {
allBooksTable.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.allBooksTable.dataSource = self
self.allBooksTable.delegate = self
let url = URL(string: "https://ipvefa0rg0.execute-api.us-east-1.amazonaws.com/dev/books?lang=fr&term=self")!
var request = URLRequest(url: url)
request.setValue(
"jFXzWHx7SkK6",
forHTTPHeaderField: "api-key"
)
request.httpMethod = "GET"
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, response, error) in
if let error = error {
print(error.localizedDescription)
} else if let data = data {
do {
let decodedData = try JSONDecoder().decode(myList.self,
from: data)
self.bookList = decodedData
print("user: ", decodedData.list[0].imageLinks.thumbnail)
print("===================================")
} catch let DecodingError.dataCorrupted(context) {
print(context)
} catch let DecodingError.keyNotFound(key, context) {
print("Key '\(key)' not found:", context.debugDescription)
//print("codingPath:", context.codingPath)
} catch let DecodingError.valueNotFound(value, context) {
print("Value '\(value)' not found:", context.debugDescription)
print("codingPath:", context.codingPath)
} catch let DecodingError.typeMismatch(type, context) {
print("Type '\(type)' mismatch:", context.debugDescription)
print("codingPath:", context.codingPath)
} catch {
print("error: ", error)
}
} else {
// Handle unexpected error
}
}
task.resume()
}
}
extension ViewController: UITableViewDataSource , UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell") as! bookTableViewCell
cell.bookName.text = bookList?.list[indexPath.row].title
if bookList?.list[indexPath.row].imageLinks.smallThumbnail != nil{
//cell.img.load(url: (bookList?.list[indexPath.row].imageLinks.smallThumbnail)!)
print((bookList?.list[indexPath.row].imageLinks.smallThumbnail)!)
cell.img.downloaded(from: (bookList?.list[indexPath.row].imageLinks.smallThumbnail)!)
}
return cell
}
}
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() { [weak self] in
self?.image = image
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
当我 运行 应用程序时,它只显示我的第一本书,然后崩溃并出现以下错误。
2020-10-15 23:12:00.953424+1100 MSA[50129:2517792] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff2043a126 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20177f78 objc_exception_throw + 48
2 CoreAutoLayout 0x00007fff58010d41 -[NSISEngine tryToOptimizeReturningMutuallyExclusiveConstraints] + 0
3 CoreAutoLayout 0x00007fff58010fcd -[NSISEngine withBehaviors:performModifications:] + 25
4 UIKitCore 0x00007fff24ac64ad -[UIView(AdditionalLayoutSupport) _recursiveUpdateConstraintsIfNeededCollectingViews:forSecondPass:] + 112
5 UIKitCore 0x00007fff24ac6136 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededCollectingViews:forSecondPass:] + 827
6 UIKitCore 0x00007fff24ac6a08 __100-[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:]_block_invoke + 85
7 UIKitCore 0x00007fff24ac6594 -[UIView(AdditionalLayoutSupport) _updateConstraintsIfNeededWithViewForVariableChangeNotifications:] + 154
8 UIKitCore 0x00007fff24ac7482 -[UIView(AdditionalLayoutSupport) _updateConstraintsAtEngineLevelIfNeededWithViewForVariableChangeNotifications:] + 393
9 UIKitCore 0x00007fff24ba9ad6 -[UIView _updateConstraintsAsNecessaryAndApplyLayoutFromEngine] + 275
10 UIKitCore 0x00007fff24bbda37 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2979
11 QuartzCore 0x00007fff27a3dd87 -[CALayer layoutSublayers] + 258
12 QuartzCore 0x00007fff27a44239 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 575
13 UIKitCore 0x00007fff24ba8fe9 -[UIView(Hierarchy) layoutBelowIfNeeded] + 573
14 UIKitCore 0x00007fff24bb0479 +[UIView(Animation) performWithoutAnimation:] + 84
15 UIKitCore 0x00007fff248954d0 -[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 1300
16 UIKitCore 0x00007fff2485e8bb -[UITableView _updateVisibleCellsNow:] + 2942
17 UIKitCore 0x00007fff2487e6e6 -[UITableView layoutSubviews] + 237
18 UIKitCore 0x00007fff24bbd9ce -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2874
19 QuartzCore 0x00007fff27a3dd87 -[CALayer layoutSublayers] + 258
20 QuartzCore 0x00007fff27a44239 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 575
21 QuartzCore 0x00007fff27a4ff91 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 65
22 QuartzCore 0x00007fff27990078 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 496
23 QuartzCore 0x00007fff279c6e13 _ZN2CA11Transaction6commitEv + 783
24 QuartzCore 0x00007fff279c7616 _ZN2CA11Transaction14release_threadEPv + 210
25 libsystem_pthread.dylib 0x00007fff5dcda054 _pthread_tsd_cleanup + 551
26 libsystem_pthread.dylib 0x00007fff5dcdc512 _pthread_exit + 70
27 libsystem_pthread.dylib 0x00007fff5dcd9ddd _pthread_wqthread_exit + 77
28 libsystem_pthread.dylib 0x00007fff5dcd8afc _pthread_wqthread + 481
29 libsystem_pthread.dylib 0x00007fff5dcd7b77 start_wqthread + 15
)
libc++abi.dylib: terminating with uncaught exception of type NSException
你能帮我理解这是怎么回事吗?我已经查看过类似的线程,但大多数解决方案都是针对该问题的。
问题是您从后台线程设置 bookList
(因为 URLSession.dataTask
在后台线程上调用它的完成)并且在 bookList
的 didSet
中,你更新 UI。您应该将 UI 更新分派到主线程。
var bookList:myList? = nil {
didSet {
DispatchQueue.main.async {
allBooksTable.reloadData()
}
}
}
您可以像下面这样在主线程上设置 bookList
...
DispatchQueue.main.async {
self.bookList = decodedData
}
如果 UI 元素在后台线程中得到更新,这就是应用程序崩溃的原因,所以无论何时你想更新 UI 你都需要在主线程中更新那个 UI 元素,并且您的会话数据任务在后台线程中是 运行 并且您设置了值 bookList
但是当设置 bookList
时有一个 属性 观察者在后台线程中重新加载表视图所以有两个解决方案。
- 在您的 api 调用函数中,您需要像这样在主线程中设置 属性:-
DispatchQueue.main.async {
self.bookList = decodedData
}
- 在你的 属性 观察者中你需要这样做
var bookList:myList? = nil {
didSet {
DispatchQueue.main.async {
allBooksTable.reloadData()
}
}
}
享受:-