Предупреждение только один раз: UITableView было указано размещать свои видимые ячейки и другое содержимое, не находясь в иерархии представлений?

#ios #swift #uitableview

#iOS #swift #uitableview

Вопрос:

Я добавляю TableView в ViewController. Когда я открою этот экран, я получу приведенное ниже предупреждение один раз.

[TableView] Предупреждение только один раз: UITableView было указано расположить его видимые ячейки и другое содержимое, не находясь в иерархии представлений (табличное представление или одно из его супервизий не было добавлено в окно). Это может привести к ошибкам, заставляя представления внутри табличного представления загружать и выполнять компоновку без точной информации (например, границы представления таблицы, коллекция признаков, поля макета, вставки безопасных областей и т. Д.), А также приведет к ненужным издержкам производительности из-за дополнительных проходов компоновки. Создайте символическую точку останова в UITableViewAlertForLayoutOutsideViewHierarchy, чтобы перехватить это в отладчике и посмотреть, что вызвало это, чтобы вы могли вообще избежать этого действия, если это возможно, или отложить его до добавления табличного представления в окно. Вид таблицы: <UITableView: 0x7fe2ba8d5a00; frame = (-47 -80; 394 553); clipsToBounds = YES; авторазмер = RM BM; Распознаватели жестов = <NSArray: 0x600003447480>; layer = <CALayer: 0x600003aa2be0>; contentOffset: {0, 0 }; Размер содержимого: {394, 176};adjustedContentInset: {0, 0, 0, 0}; Источник данных:MondayToSundayViewController: 0x7fe2b9da05c0>>

