在ViewController加载

时间:2017-11-16 11:31:39

标签: ios swift socket.io

我正在使用socket.io来使用实时机制。我现在面临的问题是在加载viewController之后创建的Socket.io对象

我正在使用Singleton design

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()
    }

}

无论如何确保用户与令牌一起建立与服务器的连接,我需要在establishConnection中设置套接字。如果我按照Vlad的回答,将永远不会建立连接,因为令牌之前是空的,因此用户将无法连接。

用户登录

func logIn() {
   // Getting it from alamofire
   keychain["token"] = token
   //then only establish connection
   SocketIOManager.sharedInstance.establishConnection()
}

如果我使用Init方法,那么socket将为nil,因为在applicationDidBecomeActive中有SocketIOManager.sharedInstance.establishConnection(),所以逻辑是每当用户加载应用applicationDidBecomeActive时将运行

技术上我正在使用sharedInstance来运行socket.io对象。

func applicationDidBecomeActive(_ application: UIApplication) {
        SocketIOManager.sharedInstance.establishConnection()
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

现在,didBecomeActive中的套接字对象在加载视图后运行

override func viewDidLoad() {
    super.viewDidLoad()
    listeningOnMerchant()

}

func listeningOnMerchant() {
   // I got error around here
   SocketIOManager.sharedInstance.socket.on("listening") { ack, data in
      print("something")


   }
  }
}

哪个会因为socket为零而崩溃。如何使viewController不崩溃。我可以使用let方法来停止崩溃

if let socket = SocketIOManager.sharedInstance.socket {

}

但是如果我使用socket并且套接字将不会运行,它将为零。我怎么不让套接字不崩溃?

因为我真的需要将socket.connect放在applicationDidBecomeActive上以使其保持一致,就像连接vs didLaunch

一样

谢谢!

4 个答案:

答案 0 :(得分:1)

据我了解,您的问题是在 establishConnection func中设置 SocketIOClient 。如果它与nil崩溃,可能你的构造函数在这里返回nil:

SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])

我也没有在这个功能中看到这样做的理由。很容易出错并在某些时候让 socket var保持未初始化状态。我宁愿让它在构造函数中设置它,如下所示:

import SocketIO

class SocketIOManager: NSObject {

    static let sharedInstance = SocketIOManager()

    let socket: SocketIOClient!

    init() {
        super.init()
        socket = YourFixedConstructorHere()
    }
}

如果你想确保它已初始化,你也可以把它变成lazy var,就像这样:

lazy var socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(false), .compress, .connectParams(["token": "asdasdasdsa"])])

答案 1 :(得分:1)

从技术上讲,要解决此问题,您需要使用init方法,以便套接字不会为零。由于您需要在应用程序暂停时运行套接字等,无论如何都需要使用init方法。

   private override init() {
        self.socket = SocketIOClient(socketURL: URL(string: mainURL)!, config: [.log(true), .compress, .forceNew(true), .connectParams(["token": getToken()])])
        super.init()
    }

添加forceNew(true),这样您就不会为一个用户创建多个连接

您需要做的下一步是创建另一个只有您的loginViewController可以访问的函数

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

    }

将令牌传递给参数,以便只有用户已登录,然后才能建立连接。如果您有任何问题,请告诉我

我将此解决方案用于我自己的应用程序并且完美运行

答案 2 :(得分:0)

如果我理解你的问题,在某些时候你不能使用 establishConnection(),因为你没有令牌。这个逻辑并不完全适合你的单例模式,因为你的对象只负责建立/取消连接,并且在创建实例后它已经无法做到这一点。我宁愿在这里使用服务,像这样:

class SocketIOService {
    let token: String // I think if token is related to SocketIO, you can store it here
    init(token: String) {
        self.token = token
    }
    // Your code to establish connections, etc
}

这样您就可以保证,没有令牌就无法创建您的整个服务。更好,就像我一样

单例模式的选项不太好,但它们肯定存在。首先,您可以在方法中添加参数:

func establishConnection(withToken token: String) {
    // code
}

使用此方法,您将需要传入令牌,因此如果没有它,用户将无法建立连接。

然后,无论你想在哪里使用它,都可以这样做:

if let token = // Your code to retrieve token {
    SocketIOManager.shared.establishConnection(withToken: token)
}

甚至:

keychain["token"].flatMap {SocketIOManager.shared.establishConnection(withToken: $0)}

非常好,是吗?

还有其他几种方法可以做到这一点,但是对于所有这些方法,您的工作流程几乎相同 - 首先检查,如果您有令牌,则调用此方法。如果您没有成功 - 在检索令牌后,请再试一次。

答案 3 :(得分:0)

我认为问题是时间问题。你应该在ViewController加载视图之前调用你的单例。所以你最好把这段代码

SocketIOManager.sharedInstance.establishConnection()

到AppDelegate

中的一个函数(先前执行过)
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

         SocketIOManager.sharedInstance.establishConnection()

    return true
}
相关问题