Swift 4.2中的Starscream单例重新初始化ViewController

时间:2019-03-11 16:58:22

标签: ios swift singleton starscream

我遇到了无法解决的问题。 我正在使用Starscream连接到本地网络上的WebSocket。套接字地址根据我连接的服务器而变化。

我有2个UIViewControllers和一个WebSocketManager类来处理通信。为了简洁起见,我省略了很多样板代码。

ViewController 1

import UIKit
import Starscream

class ViewController: UIViewController {

    var selectedSocket: String! = ""

    @IBOutlet weak var statusLabel: UILabel!

    @IBOutlet weak var table: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        table.delegate = self
        table.dataSource = self
        table.reloadData()
        table.rowHeight = 100
        table.estimatedRowHeight = UITableView.automaticDimension

         }

//MARK: - UITableView extension
extension ViewController: UITableViewDelegate, UITableViewDataSource {


    /// UITableview defaults
    /// 

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let cell = tableView.cellForRow(at: indexPath) as? DevicesOnNetworkTableViewCell {
            print("cell selected")
            selectedSocket = cell.ipAddressLabel.text
            if selectedSocket != "" {
                performSegue(withIdentifier: "connectToServerSegue", sender: selectedSocket)
                tableView.deselectRow(at: indexPath, animated: true)
            } else {
                //TODO: - Handle error
            }
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "connectToServerSegue" {
            if let destination = segue.destination as? ConnectionViewController {
                destination.websocket = selectedSocket

            }
        }
    }
}

当选择IP地址为192.168.2.34:12345的单元格时,该字符串将发送到websocket

ConnectionViewController(ViewController 2):

import UIKit
import Starscream

class ConnectionViewController: UIViewController {


    @IBOutlet weak var logoIcon: UIImageView!
    @IBOutlet weak var versionLabel: UILabel!
    @IBOutlet weak var computerNameLabel: UILabel!
    @IBOutlet weak var ipLabel: UILabel!
    @IBOutlet weak var padlockIcon: UIImageView!
    @IBOutlet weak var modalView: UIView!
    @IBOutlet weak var connectBtn: UIButton!

    ///Default value is 60
    @IBOutlet weak var modalViewTopConstraint: NSLayoutConstraint!

    ///Holds the IP Address and Port number of selected Server
    var websocket: String = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        modalViewTopConstraint.constant = 80
        modalView.alpha = 0
        ipLabel.text = websocket

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        //I've tried to call this method in viewDidLoad. No change.
        WebSocketManager.sharedInstance.establishConnection(socket: websocket)

    }

    deinit {
        print("ConnectionViewController deInitialized")
    }


    func setModalViewContent(version: String,
                             name: String,
                             passwordRequired: Bool) {
        print("Data in setModalViewContent: \(version), \(name), \(passwordRequired)")

        if modalView != nil {
            self.versionLabel.text = version //versionlabel is nil
            self.computerNameLabel.text = name // same here
            self.padlockIcon.isHidden = !passwordRequired //and here
            print("animation not finished")
            displayModalView { (Bool) in

            }
        } else {
            print("modalView is: \(String(describing:modalView))")
        }
    }

    /**
     Animates the modalview into view

     */
    func displayModalView(completion: @escaping(Bool) -> ()) {
        print("modalView: \(String(describing: modalView))")
        if modalView != nil {
            UIView.animate(withDuration: 0.4, delay: 0.3, options: .layoutSubviews, animations: {
                self.modalView.alpha = 1
                self.modalViewTopConstraint.constant = 60
                self.cancelBtn.alpha = 1
                self.view.layoutIfNeeded()
            }) { (finished) in
                print("animation finished")
                completion(true)
            }
        } else {
            completion(false)
        }
    }
}

由于必须在多个ViewControllers上保留连接,所以我认为创建一个Singleton是个好主意:

import Foundation
import Starscream

class WebSocketManager: NSObject {

static let sharedInstance = WebSocketManager()

public var socket = WebSocket(url: URL(string: "placeholder")!)

private override init() {
    super.init()
    // testing connection of the socket
    print("websocket manager is initialized")
}

func establishConnection(socket address: String) {

    socket = WebSocket(url: URL(string: "ws://\(address)/api/v3/")!)
    socket.delegate = self
    socket.connect()

}

func closeConnection() {
    socket.disconnect()
}

}



 extension WebSocketManager: WebSocketDelegate {

 // Other delegate methods omitted for brevity

 func websocketDidReceiveData(socket: WebSocketClient, data: Data) {
     print("websocket did receive data in singleton: \(data.count)")
     DataProcessing.processResponse(data)
 }

}

webSocketDidReceiveData()中名为:DataProcessing.processResponse(data)的方法仅对返回的JSON响应进行解码,并将其返回到ConnectionViewController方法:setModalViewContent(version: String, name: String, passwordRequired: Bool)

这是问题所在。 Starscream可以很好地连接到所选服务器。我得到了期望的响应,但是当数据发送回ConnectionViewController时,它返回nil。

ConnectionViewController中的此方法: setModalViewContent()获取正确的值(版本,名称和密码为必填项),但是当我尝试将这些值设置为ConnectionViewController中的任何值时,应用程序崩溃...

似乎在调用单例之后ConnectionViewController(因为缺少更好的单词)从内存中删除。

我希望我能正确解释。我绝不是编程向导... 谢谢。

0 个答案:

没有答案