WPK WPK - 4 years ago 107
iOS Question

Protocol extension default method causing a "self is immutable" error

I am trying to extend a class-bound protocol (

UITextInputTraits
) with a default method:

extension UITextInputTraits where Self: UIView {

func setTextInputTraits() {

self.autocapitalizationType = .none // <- compiler error
}
}


It gives a
"Cannot assign to property: 'self' is immutable"
error.

It works if I change the constraint from
UIView
to
UITextField
though, but that defeats the purpose of using protocols.

Why is it an error? How can I achieve implementing this default method?

Thank you!





  • cannot mark the func
    mutating
    , since
    'mutating' isn't valid on methods in classes or class-bound protocols

  • tried sending messages to self, Objective-C style, but
    perform
    does not work with non-object value arguments:

    func setTextInputTraits() {

    let sel = #selector(setter: self.autocapitalizationType)
    self.perform(sel, with: .none)
    }


Answer Source

It works if I change the constraint from UIView to UITextField though, but that defeats the purpose of using protocols. Why is it an error?

Because UIView doesn't already have an autocapitalizationType property. Thus, the compiler has no reason to believe that if it did have one, it would be settable.

How can I achieve implementing this default method?

I think you might be after something like this:

protocol MyTextInputTraits : UITextInputTraits {
    var autocapitalizationType: UITextAutocapitalizationType {get set}
}
extension MyTextInputTraits {
    func setTextInputTraits() {
       self.autocapitalizationType = .none
    }
}
extension UITextView : MyTextInputTraits {}
extension UITextField : MyTextInputTraits {}
extension UISearchBar : MyTextInputTraits {}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download