38921

Unexpected quirky behavior from socket.io in Swift

Question:

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:

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

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 }

<strong>Second Controller:</strong>

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 <strong>First view controller</strong>, when the <strong>viewDidAppear()</strong> 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 <strong>Second view controller</strong>.

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

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.

<a href="https://i.stack.imgur.com/5szgq.png" rel="nofollow"><img alt="Screenshot" class="b-lazy" data-src="https://i.stack.imgur.com/5szgq.png" data-original="https://i.stack.imgur.com/5szgq.png" src="https://etrip.eimg.top/images/2019/05/07/timg.gif" /></a>

Answer1:

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.

Recommend

  • Android deep linking into an app
  • PHP mysql form , STUCK
  • JQuery AJAX Dropdown Repeatedly Reset
  • Make NSNumberformatter().numberFromString return an optional
  • PHP count values with same id
  • Swift 3.0 Pin Color Annotation Not Changing in MapView
  • Google linechart visualization chart disappears when updating it?
  • Looped push_back against resize() + iterator
  • RegEx: Find all digits after certain string
  • Use a ListProperty or custom tuple property in App Engine?
  • Email link not working on Android
  • Magento - FishPig Integration - Not getting correct template for /blog
  • Java MethodOverloading error with double values
  • how to convert a unix timestamp into nsdate in iphone [duplicate]
  • web scrape with rvest
  • How to unwind to the first view controller on a navigation stack
  • What is the Linux Equivalent of Kernel32.dll?
  • not able to create VC++ project, with VS11
  • UML diagram generator in Visual Studio 2010
  • How to make R's read_csv2() recognise the text characters properly
  • Using Sax parsing to edit and write XML in VB6
  • Android Activity.onWindowFocusChanged doesn't get called from within TabHost
  • C: Incompatible pointer type initializing
  • Django: Count of Group Elements
  • Display issues when we change from one jquery mobile page to another in firefox
  • Deselecting radio buttons while keeping the View Model in synch
  • Incrementing object id automatically JS constructor (static method and variable)
  • How to check if every primary key value is being referenced as foreign key in another table
  • Sending data from AppleScript to FileMaker records
  • MySQL WHERE-condition in procedure ignored
  • JSON with duplicate key names losing information when parsed
  • Can I have the cursor start on a particular column by default in jqgrid's edit mode?
  • jquery mobile loadPage not working
  • Jquery - Jquery Wysiwyg return html as a string
  • Compare two NSDates in iPhone
  • How to delete a row from a dynamic generate table using jquery?
  • json Serialization in asp
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • How to stop GridView from loading again when I press back button?
  • How to load view controller without button in storyboard?