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

时间:2016-01-31 16:05:40

标签: ios xcode swift sockets lifecycle

按照标题,我在处理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({$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()时,应用程序将检查用户是否登录。如果有人已经登录,那很好。如果没有人登录,它将执行segue(模态segue)到第二个视图控制器

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

让我们假设一切顺利,直到它来到importData(),该功能根本没有启动,但应用只是继续,为什么?

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

Screenshot

1 个答案:

答案 0 :(得分:0)

经过几天的挣扎,我想我可能找到了正确答案。

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

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

对于两个视图控制器。

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