单例模式中的Swift mutating func

3
在Swift中我有这个单例模式:
struct Networking {
    static let shared = Networking()
    private var observed: Set<String> = []
}

我需要操作observed,并且需要创建一个有用的方法来插入和删除Set中的成员。

mutating func addObserver(for member: String) {
    //other code
    observed.insert(member)
}

mutating func removeObserver(for member: String) {
    //other code
    observed.remove(member)
}

问题在于当我尝试像这样调用这些方法时。
Networking.shared.addObserver(for: "x")

因为我遇到了这个错误
cannot use mutating on immutable value: “shared” is a “let” constant

这个错误很明显。 "shared" 是 "let",显然不能被修改。但是要修改 "var" ,我需要将方法声明为可变的(mutating)。这就是一个恶性循环。
有什么想法吗? 谢谢。

3
如果你把Networking用作单例模式,为什么不将其作为一个课程呢? - totiDev
可变的值类型不能成为单例——按定义,单例只能有一个实例。对于可变的值类型,一旦你改变它的一个拷贝,你就得到了不同的“实例”。 - Hamish
单例必然是类。如果你想要使用一个结构体来表示单例的偏好,那也可以,但是结构体在单例设计中根本行不通。 - GetSwifty
@PEEJWEEJ 你可以将不可变的值类型作为单例 - 这将满足所需的语义。 - Hamish
3个回答

4
如果您希望您的 Networking 对象充当单例,为什么不将其作为类而不是结构体呢?
class Networking {

    static let shared = Networking()
    private var observed: Set<String> = []

    func addObserver(for member: String) {
        //other code
        observed.insert(member)
    }

    func removeObserver(for member: String) {
        //other code
        observed.remove(member)
    }
}

Networking.shared.addObserver(for: "x")

这样可以简化代码并解决您的问题。

1
基本上,您的语法是错误的,Networking() 创建了一个类的新实例
要将结构体用作单例,您必须编写
Networking.shared.addObserver(for: "x")

然后将shared声明为可变的。
static var shared = Networking()

抱歉,我插入了一个打字错误。我已经删除了 Networking()。但是声明共享变量为 var 是正确的吗?这是否违反了单例模式? - Fry
实际上,使用“类”的另一种解决方案更可取。 - vadian

0

还有另一种方法可以实现它

class Networking {
    static let shared = Networking()
    var observed: Set<String> = [] {
        didSet {
            print("set has changed")
        }
    }
}

值类型

由于Set是一个结构体(值类型),每次向Set添加或删除元素时,didSet块都将被执行。

Networking.shared.observed.insert("a")

集合已更改。
Networking.shared.observed.insert("b")

集合已更改。
Networking.shared.observed.remove("a")

集合已更改。

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