UIResponder doesNotRecognizeSelector - PullRequest
       27

UIResponder doesNotRecognizeSelector

2 голосов
/ 16 октября 2019

Я получаю много сбоев со следующей обратной трассировкой, и я не могу найти причину этого.

Согласно Apple - [NSObject (NSObject) doesNotRecognizeSelector:] происходиткогда новый объект выделяется в памяти, ранее занятой освобожденным объектом.

Примечание: Передача ранее освобожденного объекта может вызвать исключение NSInvalidArgumentException вместо сбоя программы с памятьюнарушение доступа. Это происходит, когда новый объект размещается в памяти, ранее занятой освобожденным объектом. Если ваше приложение аварийно завершает работу из-за неперехваченного NSInvalidArgumentException (ищите - [NSObject (NSObject) doesNotRecognizeSelector:] в трассировке исключений), рассмотрите возможность профилирования вашего приложения с помощью инструмента Zombies, чтобы исключить возможность неправильного управления памятью.

https://developer.apple.com/library/archive/technotes/tn2151/_index.html

Но что случилось с остальной частью трассировки, особенно - [UIUndoGestureInteraction didMoveToView:] вещь?

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Triggered by Thread:  0

Last Exception Backtrace:
0   CoreFoundation                  0x1ae45498c __exceptionPreprocess + 220 (NSException.m:199)
1   libobjc.A.dylib                 0x1ae17d0a4 objc_exception_throw + 56 (objc-exception.mm:565)
2   CoreFoundation                  0x1ae35843c -[NSObject(NSObject) doesNotRecognizeSelector:] + 140 (NSObject.m:144)
3   UIKitCore                       0x1b24902a8 -[UIResponder doesNotRecognizeSelector:] + 296 (UIResponder.m:659)
4   CoreFoundation                  0x1ae458e08 ___forwarding___ + 1324 (NSForwarding.m:3325)
5   CoreFoundation                  0x1ae45abec _CF_forwarding_prep_0 + 92
6   UIKitCore                       0x1b2353040 -[UIUndoGestureInteraction didMoveToView:] + 108 (UIUndoGestureInteraction.m:725)
7   UIKitCore                       0x1b28eb3c4 _setInteractionView + 84 (UIView.m:16421)
8   UIKitCore                       0x1b28eb2a0 -[UIView(Dragging) addInteraction:] + 268 (UIView.m:16450)
9   UIKitCore                       0x1b26cd2b8 -[UIEditingOverlayViewController _addInteractions] + 260 (UIEditingOverlayViewController.m:79)
10  UIKitCore                       0x1b1e5b2ec -[UIViewController _setViewAppearState:isAnimating:] + 832 (UIViewController.m:4695)
11  UIKitCore                       0x1b1e5b6fc __52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke + 268 (UIViewController.m:4758)
12  CoreFoundation                  0x1ae42773c __NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__ + 16 (NSArrayHelpers.m:9)
13  CoreFoundation                  0x1ae32b86c -[__NSArrayI enumerateObjectsWithOptions:usingBlock:] + 152 (NSArrayI.m:108)
14  UIKitCore                       0x1b1e5b49c -[UIViewController _setViewAppearState:isAnimating:] + 1264 (UIViewController.m:4736)
15  UIKitCore                       0x1b1e5d530 __64-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]_block_invoke + 44 (UIViewController.m:5272)
16  UIKitCore                       0x1b1e5c32c -[UIViewController _executeAfterAppearanceBlock] + 88 (UIViewController.m:5050)
17  UIKitCore                       0x1b246bca4 _runAfterCACommitDeferredBlocks + 584 (UIApplication.m:3027)
18  UIKitCore                       0x1b245b7c0 _cleanUpAfterCAFlushAndRunDeferredBlocks + 232 (UIApplication.m:2986)
19  UIKitCore                       0x1b248b594 _afterCACommitHandler + 76 (UIApplication.m:3048)
20  CoreFoundation                  0x1ae3d1c48 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32 (CFRunLoop.c:1758)
21  CoreFoundation                  0x1ae3ccb34 __CFRunLoopDoObservers + 416 (CFRunLoop.c:1868)
22  CoreFoundation                  0x1ae3cd100 __CFRunLoopRun + 1308 (CFRunLoop.c:2910)
23  CoreFoundation                  0x1ae3cc8bc CFRunLoopRunSpecific + 464 (CFRunLoop.c:3192)
24  GraphicsServices                0x1b8238328 GSEventRunModal + 104 (GSEvent.c:2246)
25  UIKitCore                       0x1b24626d4 UIApplicationMain + 1936 (UIApplication.m:4753)
26  JustConnect                     0x10425ca60 main + 68 (APIInfoUser.swift:7)
27  libdyld.dylib                   0x1ae257460 start + 4

1 Ответ

1 голос
/ 28 октября 2019

Вот ответ от Apple Developer & Technical Support:

Ключевым моментом, на который следует обратить внимание, является то, что кадры с 0 по 5 этой обратной трассировки являются просто образцом, связанным с нераспознанным селектором. То есть кадр 6 вызвал метод для объекта, объект не распознал этот селектор, поэтому он вошел в инфраструктуру пересылки времени выполнения Objective C (кадры с 5 по 4). Это появилось в UIResponder (кадр 3), потому что UIResponder поддерживает какую-то общую пересылку сообщений. Переадресация сообщения завершилась неудачно, поэтому UIResponder вызвал super (кадр 2), который затем вызвал исключение.