При добавлении символической точки останова для UITableViewAlertForLayoutOutsideViewHierarchy в консоли отображается ниже.

 > UIKitCore`UITableViewAlertForLayoutOutsideViewHierarchy:
->  0x7fff48260c7e < 0>:   pushq  %rbp
    0x7fff48260c7f < 1>:   movq   %rsp, %rbp
    0x7fff48260c82 < 4>:   pushq  %r14
    0x7fff48260c84 < 6>:   pushq  %rbx
    0x7fff48260c85 < 7>:   subq   $0x30, %rsp
    0x7fff48260c89 < 11>:  callq  *0x3e51a6a1(%rip)         ; (void *)0x00007fff51411350: objc_retain
    0x7fff48260c8f < 17>:  movq   %rax, %rbx
    0x7fff48260c92 < 20>:  leaq   0x416a8dbf(%rip), %rdi    ; _UIInternalPreference_UITableViewEnableAlertForLayoutOutsideViewHierarchy
    0x7fff48260c99 < 27>:  leaq   0x3e5a2140(%rip), %rsi    ; @"UITableViewEnableAlertForLayoutOutsideViewHierarchy"
    0x7fff48260ca0 < 34>:  callq  0x7fff482a7529            ; _UIInternalPreferenceUsesDefault
    0x7fff48260ca5 < 39>:  testb  %al, %al
    0x7fff48260ca7 < 41>:  jne    0x7fff48260cb3            ; < 53>
    0x7fff48260ca9 < 43>:  movb   0x416a8dad(%rip), %al     ; _UIInternalPreference_UITableViewEnableAlertForLayoutOutsideViewHierarchy   4
    0x7fff48260caf < 49>:  andb   $0x1, %al
    0x7fff48260cb1 < 51>:  je     0x7fff48260d2d            ; < 175>
    0x7fff48260cb3 < 53>:  leaq   0x416c3ffe(%rip), %rax    ; _UIApplicationLinkedOnVersion
    0x7fff48260cba < 60>:  movl   (%rax), %eax
    0x7fff48260cbc < 62>:  testl  %eax, %eax
    0x7fff48260cbe < 64>:  je     0x7fff48260d3e            ; < 192>
    0x7fff48260cc0 < 66>:  cmpl   $0xd0000, %eax            ; imm = 0xD0000 
    0x7fff48260cc5 < 71>:  jb     0x7fff48260d2d            ; < 175>
    0x7fff48260cc7 < 73>:  movq   %rbx, %rdi
    0x7fff48260cca < 76>:  callq  0x7fff486252fa            ; symbol stub for: objc_opt_class
    0x7fff48260ccf < 81>:  movq   0x41607402(%rip), %rsi    ; "_isInternalTableView"
    0x7fff48260cd6 < 88>:  movq   %rax, %rdi
    0x7fff48260cd9 < 91>:  callq  *0x3e51a641(%rip)         ; (void *)0x00007fff513f7780: objc_msgSend
    0x7fff48260cdf < 97>:  testb  %al, %al
    0x7fff48260ce1 < 99>:  jne    0x7fff48260d2d            ; < 175>
    0x7fff48260ce3 < 101>: movq   0x3e519b46(%rip), %rax    ; (void *)0x00007fff89ea06a0: _NSConcreteStackBlock
    0x7fff48260cea < 108>: movq   %rax, -0x38(%rbp)
    0x7fff48260cee < 112>: movl   $0xc2000000, %eax         ; imm = 0xC2000000 
    0x7fff48260cf3 < 117>: movq   %rax, -0x30(%rbp)
    0x7fff48260cf7 < 121>: leaq   0x46728(%rip), %rax       ; __UITableViewAlertForLayoutOutsideViewHierarchy_block_invoke
    0x7fff48260cfe < 128>: movq   %rax, -0x28(%rbp)
    0x7fff48260d02 < 132>: leaq   0x3e51d237(%rip), %rax    ; __block_descriptor_40_e8_32s_e5_v8?0l
    0x7fff48260d09 < 139>: movq   %rax, -0x20(%rbp)
    0x7fff48260d0d < 143>: movq   %rbx, %rdi
    0x7fff48260d10 < 146>: callq  *0x3e51a61a(%rip)         ; (void *)0x00007fff51411350: objc_retain
    0x7fff48260d16 < 152>: movq   %rax, -0x18(%rbp)
    0x7fff48260d1a < 156>: cmpq   $-0x1, 0x416ca5c6(%rip)   ; _UIInternalPreference_TableViewReorderingUsesDragAndDrop_block_invoke_10.__s_category   7
    0x7fff48260d22 < 164>: jne    0x7fff48260d52            ; < 212>
    0x7fff48260d24 < 166>: movq   %rax, %rdi
    0x7fff48260d27 < 169>: callq  *0x3e51a5fb(%rip)         ; (void *)0x00007fff51411000: objc_release
    0x7fff48260d2d < 175>: movq   %rbx, %rdi
    0x7fff48260d30 < 178>: addq   $0x30, %rsp
    0x7fff48260d34 < 182>: popq   %rbx
    0x7fff48260d35 < 183>: popq   %r14
    0x7fff48260d37 < 185>: popq   %rbp
    0x7fff48260d38 < 186>: jmpq   *0x3e51a5ea(%rip)         ; (void *)0x00007fff51411000: objc_release
    0x7fff48260d3e < 192>: movl   $0xd0000, %edi            ; imm = 0xD0000 
    0x7fff48260d43 < 197>: callq  0x7fff48093724            ; _UIApplicationLinkedOnOrAfter
    0x7fff48260d48 < 202>: testb  %al, %al
    0x7fff48260d4a < 204>: jne    0x7fff48260cc7            ; < 73>
    0x7fff48260d50 < 210>: jmp    0x7fff48260d2d            ; < 175>
    0x7fff48260d52 < 212>: leaq   0x416ca58f(%rip), %rdi    ; UITableViewAlertForLayoutOutsideViewHierarchy.once
    0x7fff48260d59 < 219>: leaq   -0x38(%rbp), %r14
    0x7fff48260d5d < 223>: movq   %r14, %rsi
    0x7fff48260d60 < 226>: callq  0x7fff48624f8e            ; symbol stub for: dispatch_once
    0x7fff48260d65 < 231>: movq   0x20(%r14), %rax
    0x7fff48260d69 < 235>: jmp    0x7fff48260d24            ; < 166>
  

Не могли бы вы помочь мне удалить предупреждение?

Комментарии:

1. Проблема в том, что это язык ассемблера intel. Вам нужно отладить его с помощью языка ассемблера ARM на более новом оборудовании или установить микроскоп на материнскую плату. Нет, просто шучу, посмотрите обратную трассировку и посмотрите Мой ответ на некоторые советы по отладке.

Ответ №1:

Вы добавили ограничение перед добавлением своего представления в иерархию представлений. Вот почему вы получаете эту ошибку. Убедитесь, что пошаговое добавление, например :

 view.addSubview(tableView) // 1
// 2 and start adding constraints..
tableView.translatesAutoresizingMaskIntoConstraints = false
...
  

Комментарии:

1. Не приводит ли добавление ограничения перед добавлением представления в иерархию представлений к ошибке времени выполнения?

2. @YessenYermukhanbet да, и ошибка с другой формулировкой на консоли XCode. Вероятно, это не та проблема. Если люди поддерживают этот ответ, они могут объединять это нарушение иерархии представлений с этим.

Ответ №2:

В моем случае предоставленные ответы не помогли. Изменение моей реализации моментального снимка DiffableDataSource из этого:

 dataSource.apply(snapShot, animatingDifferences: true)
  

к этому:

 dataSource.apply(snapShot, animatingDifferences: false)
  

Исправлена ошибка.

Комментарии:

1. Как ни странно, в случае перехода на animatingDifferences: false происходит мертвая блокировка…

2. Никогда не было этой проблемы в моем приложении, и в любом случае она не должна заходить в тупик из-за изменения анимации — вероятно, что-то еще сломано?

3. Да, согласен. Очень странная причина. Он показывает сообщение о доступе к функции applySnapshot из одного потока. Однако, насколько я знаю, я вызываю apply snapshot только из основного потока. Каковы могут быть возможные причины?

Ответ №3:

Если вы установите рекомендуемую символическую точку останова:

 UITableViewAlertForLayoutOutsideViewHierarchy
  

он остановится на точке останова в каком-то неясном коде на языке ассемблера, что бесполезно для большинства смертных, помимо того, что он тупой, он находится в коде постфактум.

Но вы можете просмотреть обратную трассировку стека с панели XCode (альтернативно введите bt в приглашении lldb)

Обратная трассировка покажет вам, какой именно поток перезагрузки таблицы вызвал проблему, которая обычно является огромной подсказкой. Обратная трассировка обычно является достаточной подсказкой, чтобы прямо или косвенно позволить вам определить проблему и решение.


Примечание: если вы не видите трассировку в левой панели XCode, убедитесь, что в текстовом поле внизу этой панели нет текста. Это текстовый фильтр, и если ничего не соответствует тексту, который вы ввели в фильтр, на панели ничего не отображается!. Со мной достаточно, чтобы указать на это здесь… когда, например, я использую фильтр для поиска представления в иерархии представлений, введя адрес представления (который я копирую / вставляю из предупреждения об ограничении автозапуска в окне журнала XCode). Это позволяет мне увидеть, где находится оскорбительный вид в очень полезном инструменте визуализации 3D UIView в XCode, который вы можете посетить, нажав кнопку «тройные квадраты» в XCode под главным окном.


Пример того, как я только что отладил проблему:

Я получил предупреждение, потому что я вызвал tableView.reload() функцию, из которой я вызывал viewWillAppear() . И это произошло:

  1. После добавления ограничений
  2. TableView был добавлен в качестве подвида ViewController view

Примечание: Есть еще один ответ на этот вопрос, в котором говорится, что это происходит, когда вы забываете добавить представление в качестве подвида. Но это другое сообщение, когда вы совершаете более распространенную ошибку, забывая добавить представление в иерархию перед активацией связанных с ним ограничений NSLayoutConstraints. Но поскольку вы обычно получаете эту ошибку при программном написании кода ограничения, обычно легче понять, что происходит.

Итак, когда отладчик остановился в вышеупомянутой точке останова, я проверил, что окно TableView равно нулю … например, введено p tableView.window в приглашении lldb.

Затем я спросил себя, как это возможно, что TableView отсутствует в иерархии окон, и до меня доходит, что вызывать подобные вещи из viewWillAppear() плохо, потому что в этот момент иерархия представлений вот-вот появится, но еще не появилась.

Итак, я почесал голову, потому что мне определенно нужно, чтобы моя таблица перезагружалась каждый раз, когда загружается viewcontroller, чтобы предварительно выбрать определенную ячейку в таблице, поэтому viewDidLoad() это тоже не то место. 🙁

Я понял viewDidAppear() , что это лучшее место, и оно работает.

введите описание изображения здесь

Комментарии:

1. Это было очень полезно. Мне нравится ваш стиль отладки и устранения проблем, когда они появляются во время разработки. Я многому научился

Ответ №4:

Я только что решил эту проблему, и это действительно сложно. Это заняло у меня полдня.

Решение таково:

1. Поместите свой UITableView в UIView и установите ограничение UITableView таким же размером, как UIView,

2. Затем измените Y и высоту UIView, отслеживая координаты прокрутки.

Это даст вам желаемый эффект. Не меняйте размер UITableView напрямую, просто оберните его одним слоем.

Ответ №5:

  1. Проверьте, пытаетесь ли вы получить доступ к свойствам TableView в

viewDidAppear

затем измените это на

viewWillAppear

Таким образом, теперь TableView определенно присутствует.

  1. Другой вариант — удалить все? (опции) из «TableView?.» в «TableView». Таким образом, он выйдет из строя прямо там, где проблема.