I am fairly new to Swift and I am using Adafruit's Basic Chat iOS app https://github.com/adafruit/Basic-Chat that uses BLE and I am adding my own viewController and pushing that instead of the one Adafruit provides. My ViewController (ServoViewController) appears as expected.
I am communicating with an Arduino over BLE and receiving data from the Arduino and am parsing the relevant part (and printing to terminal) the data in the BLECentralViewController file.
I have set up a String variable outside of the BLECentralViewController class (so from my understanding it should be global). I read data into that variable in the BLECentralViewController and again print it successfully.
I then try to use that String variable to populate a textField in my viewController, however the textField never gets written to.
In the BLECentralViewController file I have the variables declared outside of the class like this:
var dataReceived: String = ""
public var batteryVal: String = "" // global variable
I check the incoming data from the Arduino. If it contains the String "Battery" I know it is the battery data. I can receive and get the substring (the battery %) and print it to the terminal.
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic == rxCharacteristic {
if let ASCIIstring = NSString(data: characteristic.value!, encoding: String.Encoding.utf8.rawValue) {
characteristicASCIIValue = ASCIIstring
print("Value Received: \((characteristicASCIIValue as String))")
dataReceived = (characteristicASCIIValue as String)
if dataReceived.contains("Battery:") {
print ("Battery value: ", dataReceived)
print("Substring: ", dataReceived.substring(from: 8))
batteryVal = dataReceived.substring(from: 8)
print("Printing batteryVal: ", batteryVal)
}
NotificationCenter.default.post(name:NSNotification.Name(rawValue: "Notify"), object: nil)
cvcrd.reportValvePosition()
}
}
}
In my viewController (ServoViewController) I have the following function
func reportBatteryPercent() {
// print battery value here
batteryField.text = batteryVal
print("Reporting Battery Percentage here...", batteryVal)
}
To start with I just wanted to populate the textField when ServoViewController first loads, so I called reportBatteryPercent() in viewDidLoad(). In the terminal output window I see that "Reporting Battery Percentage here..." appears, but there is no value printed in the terminal output for batteryVal and batteryField.text is empty.
Since I am pushing my ServoViewController there is no segue, so I figured a global variable would be an easy way to access that data. What am I doing wrong with accessing the global variable from my viewController?
EDIT: As per recommendations I have put the reportBatteryPercent() in viewWillAppear like this:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
reportBatteryPercent()
}
However the data still doesn't print when in the ServoViewController. I tried changing the declaration of the String from:
public var batteryVal: String = ""
to:
public var batteryVal: String = "999"
and now it prints 999 in the textField. So the problem now seems to be ServoViewController reading the batteryVal string after it has been updated by the BLECentralViewController
EDIT 2: I have confirmed the above my going back to the first viewController (BLECentralViewController) and then returning to the second viewController (ServoViewController). The correct value is now displayed.
I am away from my Apple machine now, but perhaps I could fix this by when I go to push the second ViewController, I could see if the value of interest is an empty string and sleep for a second? Would this sleep the main thread? If so how would I sleep the thread that is doing the push of the viewController?