Unexpected quirky behavior from socket.io in Swift

时光怂恿深爱的人放手 提交于 2019-12-08 11:50:22

问题


As per title, I'm having some trouble dealing with socket.io. It connects really well and accordingly in the first view controller but weird things happen when it comes to second controller.

Here's the code:

First Controller: I have declared some global variable for connection purposes between both view controller.

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

}

Second Controller:

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()
}

}

You may have noticed that in First view controller, when the viewDidAppear() is launched, the app will checks if user is login or not. If somebody has already logged in, it's fine. If there is nobody logging in, it will perform a segue(modally segue) to Second view controller.

A login form will be presented in second view controller and once user hits the login button, you might wanna look at the code.

Let's assume that everything goes right until it comes to importData(), the function isn't launched at all but the app just goes on, why?

Here's a screenshot of the console, pay attention to "Did you import?", if the function is launched, the app should return some additional message from 1st view controller.


回答1:


After struggling for a few days, I think I may have found the correct answer.

Eventually I defined 2 different socket handlers connection as such:

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

for both view controller.

If there is a conclusion I can draw from this conundrum is that we can't use single socket handler for socket methods from different view controller.



来源:https://stackoverflow.com/questions/35115936/unexpected-quirky-behavior-from-socket-io-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!