我正在努力制定一个合适的单例模型用于Swift的使用。到目前为止,我已经能够得到一个非线程安全的模型工作为:

class var sharedInstance: TPScopeManager {
    get {
        struct Static {
            static var instance: TPScopeManager? = nil
        }

        if !Static.instance {
            Static.instance = TPScopeManager()
        }

        return Static.instance!
    }
}

将单例实例包装在Static结构中应该允许单个实例不与单例实例发生冲突,而不需要复杂的命名方案,并且它应该使事情相当私密。但是,这个模型显然不是线程安全的。所以我尝试将dispatch_once添加到整个事情中:

class var sharedInstance: TPScopeManager {
    get {
        struct Static {
            static var instance: TPScopeManager? = nil
            static var token: dispatch_once_t = 0
        }

        dispatch_once(Static.token) { Static.instance = TPScopeManager() }

        return Static.instance!
    }
}

但是我在dispatch_once行上得到了一个编译器错误:

不能将表达式的类型“Void”转换为类型“()”

我尝试了几种不同的语法变体,但它们似乎都有相同的结果:

dispatch_once(Static.token, { Static.instance = TPScopeManager() })

在Swift中dispatch_once的正确用法是什么?我最初认为问题出在错误消息中的()块上,但我看得越多,就越觉得可能是正确定义dispatch_once_t的问题。


当前回答

第一个解决方案

let SocketManager = SocketManagerSingleton();

class SocketManagerSingleton {

}

在后面的代码中:

func someFunction() {        
    var socketManager = SocketManager        
}

第二个解决方案

func SocketManager() -> SocketManagerSingleton {
    return _SocketManager
}
let _SocketManager = SocketManagerSingleton();

class SocketManagerSingleton {

}

在后面的代码中,你可以使用大括号来减少混淆:

func someFunction() {        
    var socketManager = SocketManager()        
}

其他回答

在看到David的实现之后,似乎没有必要使用单个类函数instanceMethod,因为let所做的事情与sharedInstance类方法几乎相同。你所要做的就是把它声明为一个全局常数,就是这样。

let gScopeManagerSharedInstance = ScopeManager()

class ScopeManager {
   // No need for a class method to return the shared instance. Use the gScopeManagerSharedInstance directly. 
}

我要求我的单例允许继承,而这些解决方案实际上都不允许。所以我想到了这个:

public class Singleton {
    private static var sharedInstanceVar = Singleton()

    public class func sharedInstance() -> Singleton {
        return sharedInstanceVar
    }
}


public class SubSingleton: Singleton {

    private static var sharedInstanceToken: dispatch_once_t = 0

    public class override func sharedInstance() -> SubSingleton {
        dispatch_once(&sharedInstanceToken) {
            sharedInstanceVar = SubSingleton()
        }
    return sharedInstanceVar as! SubSingleton
    }
}

这样,当首先执行Singleton. sharedinstance()时,它将返回Singleton的实例 当首先执行SubSingleton. sharedinstance()时,它将返回创建的SubSingleton实例。 如果执行了上述操作,则SubSingleton.sharedInstance() is Singleton为true,并且使用相同的实例。

第一种脏方法的问题是,我不能保证子类会实现dispatch_once_t,并确保每个类只修改一次sharedInstanceVar。

我将尝试进一步完善它,但是看看是否有人对此有强烈的反对(除了它很冗长并且需要手动更新之外),这将是很有趣的。

   func init() -> ClassA {
    struct Static {
        static var onceToken : dispatch_once_t = 0
        static var instance : ClassA? = nil
    }

    dispatch_once(&Static.onceToken) {
        Static.instance = ClassA()
    }

    return Static.instance!
}

根据苹果的文档,已经重复了很多次,在Swift中最简单的方法是使用静态类型属性:

class Singleton {
    static let sharedInstance = Singleton()
}

然而,如果你正在寻找一种方法来执行一个简单的构造函数调用之外的额外设置,秘密是使用一个立即调用的闭包:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()
        // setup code
        return instance
    }()
}

这保证是线程安全的,并且只进行一次惰性初始化。

final class MySingleton {
     private init() {}
     static let shared = MySingleton()
}

那就叫它;

let shared = MySingleton.shared