意外错误:在类中编译时出现“无法分配给属性'self',因为它是不可变的”。

3

现在这是Swift编译器的奇怪行为。我在一个类中获得了一个Cannot assign to property 'self' is immutable 的编译时错误。以下是最小化的playground代码:

import UIKit

open class TextInputTraitsWrapper: NSObject {
    private var wrapped: UITextInputTraits
    
    public init(wrapped: UITextDocumentProxy) {
        self.wrapped = wrapped
        super.init()
    }
    
    open var keyboardAppearance: UIKeyboardAppearance {
        get {
            return wrapped.keyboardAppearance ?? UIKeyboardAppearance.default
        }
        set {
            wrapped.keyboardAppearance = newValue // ERROR ON THIS LINE
        }
    }
}

这是我得到的错误信息(这是完整的程序):

enter image description here

另外,协议UITextInputTraits这样定义keyboardAppearanceoptional var keyboardType: UIKeyboardType { get set }

为什么我在一个类中会得到这种类型的错误?

2个回答

4
这是一个错误,但不是你想的那种错误(错误消息没有任何帮助)。这是一个已知的错误, 是因为UITextInputTraits协议中的keyboardAppearance属性是可选属性(意味着可能没有实现)。这是Objective C的一个特性,而不是Swift的特性,该错误是这样的属性在Swift中不能直接设置,即使它们被标记为{get set}。
让我们模拟同样的架构:
@objc public protocol P {
    @objc optional var keyboardAppearance : NSString {get set}
}

open class C : NSObject {
    private var wrapped: P
    public init(wrapped: P) {
        self.wrapped = wrapped
        super.init()
    }
    open var keyboardAppearance : NSString {
        get {
            wrapped.keyboardAppearance ?? "" as NSString
        }
        set {
            wrapped.keyboardAppearance = newValue
        }
    }
}

我们遇到了相同的错误。但如果删除关键字 optional,该错误就会消失。这证明了 optional 是引起问题的原因。但在您的情况下,您无法删除 optional,因为该协议不属于您。
解决方法与原始错误相同 - 使用关键路径(key path)。
let kp = \C.wrapped.keyboardAppearance
self[keyPath:kp] = newValue

1
或者简单地写成 wrapped[keyPath: \.keyboardAppearance] = newValue - Leo Dabus
谢谢你,Matt,你像往常一样是我的救星。 - Rasto

-2

该错误与您创建的类无关。它与您的变量“wrapped”的底层协议有关。您不能直接修改keyboardAppearance属性。

相反,您需要在源代码中进行修改。那就是用户输入文本框/搜索栏。

为此,只需访问您的UITextField / UISearchBar并在那里更改keyboardAppearance属性即可。

textField.keyboardAppearance = UIKeyboardAppearance.dark

为什么它不能直接修改?这个类型是optional var keyboardAppearance: UIKeyboardAppearance { get set },这意味着它是可设置的。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接