Синглтон Starscream в Swift 4.2 повторно инициализирует ViewController - PullRequest
0 голосов
/ 11 марта 2019

Я столкнулся с проблемой, которую не могу исправить.Я использую 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, он возвращает ноль.

Этот метод из ConnectionViewController: setModalViewContent() возвращает правильные значения (version, name & passwordRequired), нокогда я пытаюсь установить эти значения на что-либо в ConnectionViewController, приложение вылетает ...

Кажется, что ConnectionViewController (из-за отсутствия лучшего слова) удаляется из памяти при вызове синглтона.

Надеюсь, я объяснил это правильно.Я ни в коем случае не мастер программирования ... Спасибо.

...