我遇到了无法解决的问题。 我正在使用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
(因为缺少更好的单词)从内存中删除。
我希望我能正确解释。我绝不是编程向导... 谢谢。