我正在使用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
谢谢!
答案 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
}