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

按照标题,我在处理socket.io时遇到了一些麻烦。 它连接得非常好,因此在第一个视图控制器中,但是当涉及到第二个控制器时会发生奇怪的事情。

代码如下:

第一个控制器:我已经声明了两个视图控制器之间的连接目的的全局variables。

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({$0.globalPatientMileAge < $1.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() } } 

您可能已经注意到,在第一个视图控制器中 ,当viewDidAppear()启动时,应用程序将检查用户是否login。 如果有人已经login,那很好。 如果没有人login,它将对第二个视图控制器执行一个segue(modally segue)。

一个login表单将在第二个视图控制器中呈现,一旦用户点击loginbutton, 您可能想看看代码

让我们假设一切正常,直到涉及到importData(),函数根本没有启动,但应用程序只是继续,为什么呢?

这里有一个控制台的截图,注意“你导入了吗?”,如果这个函数启动了,应用程序应该从第一个视图控制器返回一些额外的消息。

截图

经过几天的努力,我想我可能find了正确的答案。

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

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

为视图控制器。

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