简体   繁体   中英

Any reason why the NotificationCenter causes EXC_BAD_ACCESS on simulator, but not on device?

I have this code here:

    @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")

}

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

DeviceFieldButton is just a subclass of UIButton , with an additional field of pattern . On a physical device (iPhone X on iOS 13.2), EXC_BAD_ACCESS does not occur. It is only replicable in the Simulator. Have cleaned project multiple times with same observations.

Edit:

Back trace:

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
            }
        }
    }

}

Usage:

            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)

after a day of debugging, I have found the issue to the crash.

Previously I was using this for the receiving end, I was using this:

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

}

This causes the crash in the Simulator, which does not occur, if the for parameter is removed, which was a left over from another method which I copied over due to laziness.

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

}

So, I'm answering my own question, in case others in the future stumble across with the same issue.

By the way, thanks to @Philip Mills in the above comment. That made me look into the receiving end instead of focusing on the posting end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM