Любая причина, почему NotificationCenter вызывает EXC_BAD_ACCESS на симуляторе, но не на устройстве? - PullRequest
1 голос
/ 15 апреля 2020

У меня есть этот код здесь:

    @objc func buttonTapped(sender: DateFieldButton) {

        // Thread 1: EXC_BAD_ACCESS (code=1, address=0xfffe) here
        NotificationCenter.default.post(name: .dateFieldTapped, object: nil, userInfo: [0 : sender.pattern])

    }
extension Notification.Name {

    static let dateFieldTapped = Notification.Name("dateFieldTapped")

}

Если бы button.addTarget(self, action: #selector(buttonTapped(sender:)), for: .touchUpInside)

DeviceFieldButton это просто подкласс UIButton, с дополнительным полем pattern. На физическом устройстве (iPhone X на iOS 13.2) EXC_BAD_ACCESS не происходит. Он воспроизводится только в симуляторе. Очистить проект несколько раз с одними и теми же наблюдениями.

Редактировать:

Обратный след:

libobjc.A.dylib`objc_retain:
    0x7fff50b51c60 <+0>:  testq  %rdi, %rdi
    0x7fff50b51c63 <+3>:  je     0x7fff50b51c81            ; <+33>
    0x7fff50b51c65 <+5>:  js     0x7fff50b51c83            ; <+35>
->  0x7fff50b51c67 <+7>:  movq   (%rdi), %rax
    0x7fff50b51c6a <+10>: testb  $0x4, 0x20(%rax)
    0x7fff50b51c6e <+14>: jne    0x7fff50b51c88            ; objc_object::sidetable_retain()
    0x7fff50b51c74 <+20>: movq   0x3908fee5(%rip), %rsi    ; "retain"
    0x7fff50b51c7b <+27>: jmpq   *0x36ced19f(%rip)         ; (void *)0x00007fff50b37400: objc_msgSend
    0x7fff50b51c81 <+33>: xorl   %edi, %edi
    0x7fff50b51c83 <+35>: movq   %rdi, %rax
    0x7fff50b51c86 <+38>: retq   
    0x7fff50b51c87 <+39>: nop    
Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:]:
    0x7fff2590ddf0 <+0>:  testq  %rdx, %rdx
    0x7fff2590ddf3 <+3>:  je     0x7fff2590de44            ; <+84>
    0x7fff2590ddf5 <+5>:  pushq  %rbp
    0x7fff2590ddf6 <+6>:  movq   %rsp, %rbp
    0x7fff2590ddf9 <+9>:  pushq  %r15
    0x7fff2590ddfb <+11>: pushq  %r14
    0x7fff2590ddfd <+13>: pushq  %rbx
    0x7fff2590ddfe <+14>: pushq  %rax
    0x7fff2590ddff <+15>: movq   %rdi, %r14
    0x7fff2590de02 <+18>: movq   0x62206d9f(%rip), %rdi    ; (void *)0x00007fff87b1d538: NSConcreteNotification
    0x7fff2590de09 <+25>: movq   0x622003a8(%rip), %rsi    ; "newTempNotificationWithName:object:userInfo:"
    0x7fff2590de10 <+32>: movq   0x5b06b749(%rip), %r15    ; (void *)0x00007fff50b37400: objc_msgSend
    0x7fff2590de17 <+39>: callq  *%r15
    0x7fff2590de1a <+42>: movq   %rax, %rbx
    0x7fff2590de1d <+45>: movq   0x8(%r14), %rdi
    0x7fff2590de21 <+49>: movq   %rax, %rsi
    0x7fff2590de24 <+52>: xorl   %edx, %edx
    0x7fff2590de26 <+54>: callq  0x7fff25ae65d8            ; symbol stub for: _CFXNotificationPost
->  0x7fff2590de2b <+59>: movq   0x6220038e(%rip), %rsi    ; "recycle"
    0x7fff2590de32 <+66>: movq   %rbx, %rdi
    0x7fff2590de35 <+69>: movq   %r15, %rax
    0x7fff2590de38 <+72>: addq   $0x8, %rsp
    0x7fff2590de3c <+76>: popq   %rbx
    0x7fff2590de3d <+77>: popq   %r14
    0x7fff2590de3f <+79>: popq   %r15
    0x7fff2590de41 <+81>: popq   %rbp
    0x7fff2590de42 <+82>: jmpq   *%rax
    0x7fff2590de44 <+84>: retq   

DeviceFieldButton:

class DateFieldButton: UIButton {

    var pattern = String()

    override var isSelected: Bool {
        didSet {
            if #available(iOS 13.0, *) {
                backgroundColor = isHighlighted ?  .highlightKeyboardColor : .keyboardColor
            } else {
                backgroundColor = isHighlighted ?  .highlightLightKeyboard : .lightKeyboard
            }
        }
    }

    override var isHighlighted: Bool {
        didSet {
            if #available(iOS 13.0, *) {
                backgroundColor = isHighlighted ?  .highlightKeyboardColor : .keyboardColor
            } else {
                backgroundColor = isHighlighted ?  .highlightLightKeyboard : .darkKeyboard
            }
        }
    }

}

Использование:

            let button = DateFieldButton(type: .custom)
            button.layer.cornerRadius = 10

            dateFormatter.dateFormat = pattern
            let realPattern = dateFormatter.string(from: Date())

            button.setTitle(realPattern, for: .normal)
            button.titleLabel?.text = realPattern
            button.contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)

            if #available(iOS 13, *) {
                button.setTitleColor(.blackAndWhite, for: .normal)
            }
            else {
                button.setTitleColor(.black, for: .normal)
            }
            button.pattern = pattern

            button.addTarget(self, action: #selector(buttonTapped(sender:)), for: .touchUpInside)

1 Ответ

1 голос
/ 16 апреля 2020

после дня отладки я обнаружил проблему на cra * sh.

Ранее я использовал это для получающей стороны, я использовал это:

NotificationCenter.default.addObserver(self, selector: #selector(dateButtonTapped(_:for:)), name: .dateFieldTapped, object: nil)
@objc func dateButtonTapped(_ sender: Notification, for event: UIEvent) {

}

Это вызывает cra sh в симуляторе, который не возникает, если удален параметр for, который был перенесен из другого метода, который я скопировал из-за лени.

NotificationCenter.default.addObserver(self, selector: #selector(dateButtonTapped(_:)), name: .dateFieldTapped, object: nil)
@objc func dateButtonTapped(_ sender: Notification) {

}

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

Кстати, благодаря @Philip Mills в приведенном выше комментарии! Это заставило меня взглянуть на принимающую сторону вместо того, чтобы сосредоточиться на конце публикации.

...