Telah sering menemui kesalahan ini di OS X saya menggunakan swift:
"Aplikasi ini memodifikasi mesin autolayout dari utas latar belakang, yang dapat menyebabkan kerusakan mesin dan crash aneh. Ini akan menyebabkan pengecualian dalam rilis mendatang."
Saya memiliki NSWindow saya dan saya bertukar pandangan ke contentView
jendela. Saya mendapatkan kesalahan ketika saya mencoba dan melakukan NSApp.beginSheet
di jendela, atau ketika saya menambahkan subview
ke jendela. Sudah mencoba menonaktifkan hal-hal autoresize, dan saya tidak punya apa-apa menggunakan tata letak otomatis. Adakah pikiran?
Terkadang baik-baik saja dan tidak ada yang terjadi, di lain waktu itu benar-benar menghancurkan saya UI
dan tidak ada beban
swift
macos
autolayout
background-thread
Menandai
sumber
sumber
Jawaban:
Itu harus ditempatkan di dalam utas berbeda yang memungkinkan UI untuk memperbarui segera setelah fungsi utas selesai:
Modern Swift:
Versi Swift yang lebih lama, pra Swift 3.
Tujuan-C:
sumber
Anda mendapatkan pesan kesalahan yang sama saat melakukan debug dengan pernyataan cetak tanpa menggunakan 'dispatch_async' Jadi, ketika Anda mendapatkan pesan kesalahan itu, saatnya untuk menggunakan
Cepat 4
Cepat 3
Versi Swift sebelumnya
sumber
dispatch_async(dispatch_get_main_queue(), ^{ /* UI related code */ });
Edit: Saya memperbarui jawabannya, format sintaks berfungsi lebih baik di sana.Kesalahan "aplikasi ini memodifikasi mesin autolayout dari utas latar" dicatat dalam konsol lama setelah masalah yang sebenarnya terjadi, jadi debugging ini bisa sulit tanpa menggunakan breakpoint.
Saya menggunakan jawaban @ markussvensson untuk mendeteksi masalah saya dan menemukannya menggunakan Symbolic Breakpoint ini (Debug> Breakpoints> Create Symbolic Breakpoint):
[UIView layoutIfNeeded]
atau[UIView updateConstraintsIfNeeded]
!(BOOL)[NSThread isMainThread]
Bangun dan jalankan aplikasi pada emulator dan ulangi langkah-langkah yang menyebabkan pesan kesalahan dilemparkan (aplikasi akan lebih lambat dari biasanya!). Xcode kemudian akan menghentikan aplikasi dan menandai baris kode (mis. Panggilan func) yang mengakses UI dari utas latar belakang.
sumber
movq 0x10880ba(%rip), %rsi ; "_wantsReapplicationOfAutoLayoutWithLayoutDirtyOnEntry:"
Saat Anda mencoba memperbarui nilai bidang teks atau menambahkan subview di dalam utas latar belakang, Anda bisa mendapatkan masalah ini. Untuk alasan itu, Anda harus meletakkan kode semacam ini di utas utama.
Anda perlu membungkus metode yang memanggil pembaruan UI dengan dispatch_asynch untuk mendapatkan antrian utama. Sebagai contoh:
Diedit - SWIFT 3:
Sekarang, kita bisa melakukannya dengan mengikuti kode berikut:
sumber
Bagi saya, pesan kesalahan ini berasal dari spanduk dari Admob SDK.
Saya dapat melacak asal ke "WebThread" dengan menetapkan breakpoint bersyarat.
Kemudian saya bisa menyingkirkan masalah ini dengan merangkum pembuatan Banner dengan:
Saya tidak tahu mengapa ini membantu karena saya tidak dapat melihat bagaimana kode ini dipanggil dari non-main-thread.
Semoga bisa membantu siapa saja.
sumber
Saya punya masalah ini sejak memperbarui ke iOS 9 SDK ketika saya memanggil blok yang melakukan pembaruan UI dalam NSURLConnection async penangan penyelesaian permintaan. Menempatkan panggilan blok di dispatch_async menggunakan dispatch_main_queue memecahkan masalah.
Ini bekerja dengan baik di iOS 8.
sumber
Punya masalah yang sama karena saya menggunakan
performSelectorInBackground
.sumber
Anda tidak harus mengubah UI dari utas utama! UIKit bukan utas yang aman, sehingga masalah di atas dan juga beberapa masalah aneh lainnya akan muncul jika Anda melakukannya. Aplikasi ini bahkan dapat macet.
Jadi, untuk melakukan operasi UIKit, Anda perlu mendefinisikan blok dan membiarkannya dieksekusi pada antrian utama: seperti,
sumber
Jelas Anda sedang melakukan beberapa pembaruan UI di back ground thread. Tidak dapat memprediksi dengan tepat di mana, tanpa melihat kode Anda.
Ini adalah beberapa situasi yang mungkin terjadi: -
Anda mungkin melakukan sesuatu di utas latar belakang dan tidak menggunakan. Berfungsi sama dengan kode ini lebih mudah dikenali.
memanggil func melakukan panggilan permintaan web pada utas latar belakang dan penangannya selesai memanggil func lainnya melakukan pembaruan ui. untuk menyelesaikan ini coba periksa kode di mana Anda telah memperbarui UI setelah panggilan permintaan web.
sumber
Masalah utama dengan "Aplikasi ini memodifikasi mesin autolayout dari utas latar belakang" adalah bahwa tampaknya akan dicatat lama setelah masalah yang sebenarnya terjadi, ini dapat membuatnya sangat sulit untuk memecahkan masalah.
Saya berhasil memecahkan masalah ini dengan membuat tiga breakpoint simbolis.
Debug> Breakpoints> Buat Sympointic Breakpoint ...
Breakpoint 1:
Simbol:
-[UIView setNeedsLayout]
Kondisi:
!(BOOL)[NSThread isMainThread]
Breakpoint 2:
Simbol:
-[UIView layoutIfNeeded]
Kondisi:
!(BOOL)[NSThread isMainThread]
Breakpoint 3:
Simbol:
-[UIView updateConstraintsIfNeeded]
Kondisi:
!(BOOL)[NSThread isMainThread]
Dengan breakpoints ini, Anda dapat dengan mudah mendapatkan jeda pada baris aktual di mana Anda salah memanggil metode UI pada utas non-utama.
sumber
Saya mengalami masalah ini saat memuat ulang data di UITableView. Cukup kirim ulang isi sebagai berikut perbaiki masalah untuk saya.
sumber
Saya memiliki masalah yang sama. Ternyata saya menggunakan
UIAlerts
yang membutuhkan antrian utama. Tapi, mereka sudah usang .Ketika saya mengubah
UIAlerts
keUIAlertController
, saya tidak lagi memiliki masalah dan tidak perlu menggunakandispatch_async
kode apa pun . Pelajaran - memperhatikan peringatan. Mereka membantu bahkan ketika Anda tidak mengharapkannya.sumber
Anda sudah memiliki jawaban kode yang benar dari @ Mark tetapi, hanya untuk membagikan temuan saya: Masalahnya adalah Anda meminta perubahan dalam tampilan dan mengasumsikan bahwa itu akan terjadi secara instan. Pada kenyataannya, pemuatan tampilan tergantung pada sumber daya yang tersedia. Jika semuanya memuat cukup cepat dan tidak ada penundaan maka Anda tidak melihat apa pun. Dalam skenario, di mana ada keterlambatan karena utas proses sedang sibuk dll, aplikasi mengalami situasi di mana ia seharusnya menampilkan sesuatu meskipun belum siap. Oleh karena itu, disarankan untuk mengirimkan permintaan ini dalam antrian asinkron sehingga, mereka dieksekusi berdasarkan beban.
sumber
Saya mengalami masalah ini ketika saya menggunakan TouchID jika itu membantu orang lain, bungkus logika kesuksesan Anda yang kemungkinan melakukan sesuatu dengan UI di antrian utama.
sumber
Ini bisa berupa sesuatu yang sederhana seperti menyetel bidang teks / nilai label atau menambahkan subview di dalam utas latar belakang, yang dapat menyebabkan tata letak bidang berubah. Pastikan apa pun yang Anda lakukan dengan antarmuka hanya terjadi di utas utama.
Periksa tautan ini: https://forums.developer.apple.com/thread/7399
sumber
Saya memiliki masalah yang sama ketika mencoba memperbarui pesan kesalahan di UILabel di ViewController yang sama (butuh beberapa saat untuk memperbarui data ketika mencoba melakukan itu dengan pengkodean normal). Saya menggunakan
DispatchQueue
Swift 3 Xcode 8 dan berfungsi.sumber
Jika Anda ingin mencari kesalahan ini, gunakan pemeriksa utas jeda pada masalah centang. Memperbaiki itu mudah sebagian besar kali, mengirim garis bermasalah di antrian utama.
sumber
Bagi saya masalahnya adalah sebagai berikut. Pastikan
performSegueWithIdentifier:
dilakukan di utas utama:sumber
Swift 4,
Misalkan, jika Anda memanggil beberapa metode menggunakan operasi antrian
Dan misalkan fungsi searchFavourites seperti,
jika Anda memanggil, semua kode di dalam metode "searchFavourites" pada utas utama, itu masih akan memberikan kesalahan jika Anda memperbarui beberapa UI di dalamnya.
Jadi gunakan solusi,
Untuk skenario seperti ini.
sumber
Di sini, periksa baris ini dari log
Anda dapat memeriksa fungsi mana yang memanggil dari utas latar belakang atau tempat Anda memanggil metode api, Anda harus memanggil fungsi Anda dari utas utama seperti ini.
Log di Sini
sumber
Saya juga mengalami masalah ini, melihat satu ton pesan ini dan jejak stack sedang dicetak dalam output, ketika saya mengubah ukuran jendela ke ukuran yang lebih kecil dari nilai awalnya. Menghabiskan waktu yang lama untuk mencari tahu masalahnya, saya pikir saya akan membagikan solusi yang agak sederhana. Saya pernah diaktifkan
Can Draw Concurrently
padaNSTextView
melalui IB. Itu memberitahu AppKit bahwa ia dapat memanggil metode tampilandraw(_:)
dari utas lain. Setelah menonaktifkannya, saya tidak lagi mendapat pesan kesalahan. Saya tidak mengalami masalah sebelum memperbarui ke macOS 10.14 Beta, tetapi pada saat yang sama, saya juga mulai memodifikasi kode untuk melakukan pekerjaan dengan tampilan teks.sumber