例如我们有简单的枚举
public enum CXActionSheetToolBarButtonItem {
case cancel
case done
case now
private static var titles: [CXActionSheetToolBarButtonItem: String] = [
.cancel: "Cancel",
.done: "Done",
.now: "Now",
]
public var title: String {
get { return CXActionSheetToolBarButtonItem.titles[self] ?? String(describing: self) }
// what am I want to do
set(value) { CXActionSheetToolBarButtonItem.titles[self] = value }
}
// what am I forced to do
public static func setTitle(_ title: String, for item: CXActionSheetToolBarButtonItem) {
CXActionSheetToolBarButtonItem.titles[item] = title
}
}
为什么我不能像这样设置新标题
CXActionSheetToolBarButtonItem.cancel.title = "asd"
编译器响应错误 - 无法分配属性:'取消'不可设置,但我可以用功能设置标题
CXActionSheetToolBarButtonItem.setTitle("asd", for: .cancel)
我应该如何改变我的var作为可设置的? .cancel.title = "asd"
答案 0 :(得分:6)
使用枚举似乎不合适,但我会以面值来解决问题。您需要将您的setter标记为nonmutating
,以便可以在枚举的非var
实例上调用它:
public enum CXActionSheetToolBarButtonItem {
// ...
public var title: String {
get { return CXActionSheetToolBarButtonItem.titles[self] ?? String(describing: self) }
nonmutating set(value) { CXActionSheetToolBarButtonItem.titles[self] = value }
}
}
CXActionSheetToolBarButtonItem.cancel.title = "foo" // Works... but why would you want this?!
答案 1 :(得分:0)
我认为你不能这样做的主要原因是因为Swift编译器在默认情况下将枚举案例视为不可变的(类似于用struct
声明的不可变let
),这里你是试图改变它。
如果您尝试将变异函数添加到此枚举
,这是一个很好的方法mutating public func setTitle2(_ newValue: String) {
CXActionSheetToolBarButtonItem.titles[self] = newValue
}
然后您将收到错误消息
error: cannot use mutating member on immutable value: 'cancel' returns immutable value
获得类似行为的一种方法是将此枚举更改为一组静态变量(这与您尝试实现的更加一致)。
public struct CXActionSheetToolBarButtonItem {
var title: String
static var cancel = CXActionSheetToolBarButtonItem(title: "Cancel")
static var done = CXActionSheetToolBarButtonItem(title: "Done")
static var now = CXActionSheetToolBarButtonItem(title: "Now")
}
现在您可以使用以下
CXActionSheetToolBarButtonItem.cancel.title = "asd"
此外,您仍然可以使用点语法
let buttonItem: CXActionSheetToolBarButtonItem = .cancel // it works
希望有所帮助!
TD; DR:因为enum
是不可变对象。
答案 2 :(得分:0)
首先:无论你想在这里做什么 - 它肯定不是一个好方法而且非常危险。正如克雷格在评论中指出的那样,你正在搞乱实例属性和静态属性。您可以拥有枚举的多个实例 - 但是当您想要更改特定实例的标题时,您还可以更改所有其他实例的标题。这是意想不到的行为,您应该考虑另一种解决方案。
话虽这么说,你的代码确实工作 - 只需稍作修改:而不是
CXActionSheetToolBarButtonItem.cancel.title = "asd"
你可以写
var item = CXActionSheetToolBarButtonItem.cancel
item.title = "asd"
这将编译。
背后的原因是枚举是一个值类型。每次创建枚举类型的实例时,例如var item = CXActionSheetToolBarButtonItem.cancel
,将枚举值复制到新变量item
中。您可以使用var
或let
选择是否希望该值可变。这就是Swift枚举的用法。
单个枚举案例如CXActionSheetToolBarButtonItem.cancel
根据定义是不可变的。
CXActionSheetToolBarButtonItem.cancel.title = "asd"
没有任何意义,因为没有可以分配标题的实例。枚举案例.cancel
未绑定到变量。