iOS SDK retrieving a variable error

So I am using the iOS SDK so that I can talk to the Particle Cloud with Xcode. I have already successfully created the bridging header and I successfully used SparkCloud.sharedInstance().login() to login to my Cloud account. I have also successfully got a list of all the devices through Xcode. So everything works. But when I try to get a variable from the Cloud, I get this error, "2018-01-20 13:06:38.308319-0500 BusLocator[5374:3327907] TIC Read Status [6:0x1c01633c0]: 1:57"
I actually get three of these errors in a row, but they are all the exact same.

Here is the code that generated the error,

SparkCloud.sharedInstance().getDevices { (devices:[SparkDevice]?, error:Error?) -> Void in
            if let _ = error {
                print("Check your internet connectivity")
            }
            else {
                if let d = devices {
                    for device in d {
                        print("\(device.name ?? "No device name")")
                        if device.name == busNumber {
                            self.myPhoton = device
                            print("Connected to \(device.name ?? "no device"))")
                        }
                    }
                }
            }
        }

Let me know if you need anymore information

Thanks!

I don’t see any place in the code you posted where you’re try to access a variable. Which line in your code is throwing the error?

Sorry, wrong code. Here is the actual code that causes the error:

func getLocation() {
    if self.loggedIn == true {
        print("Attempting to get the location")
        myPhoton!.getVariable("L", completion: { (result:Any?, error:Error?) -> Void in
            if let _ = error {
                print("Failed reading location from device")
            }
            else {
                if let location = result as? NSNumber {
                    print("Location is \(location.stringValue)")
                }
            }
        })
    }
}

I call the function “getLocation()” in the IBAction of a button so that it calls it when the button is pressed.
The name of the variable is “L” and it should return a latitude and longitude like, “1234.234, 1234.3456” or something.

The “loggedIn” variable is true after I successfully login to the Particle Cloud in some code above. I’m not sure if you need that login code, but here it is,

func login() {
    if usernameTextField.text != "Username" && passwordTextField.text != "Password" {
        SparkCloud.sharedInstance().login(withUser: usernameTextField.text!, password: passwordTextField.text!) { (error:Error?) -> Void in
            if let _ = error {
                print("Wrong credentials or no internet connectivity, please try again")
                self.loginFeedbackLabel.text = "Wrong username or password"
                self.loggedIn = false
            }
            else {
                print("Logged in")
                self.loggedIn = true
                self.loginFeedbackLabel.text = "Login Successful"
                self.connectToDevice(busNumber: self.busNumberTextField.text!)
            }
        }
    }
    
}

So this function is called when the login button is pressed and uses the text from two text fields for the username and password.

Let me know if you need any more information.

Thanks!

I was out of town, so I wasn’t keeping up with your problem, hence the delay in getting back to you. You’ve shown 3 different pieces of code, but I’m not sure how it all fits together. Please post all the code that runs before and up to the code that causes the error. That should include the function connectToDevice that I see you’re calling form the login() function. The fact that the error takes a while to show up sounds like you may be timing out on your call to the Particle.variable.

That’s okay. I will send the code sometime today because I’m not on my mac right now. Thanks for the help

Here is all the code:

    import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var usernameTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var busNumberTextField: UITextField!
    @IBOutlet weak var loginFeedbackLabel: UILabel!
    @IBOutlet weak var locationLabel: UILabel!
    
    var myPhoton: SparkDevice!
    var loggedIn: Bool = false
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func loginButtonPressed(_ sender: Any) {
        login()
        connectToDevice(busNumber: busNumberTextField.text!)
    }
    
    @IBAction func getLocationButtonPressed(_ sender: Any) {
        getLocation()
    }
    
    
    func login() {
        if usernameTextField.text != "Username" && passwordTextField.text != "Password" {
            SparkCloud.sharedInstance().login(withUser: usernameTextField.text!, password: passwordTextField.text!) { (error:Error?) -> Void in
                if let _ = error {
                    print("Wrong credentials or no internet connectivity, please try again")
                    self.loginFeedbackLabel.text = "Wrong username or password"
                    self.loggedIn = false
                }
                else {
                    print("Logged in")
                    self.loggedIn = true
                    self.loginFeedbackLabel.text = "Login Successful"
                    self.connectToDevice(busNumber: self.busNumberTextField.text!)
                }
            }
        }
        
    }
    
    func connectToDevice(busNumber: String) {
        SparkCloud.sharedInstance().getDevices { (devices:[SparkDevice]?, error:Error?) -> Void in
            if let _ = error {
                print("Check your internet connectivity")
            }
            else {
                if let d = devices {
                    for device in d {
                        print("\(device.name ?? "No device name")")
                        if device.name == busNumber {
                            self.myPhoton = device
                            print("Connected to \(device.name ?? "no device"))")
                        }
                    }
                }
            }
        }
    }
    
    func getLocation() {
        if self.loggedIn == true {
            print("Attempting to get the location")
            myPhoton!.getVariable("L", completion: { (result:Any?, error:Error?) -> Void in
                if let _ = error {
                    print("Failed reading location from device")
                }
                else {
                    if let location = result as? NSNumber {
                        print("Location is \(location.stringValue)")
                    }
                }
            })
        }
    }
    
    
}

