Lazy vs init用于swift中的单例设计

时间:2017-11-18 07:11:52

标签: ios swift socket.io

我正在使用Socket.io库为我的应用添加实时功能,而我正在使用Singleton设计

import SocketIO

class SocketIOManager: NSObject {

    static let sharedInstance = SocketIOManager()

    var socket: SocketIOClient!

    func establishConnection() {
       socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])
       socket.connect()

    }

    func closeConnection() {
        socket.disconnect()
    }

}

从技术上讲,只要我的应用加载socket,就不能为零,否则会崩溃。我找到了两个可以解决这个问题的解决方案

  1. 懒惰

    lazy var socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])
    
  2. 使用此方法socket将永远不会为零,因为它将始终初始化。但是这个方法的问题在于,如果创建SocketIOClient并不便宜,那么它将是一个很好的使用方法。

    1. 初始化()

      class SocketIOManager: NSObject {
      
          static let sharedInstance = SocketIOManager()
      
          let socket: SocketIOClient!
      
      
      
      init() {
              super.init()
              socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])
        }
      }
      
    2. 通过使用这种方法,我有点困惑,因为我最初没有像

      那样创建SocketIOManager对象
      let socket = SocketIOManager()
      

      因为如果我没有弄错,如果只创建了对象,套接字将被初始化,而我不确定在Singleton设计中使用init()

      哪种方法适合我的用例?

2 个答案:

答案 0 :(得分:5)

在Swift全局变量中,默认情况下,类的静态成员都是 lazy ,所以这是正确的:

this

请注意init上的 private ,以防止其他人尝试实例化此类,因为它是一个单例。

答案 1 :(得分:1)

来自documentation

  

存储类型属性在首次访问时会被懒惰地初始化。它们只保证初始化一次,即使同时由多个线程访问,也不需要使用延迟修饰符进行标记。

建议的方法是将套接字声明为非可选,首先初始化该属性,然后调用super

class SocketIOManager: NSObject {

    static let sharedInstance = SocketIOManager()

    let socket: SocketIOClient

    init() {
        socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])
        super.init()
    }
}

或者使用闭包初始化socket,但这要求不能访问同一类的其他属性。

class SocketIOManager: NSObject {

    static let sharedInstance = SocketIOManager()

    let socket: SocketIOClient = {
         return SocketIOClient(socketURL: URL(string: "https://server.com/path")!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])
    }()
}

或者如果mainURL在同一个类中声明为常量,则可以懒惰地初始化socket。这意味着套接字也将在 首次访问时初始化。

class SocketIOManager: NSObject {

    static let sharedInstance = SocketIOManager()

    let mainURL = URL(string: "https://server.com/path")!

    lazy var socket: SocketIOClient = {
         return SocketIOClient(socketURL: mainURL, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])
    }()
}

在第二种和第三种情况下,不需要额外的init方法。