Często napotykałem ten błąd w moim systemie OS X za pomocą swift:
„Ta aplikacja modyfikuje silnik autolayout z wątku w tle, co może prowadzić do uszkodzenia silnika i dziwnych awarii. Spowoduje to wyjątek w przyszłej wersji”.
Mam moje okno NSWindow i zmieniam widoki contentView
w oknie. Występuje błąd, gdy próbuję zrobić NSApp.beginSheet
okno w oknie lub dodać go subview
do okna. Próbowałem wyłączyć rzeczy z automatyczną zmianą rozmiaru i nie mam nic przy użyciu automatycznego układu. jakieś pomysły?
Czasami jest w porządku i nic się nie dzieje, innym razem całkowicie mnie psuje UI
i nic się nie ładuje
Odpowiedzi:
Musi zostać umieszczony w innym wątku, który umożliwia aktualizację interfejsu użytkownika, gdy tylko zakończy się wykonywanie funkcji wątku:
Modern Swift:
Starsze wersje Swift, przed Swift 3.
Cel C:
źródło
Otrzymujesz podobny komunikat o błędzie podczas debugowania za pomocą instrukcji drukowania bez użycia polecenia „dispatch_async”. Gdy pojawi się ten komunikat o błędzie, czas na użycie
Szybki 4
Szybki 3
Wcześniejsze wersje Swift
źródło
dispatch_async(dispatch_get_main_queue(), ^{ /* UI related code */ });
Edytuj: Zaktualizowałem jego odpowiedź, formatowanie składni działa tam lepiej.Błąd „ta aplikacja modyfikuje silnik autolayout z wątku w tle” jest rejestrowany w konsoli długo po wystąpieniu rzeczywistego problemu, więc debugowanie może być trudne bez użycia punktu przerwania.
Użyłem odpowiedzi @ markussvensson, aby wykryć mój problem i znalazłem go za pomocą tego Symbolicznego punktu przerwania (Debugowanie> Punkty przerwania > Utwórz symboliczny punkt przerwania ):
[UIView layoutIfNeeded]
lub[UIView updateConstraintsIfNeeded]
!(BOOL)[NSThread isMainThread]
Zbuduj i uruchom aplikację na emulatorze i powtórz kroki prowadzące do wyświetlenia komunikatu o błędzie (aplikacja będzie wolniejsza niż zwykle!). Xcode zatrzyma aplikację i zaznaczy wiersz kodu (np. Wywołanie func), który uzyskuje dostęp do interfejsu użytkownika z wątku w tle.
źródło
movq 0x10880ba(%rip), %rsi ; "_wantsReapplicationOfAutoLayoutWithLayoutDirtyOnEntry:"
Podczas próby aktualizacji wartości pola tekstowego lub dodania widoku podrzędnego w wątku w tle można uzyskać ten problem. Z tego powodu powinieneś umieścić ten rodzaj kodu w głównym wątku.
Aby uzyskać kolejkę główną, musisz owinąć metody wywołujące aktualizacje interfejsu użytkownika metodą dispatch_asynch. Na przykład:
ZMIENIONO - SWIFT 3:
Teraz możemy to zrobić zgodnie z następnym kodem:
źródło
Dla mnie ten komunikat o błędzie pochodzi z baneru z AdMob SDK.
Byłem w stanie śledzić początek do „WebThread” poprzez ustawienie warunkowego punktu przerwania.
Następnie udało mi się pozbyć tego problemu, kapsułkując tworzenie banera za pomocą:
Nie wiem, dlaczego to pomogło, ponieważ nie widzę, jak ten kod został wywołany z wątku innego niż główny.
Mam nadzieję, że może pomóc każdemu.
źródło
Miałem ten problem od czasu aktualizacji do zestawu SDK dla systemu iOS 9, gdy dzwoniłem do bloku, który aktualizował interfejs użytkownika w module obsługi zakończenia żądania asynchronicznego NSURLConnection. Umieszczenie wywołania bloku w pliku dispatch_async przy użyciu narzędzia dispatch_main_queue rozwiązało problem.
Działa dobrze w iOS 8.
źródło
Miałem ten sam problem, ponieważ używałem
performSelectorInBackground
.źródło
Nie wolno zmieniać interfejsu użytkownika poza głównym wątkiem! UIKit nie jest bezpieczny dla wątków, więc jeśli to zrobisz, pojawią się powyższe problemy i inne dziwne problemy. Aplikacja może nawet ulec awarii.
Tak więc, aby wykonać operacje UIKit, musisz zdefiniować blok i pozwolić, aby był on wykonywany w głównej kolejce: np.
źródło
Oczywiście robisz aktualizację interfejsu użytkownika w wątku z tyłu. Nie mogę dokładnie przewidzieć, gdzie jest Twój kod.
Oto niektóre sytuacje, które mogą się zdarzyć:
możesz robić coś w tle i nie używać. Będąc w tej samej funkcji, ten kod jest łatwiejszy do wykrycia.
wywołanie func wykonującego żądanie WWW wywołanie wątku w tle i jego moduł obsługi zakończenia wywołujący func wykonującego aktualizację interfejsu użytkownika. aby rozwiązać ten problem, sprawdź kod, w którym zaktualizowałeś interfejs użytkownika po wywołaniu żądania internetowego.
źródło
Główny problem z „Ta aplikacja modyfikuje silnik autolayout z wątku w tle” polega na tym, że wydaje się, że jest rejestrowany długo po wystąpieniu rzeczywistego problemu, co może bardzo utrudnić jego rozwiązanie.
Udało mi się rozwiązać problem, tworząc trzy symboliczne punkty przerwania.
Debugowanie> Punkty przerwania> Utwórz symboliczny punkt przerwania ...
Punkt przerwania 1:
Symbol:
-[UIView setNeedsLayout]
Stan: schorzenie:
!(BOOL)[NSThread isMainThread]
Punkt przerwania 2:
Symbol:
-[UIView layoutIfNeeded]
Stan: schorzenie:
!(BOOL)[NSThread isMainThread]
Punkt przerwania 3:
Symbol:
-[UIView updateConstraintsIfNeeded]
Stan: schorzenie:
!(BOOL)[NSThread isMainThread]
Dzięki tym punktom przerwania możesz łatwo uzyskać przerwę w wierszu, w którym niepoprawnie wywołujesz metody interfejsu użytkownika w wątku innym niż główny.
źródło
Miałem ten problem podczas ponownego ładowania danych w UITableView. Po prostu wysłanie przeładowania w następujący sposób naprawiło problem.
źródło
Miałem ten sam problem. Okazało się, że korzystałem z
UIAlerts
tej potrzebnej głównej kolejki. Ale są przestarzałe .Kiedy zmienił
UIAlerts
się doUIAlertController
, już nie miał problemu i nie trzeba używać żadnegodispatch_async
kodu. Lekcja - zwróć uwagę na ostrzeżenia. Pomagają nawet wtedy, gdy się tego nie spodziewasz.źródło
Masz już poprawną odpowiedź na kod z @Mark, ale tylko po to, by podzielić się moimi ustaleniami: Problem polega na tym, że prosisz o zmianę poglądu i zakładasz, że nastąpi to natychmiast. W rzeczywistości ładowanie widoku zależy od dostępnych zasobów. Jeśli wszystko ładuje się wystarczająco szybko i nie ma opóźnień, nic nie zauważysz. W scenariuszach, w których występuje opóźnienie z powodu zajętości wątku procesowego itp., Aplikacja działa w sytuacji, w której ma coś wyświetlić, mimo że nie jest jeszcze gotowa. Dlatego wskazane jest wysyłanie tych żądań w kolejkach asynchronicznych, aby były one wykonywane na podstawie obciążenia.
źródło
Miałem ten problem, kiedy korzystałem z TouchID, jeśli to pomaga komukolwiek innemu, zapakuj swoją logikę sukcesu, która prawdopodobnie robi coś z interfejsem użytkownika w głównej kolejce.
źródło
Może to być coś tak prostego, jak ustawienie wartości pola tekstowego / etykiety lub dodanie widoku podrzędnego w wątku tła, co może spowodować zmianę układu pola. Upewnij się, że wszystko, co robisz z interfejsem, dzieje się tylko w głównym wątku.
Sprawdź ten link: https://forums.developer.apple.com/thread/7399
źródło
Miałem ten sam problem, gdy próbowałem zaktualizować komunikat o błędzie w UILabel w tym samym ViewController (aktualizacja danych podczas próby normalnego kodowania zajmuje trochę czasu). Użyłem
DispatchQueue
w Swift 3 Xcode 8 i działa.źródło
Jeśli chcesz wyłapać ten błąd, użyj głównego pauzy sprawdzania wątków przy problemach. Naprawienie go jest przez większość czasu łatwe, rozwiązywanie problematycznej linii w głównej kolejce.
źródło
Dla mnie problem był następujący. Upewnij się, że
performSegueWithIdentifier:
jest wykonywany w głównym wątku:źródło
Swift 4,
Załóżmy, że jeśli wywołujesz jakąś metodę za pomocą kolejki operacji
Załóżmy, że wyszukiwanie funkcji Ulubione to:
jeśli zadzwonisz, cały kod w metodzie „searchFavourites” w głównym wątku, nadal będzie dawał błąd, jeśli aktualizujesz w nim jakiś interfejs użytkownika.
Więc użyj rozwiązania,
Dla tego rodzaju scenariusza.
źródło
Tutaj sprawdź tę linię z dzienników
możesz sprawdzić, która funkcja wywołująca z wątku w tle lub gdzie wywołujesz metodę interfejsu API, musisz wywołać swoją funkcję z głównego wątku w ten sposób.
Dzienniki tutaj
źródło
Zetknąłem się również z tym problemem, widząc mnóstwo tych komunikatów i śladów stosu drukowanych na wydruku, gdy zmieniłem rozmiar okna na mniejszy niż jego początkowa wartość. Długo zastanawiając się nad tym problemem, pomyślałem, że podzielę się raczej prostym rozwiązaniem. Kiedyś włączyłem
Can Draw Concurrently
naNSTextView
IB. To mówi AppKit, że może wywołaćdraw(_:)
metodę widoku z innego wątku. Po wyłączeniu nie otrzymuję już komunikatów o błędach. Nie miałem żadnych problemów przed aktualizacją do macOS 10.14 Beta, ale jednocześnie zacząłem modyfikować kod, aby działał z widokiem tekstowym.źródło