Таким образом, реальный вопрос заключается в том, что происходит в кадре 6. Чтобы узнать больше об этом, вы можете разобрать код(-:

(lldb) disas -n '-[UIUndoGestureInteraction didMoveToView:]'  
UIKitCore`-[UIUndoGestureInteraction didMoveToView:]:  
    0x1bbe92fd4 <+0>:   stp    x22, x21, [sp, #-0x30]!  
    0x1bbe92fd8 <+4>:   stp    x20, x19, [sp, #0x10]  
    0x1bbe92fdc <+8>:   stp    x29, x30, [sp, #0x20]  
    0x1bbe92fe0 <+12>:  add    x29, sp, #0x20    ; =0x20   
    0x1bbe92fe4 <+16>:  mov    x21, x2  
    0x1bbe92fe8 <+20>:  mov    x19, x0  
    0x1bbe92fec <+24>:  add    x20, x0, #0x10    ; =0x10   
    0x1bbe92ff0 <+28>:  mov    x0, x20  
    0x1bbe92ff4 <+32>:  mov    x1, x2  
    0x1bbe92ff8 <+36>:  bl     0x1b7cd71d8       ; objc_storeWeak  
    0x1bbe92ffc <+40>:  cbz    x21, 0x1bbe930a8  ; <+212>  
    0x1bbe93000 <+44>:  adrp   x8, 208464  
    0x1bbe93004 <+48>:  add    x1, x8, #0x7b1    ; =0x7b1   
    0x1bbe93008 <+52>:  mov    x0, x19  
    0x1bbe9300c <+56>:  bl     0x1b7cb9180       ; objc_msgSend  
    0x1bbe93010 <+60>:  mov    x0, x20  
    0x1bbe93014 <+64>:  bl     0x1b7cd7a80       ; objc_loadWeakRetained  
    0x1bbe93018 <+68>:  mov    x20, x0  
    0x1bbe9301c <+72>:  adrp   x8, 208304  
    0x1bbe93020 <+76>:  add    x1, x8, #0xc04    ; =0xc04   
    0x1bbe93024 <+80>:  bl     0x1b7cb9180       ; objc_msgSend  
    0x1bbe93028 <+84>:  mov    x29, x29  
    0x1bbe9302c <+88>:  bl     0x1b7cd8864       ; objc_retainAutoreleasedReturnValue  
    0x1bbe93030 <+92>:  mov    x21, x0  
    0x1bbe93034 <+96>:  adrp   x8, 208502  
    0x1bbe93038 <+100>: add    x1, x8, #0xbb7    ; =0xbb7   
    0x1bbe9303c <+104>: bl     0x1b7cb9180       ; objc_msgSend  
    0x1bbe93040 <+108>: stp    d0, d1, [x19, #0x100]  

Здесь вы можете узнать несколько вещей. Во-первых, кадр 6 в обратном следе имеет смещение +108, поэтому фактический сбой при вызове составляет +104. Objc_msgSend,имеет два стандартных параметра, целевой объект и селектор. На 64-битном Arm они отображаются на x0 и x1 соответственно.

Давайте сначала посмотрим на селектор. Это построено двумя инструкциями на +96 и+100.Эти две инструкции образуют относительный адрес ПК. Инструкция adrp ('добавить относительно страницы') берет текущий ПК (0x1bbe93034), очищает младшие 12 бит (0x1bbe93000, помните, что исторический размер страницы равен 4096 [1]), а затем берет литерал, сдвигает его влево на 12 бит (208502 << 12), а затем добавляет его. Инструкция добавления намного проще. результат предыдущего вычисления и добавляет 0xbb7 (обратите внимание на переключение с десятичного на шестнадцатеричное!). </p>

Если вы выполните это вычисление в отладчике, вы увидите следующее:

(lldb) p (char*)( 0x1bbe93000+(208502<<12)+0xbb7)  
(char *) $1 = 0x00000001eed09bb7 "actualSceneBounds" 

Так чтоСелектор является актуальнымКруто.

Теперь давайте посмотрим на объект. Во время вызова (+104) ожидается, что он будет в х0. В +92 мы видим, что это копирует x0 к x21, но это только отвлечение. На самом деле x0 - это результат функции из objc_retainAutoreleasedReturnValue со значением +88. Эта функция принимает и возвращает объект, поэтому x0 - это значение, возвращаемое сообщением, отправленным в +80. Делая тот же трюк с относительной страницей, который мы делали ранее, мы видим, что селектором для этого вызова является -window. Но какой объект вызывается?

Работать с этим… ну… довольно сложно из-за танца objc_storeWeak / objc_loadWeakRetained. Я считаю, что это сводится к значению, переданному в этот метод через x2, то есть третий параметр. Основываясь на имени метода, это явно представление (помните, что для методов Objective C первые два параметра, x0 и x1, содержат цель и селектор, поэтому x2 содержит первый фактический параметр).

Итак, в итоге:

  • Кажется, что у этого метода есть параметр представления.

  • Запрошено window.window.screenBounds.

  • Последний доступ к свойству не удался, потому что объект, который должен быть окном, не реализует метод -screenBounds.

Я не знаюя не знаю достаточно о UIKit, чтобы объяснить это. У меня есть несколько предложений здесь:

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

  2. Если это не удастся, отскок к App Frameworkworks> Cocoa Touch, чтобы увидетьесли у кого-то есть какие-либо предложения.

Делитесь и наслаждайтесь

-

[1] На 64-битном ARM фактический размер страницы обычно составляет 64КиБ, но инструкция adrp использует исторический размер страницы 4096, поскольку она соответствует максимальному литеральному размеру в инструкции добавления.

https://forums.developer.apple.com/message/389467

...