Search code examples
iosswiftxcodeuibuttonnsmutabledictionary

[UIButton copyWithZone:]: unrecognized selector sent to instance


    func createRowOfButtons(buttonTitles: [NSString]) -> UIView {
    var buttons = [UIButton]()
    let keyboardRowView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 50))
    var dict = [UIButton:String]()
    for buttonTitle in buttonTitles 
    {
       let button = createButtonWithTitle(title: buttonTitle as String)
        buttons.append(button)
        keyboardRowView.addSubview(button)
        dict.updateValue("\(buttonTitle)", forKey: button)
    }
    allButtons = NSMutableDictionary(dictionary: dict)
    //error:[UIButton copyWithZone:]: unrecognized selector sent to instance 0x7e011bc0
    addIndividualButtonConstraints(buttons: buttons, mainView:keyboardRowView)
    return keyboardRowView
}

I am new to iOS, I want to create a NSMutableDictionary of UIButton but it give the following error:

Cannot cast 'UIButton' to 'NSCopying'.

I don't understand why this error occurs.

Thanks in advance.


Solution

  • It is really not certain why you would have to resort to using NSString or NSMutableArray, especially taking into account that you bridge NSString to String, which hints that NSString is actually useless.

    Local buttons and dict arrays also seem to be unnecessary since after your loop finishes you simply assign those buttons to allButtons. It means that you can address that storage directly (with proper Swift [String: UIButton] type instead of NSMutableDictionary):

    var allButtons: [String: UIButton]!
    
    func createRowOfButtons(buttonTitles: [String]) -> UIView {
    
        let keyboardRowView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 50))
    
        // Initialize / reset dictionary
        // Do it here or on declaration
        allButtons = [String: UIButton]()
    
        // Populate dictionary
        buttonTitles.forEach { title in
            let button = UIButton()// createButtonWithTitle(title: title)
            keyboardRowView.addSubview(button)
            allButtons[title] = button
        }
    
        addIndividualButtonConstraints(buttons: Array(allButtons.values),
                                       mainView: keyboardRowView)
        return keyboardRowView
    }
    

    You also access buttons by their titles, not vice versa.