侧边栏壁纸
博主头像
钱学超博主等级

火星人,1万小时法则的忠实拥趸。技术宅,象棋和羽毛球爱好者,马拉松PB成绩:4小时零8分。坚持认为算法是计算机的灵魂。喜欢解决问题,喜欢手工,喜欢与朋友们聊天喝酒吹牛X。

  • 累计撰写 81 篇文章
  • 累计创建 447 个标签
  • 累计收到 88 条评论
标签搜索

目 录CONTENT

文章目录

swift使用websocket连接打造im之注意事项

钱学超
2023-02-24 / 2 评论 / 0 点赞 / 298 阅读 / 601 字 / 正在检测是否收录...
  1. swift尽可能多的使用struct而不是class,因为struct是按值传递,class是按照引用传递

  2. 所以在struct使用的时候需要多注意引用的保存。即便是class,也可能会存在引用的保存问题。

  3. 例子:

lass LztSocket: WebSocketDelegate {
    private init() {}
    // 唯一实例
    public static var shared: LztSocket = .init()

    // 初始化WebSocket,连接服务器,设置参数等。
    func initSocket() {
        if (socket != nil) {
            return
        }
        let devId = LztContext.shared.deviceId;
        let url = "\(LztConst.pushUrl)/wsapi/v1.0/ws/connect?token=\(LztContext.shared.pushToken)&dev_id=\(devId)&dev_type=ios";
        var request = URLRequest(url: URL(string: url)!)
        request.timeoutInterval = 5
        request.setValue("14", forHTTPHeaderField: "Sec-WebSocket-Version")
        let pinner = FoundationSecurity(allowSelfSigned: true) // don't validate SSL certificates
        let socket = WebSocket(request: request, certPinner: pinner)
        socket?.delegate = self
        socket?.connect()
        log.debug("初始化Socket连接完毕")
    }
    func didReceive(event: Starscream.WebSocketEvent, client: Starscream.WebSocket) {
        log.debug("接收到服务器推送下来的消息了。")
    }
}
  1. 查看以上代码,初看觉得没啥问题,运行起来,就是无法收取到任何服务器端消息。

  2. 仔细研究了一下,发现socket对象是在initSocket方法调用中产生的,没有意外的话,方法调用结束,它的生命周期也就结束了,会被回收掉。

  3. 因此,即便是有消息回来,也不可能有内容打印出来。虽然整个类是一个单例,创建之后,单例始终存在,但是因为没有任何引用到socket对象保存在单例的实例中,因此也会被回收掉。

  4. 解决方法:

    // websocket 连接
    private var socket:WebSocket? = nil;
  1. 在initialSocket方法中,把let去掉,这样,socket的生命周期就随着单例走了。只要单例不销毁,就可以一直接收到消息。

  2. 同样类似的问题,也会存在于SwiftUI的页面属性中。

  3. 因为SwiftUI的页面,全部是采用的struct XXXX:View 的形式,在构建页面的时候,如果是struct的属性,使用完毕之后,struct会被销毁,属性也会被销毁。虽然这时候页面还显示在画面中,但是已经不是你代码写的那个View了。

  4. 如果要让某个属性暂不销毁,就需要给他设置@State,或者其他可以保存状态的modifier。


0

评论区