【问题标题】:Singleton with properties in Swift 3在 Swift 3 中具有属性的单例
【发布时间】:2016-10-23 12:38:45
【问题描述】:

在 Apple 的 Using Swift with Cocoa and Objective-C document(针对 Swift 3 更新)中,他们给出了以下单例模式示例:

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()

        // setup code

        return instance
    }()
}

让我们假设这个单例需要管理一个可变的字符串数组。我将如何/在哪里声明该属性并确保将其正确初始化为空的 [String] 数组?

【问题讨论】:

    标签: singleton swift3


    【解决方案1】:

    对我来说这是最好的方法,将 init 设为私有。 Swift 3 \ 4 \ 5 语法

    // MARK: - Singleton
    
    final class Singleton {
    
        // Can't init is singleton
        private init() { }
    
        // MARK: Shared Instance
    
        static let shared = Singleton()
    
        // MARK: Local Variable
    
        var emptyStringArray = [String]()
    
    }
    

    【讨论】:

    • 我赞成这个答案,但为了匹配 Swift 3 语法,“sharedInstance”应该改为“shared”。
    • 除非有从 swift 2 到 swift 3 的回归,否则你不会
    • shared后面的类型可以省略吧? static let shared = Singleton()
    • @YannickSteph 你不必写static let shared: Singleton = Singleton() 而是你可以写static let shared = Singleton()
    • @RomanN 不,您不能覆盖 init,因为它不继承类。如果你能做到这一点,用这个例子final class Singleton: NSObject { private override init() { } }
    【解决方案2】:

    根据苹果的文档:In Swift, you can simply use a static type property, which is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously

    class Singleton {
    
        // MARK: - Shared
    
        static let shared = Singleton()
    }
    

    带初始化方法:

    class Singleton {
    
        // MARK: - Shared
    
        static let shared = Singleton()
    
        // MARK: - Initializer
    
        private init() {
        }
    
    }
    

    【讨论】:

    • 为什么 init() 不是私有的?
    【解决方案3】:

    你可以像这样初始化一个空数组。

    class Singleton {
    
        //MARK: Shared Instance
    
        static let sharedInstance : Singleton = {
            let instance = Singleton(array: [])
            return instance
        }()
    
        //MARK: Local Variable
    
        var emptyStringArray : [String]
    
        //MARK: Init
    
        init( array : [String]) {
            emptyStringArray = array
        }
    }
    

    或者,如果您更喜欢不同的方法,这个方法也可以。

    class Singleton {
    
        //MARK: Shared Instance
    
        static let sharedInstance : Singleton = {
            let instance = Singleton()
            return instance
        }()
    
        //MARK: Local Variable
    
        var emptyStringArray : [String]? = nil
    
        //MARK: Init
    
        convenience init() {
            self.init(array : [])
        }
    
        //MARK: Init Array
    
        init( array : [String]) {
            emptyStringArray = array
        }
    }
    

    【讨论】:

    • 这种方法在扩展中不起作用吗? extension Cache { static let sharedInstance: Cache = { let instance = Cache() return instance }() }
    • 有趣的是,Apple 在 iOS 10 中将 class var 用于单例(例如 UIApplication)。他们的实现会和这个一样吗?
    • 我更喜欢单例初始化方法作为private 方法,甚至不是internal。这可以防止其他人为此类使用默认的 '()' 初始化程序。
    • @KumarC 你是对的,如果我们在init 中添加一个private 会不会解决问题。
    • @TikhonovAlexander 你能带来更多信息吗?
    【解决方案4】:

    任何初始化都将在 init 方法中完成。单例和非单例之间没有区别。

    【讨论】:

    • 直接回答问题的附加代码 sn-p 将使此答案更有帮助。
    猜你喜欢
    • 2017-02-27
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多