I tried your code, and it works for me with a couple of modifications. We may be using different versions of something, because SparkDevice and SparkCloud cause errors for me; replacing Spark with Particle fixes those errors.

After those two changes, your code works fine for me. I can’t get the error you’re seeing, and the error you get is one I’ve never seen before in Xcode. Looking at StackOverflow, it appears that the error you’re seeing is a known bug, and can be ignored. I don’t see it in Xcode 9.2. Is this the only error you see? Are you getting any of the print messages from the getLocation function? Can you post your Photon code where you define your variables and declare the Particle.variable?

One other problem. You’re calling connectToDevice twice; once from loginButtonPressed, and then again from within the login function. You should delete the one in loginButtonPressed; it could be that by calling it there, you may be trying to connect to the device before the login function completes (since it’s an asynchronous method).

So if I change all of the SparkDevice and SparkClouds to ParticleDevice and ParticleCloud, do I have to change the library that I import in the header file from SparkCloud.h to ParticleCloud.h? Because I get an error when I change this line:

var myPhoton: SparkDevice!

to

var myPhoton: ParticleDevice!

I get an error saying that ParticleDevice is an undeclared type.

Also, I am not getting any debug messages from the getLocation() function. All I get is the “Attempting to get the location”

I am very new to Xcode, so if some of these questions have obvious answers, please bear with me.

Thanks!

I’ve been looking at it for a little bit now and I think I might know what the problem is. Like you said, I might be using an older version of the SDK. I’m using the SparkCloud SDK, but I think I need to use the Particle-SDK one. Is this right? If so do you know how I would get that newest SDK?

I think you can get the newest version of the Particle iOS SDK here. It’s probably ok to stick with the version you have, at least for a while, to try and figure out why it’s not working. The fact that you don’t get either of the other two print statements in the getLocation function is puzzling. Is anything else happening at that point? Is Xcode crashing, and giving you the error you originally posted above, or does that error come earlier? Have you tried waiting for 30-60 seconds after you click the button to get the location to see if another error comes up?

Xcode doesn’t crash at all. I added the line print(“TEST”), as seen here:

func getLocation() {
    if self.loggedIn == true {
        print("Attempting to get the location")
        myPhoton!.getVariable("L", completion: { (result:Any?, error:Error?) -> Void in
            if let _ = error {
                print("Failed reading location from device")
            }
            else {
                if let location = result as? NSNumber {
                    print("Location is \(location.stringValue)")
                    self.locationLabel.text = location.stringValue
                }
                print("TEST")
            }
        })
    }
}

Now it prints “Attempting to get the location” and then about 3 seconds later it prints “TEST”

Then after about 15-20 seconds it prints that error again.

In my bridging header I am importing "Spark-SDK"
I’m not sure if I should be using a different one or if it matters…

Thanks again!

Ok, so it’s entering the else clause, but apparently, the “if let” line is not working correctly. Try adding a print statement as the first line in the else clause: print(“result is: \(result)”) and see what that gives you.

Well that worked! It printed the value of the variable! I am still getting the error messages though. I’m not sure if those matter.

Thanks!

I think you can ignore those errors. They’ll probably go away if you update to the latest version of Mac OS and Xcode. The fact that the simple print works, means that the result you’re getting from the Photon cannot be cast to an NSNumber. How is your variable declared in your .ino file?

It’s defined as a string

Ok, that's why that line isn't working then. Try the following instead, and see if that works,

if let location = result as? String {
       print("Location is \(location)")
       self.locationLabel.text = location
}

Yup that works now! So the only problem was the type of variable it was using haha. Thank you for all the help!