Swift 中 socket.io 的意外古怪行为

Unexpected quirky behavior from socket.io in Swift

根据标题,我在处理 socket.io 时遇到了一些问题。它在第一个视图控制器中连接得非常好,因此在第二个控制器中会发生奇怪的事情。

代码如下:

第一个控制器:我已经声明了一些全局变量用于两个视图控制器之间的连接。

import UIKit
import SocketIOClientSwift
import SwiftyJSON
import CoreData

//declare some global variable
var patientCoreData = [NSManagedObject]()
var numberOfUsersExisting:Int = 0 //assign to 0 by default
var appUserData: Patient? //for specific user
var pSample: Array<Patient> = [] //for all user

//initiate socket globally
let socket = SocketIOClient(socketURL: "localhost:3000", options: [
    "reconnects": true
])

func reportStatus(){
    socket.on("connect") {data, ack in
        print("Report status: View Controller connected")
        socket.emit("click", "Client app connected")
    }
}

func readDataFromSocket(completion: (data:AnyObject)-> ()){
    socket.on("reply") {data, ack in
        print("database replied")
        completion(data: data)
    }//socket
}//readDataFromSOCKET

func importData(){
    reportStatus()
    socket.connect()
    readDataFromSocket(){ data in
        let json = JSON(data)
        let nou = json[0].count
        if nou > 0 {
            print("Test(1st VC): grabbing data from database")
            for var i=0; i<nou; ++i{
                numberOfUsersExisting = nou
                pSample += [Patient(id: json[0][i]["ID"].intValue, name: json[0][i]["Name"].stringValue, gender: json[0][i]["Gender"].stringValue, mileage: json[0][i]["Mileage"].doubleValue)]
            pSample.sortInPlace({[=12=].globalPatientMileAge < .globalPatientMileAge})
        }
        print("Successfully grabbed data")
    }else{
        print("No user in the database")
        numberOfUsersExisting = 0
    }
}//readDataFromSocket
}

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout{
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()

}

override func viewDidLoad() {
    super.viewDidLoad()

}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    print("First view appeared")
    let prefs = NSUserDefaults.standardUserDefaults()

    //if an user has logged in
    let isLoggedIn = prefs.integerForKey("ISLOGGEDIN") as Int
    if (isLoggedIn != 1){
        print("No user currently, so heading to login screen")
        socket.disconnect()
        self.performSegueWithIdentifier("gotoLogin", sender: self)
    }else{
        print("ViewDidAppear: An user has been logged in")
        let permissionToLoadData = prefs.integerForKey("ISLOGGEDIN")

        if (permissionToLoadData != 1) {
            print("Please grant permission to get data")
        }else{
            print("First view: connecting to database")

            importData()

        }//permission to load data
    }
}//end of viewDidAppear

}

第二个控制器:

import UIKit
import SocketIOClientSwift
import SwiftyJSON
import CoreData

var nou:Int?

class LoginViewController: UIViewController {
let prefs:NSUserDefaults = NSUserDefaults.standardUserDefaults()
let registeredUserID = NSUserDefaults.standardUserDefaults().stringForKey("registerPatientID")
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

func displayAlertMessage(userMessage:String){
    let alert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
    let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
    alert.addAction(okAction)
    self.presentViewController(alert, animated: true, completion: nil)
}

func successMessage(userMessage:String){
    let alert = UIAlertController(title: "Welcome Back", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert)
    let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
    alert.addAction(okAction)
    self.presentViewController(alert, animated: true, completion: nil)
}

@IBOutlet weak var loginPatientID: UITextField!

@IBAction func LoginButton(sender: AnyObject) {

    let logInUserID = loginPatientID.text
    if (logInUserID!.isEmpty){
        displayAlertMessage("Please enter your Patient ID!")
        return
    }else{
        print("Test: requesting login permission from database")

        socket.emit("loginRequest", logInUserID!)
        print("Test: requested")

        socket.on("loginReply") {data, ack in
            let jsonLogin = JSON(data)
            if jsonLogin[0].intValue == 1{
                print("Test: ID Matched, putting up ViewController")

                self.prefs.setObject(logInUserID, forKey: "AppUserID")
                self.prefs.setInteger(1, forKey: "ISLOGGEDIN")
                self.prefs.synchronize()

                let permissionToLoadData = self.prefs.integerForKey("ISLOGGEDIN")

                if (permissionToLoadData != 1) {
                    print("Please grant permission to get data")
                }else{
                    print("First view: connecting to database")

                    importData()
                    print("Did you import?")

                }//permission to load data

                self.loginPatientID.resignFirstResponder()
                self.dismissViewControllerAnimated(true, completion: nil)
            }else if jsonLogin[0].intValue == 0{
                    self.displayAlertMessage("Sorry, you are not assigned to this program")
            }else if jsonLogin[0].intValue == 3{
                print("Test: Query problem")
            }else{
                print("Test: not getting anything from ID database")
            }
        }//socket.on
    }//else
}//login button


override func viewDidLoad() {
    super.viewDidLoad()
    print("Login View Controller loaded")

}

override func viewDidAppear(animated: Bool) {
    socket.connect()
    print("LoginVC: establishing connection")
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    self.view.endEditing(true)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

}

您可能已经注意到,在 First view controller 中,当 viewDidAppear() 启动时,应用程序将检查用户是否登录与否。如果有人已经登录,那很好。如果没有人登录,它将执行一个 segue(模态 segue)到 Second view controller.

登录表单将显示在第二个视图控制器中,一旦用户点击登录按钮,您可能想查看代码

假设在 importData() 之前一切正常,该函数根本没有启动,但应用程序继续运行,为什么?

这是控制台的屏幕截图,注意 "Did you import?",如果启动该功能,应用程序应该 return 来自第一个视图控制器的一些附加消息。

折腾了几天,我想我可能找到了正确的答案。

最终我定义了 2 个不同的套接字处理程序连接:

let loginSocket = SocketIOClient(socketURL: "localhost:3000")
let socket = SocketIOClient(socketURL: "localhost:3000", options: [
"reconnects": true
])

对于两个视图控制器。

如果我可以从这个难题中得出一个结论,那就是我们不能对来自不同视图控制器的套接字方法使用单个套接字处理程序。