Best way to show realtime data in iOS with Charts API - ios

I know there are some posts about it but I can't find something useful. Therefore, I'm opening new post. I have a device which sends some values over bluetooth. I have function which gets this value like every second. I need to show this data in line chart realtime (Two line). I know Android API has a function for realtime but I can't find it in iOS API.
How I'm doing now is like this;
if (uuid == kUUIDECGSensor) {
let dataDict: [AnyHashable: Any] = LBValueConverter.manageValueElectrocardiography(dataValue)
// print("kUUIDECGSensor dict: \(dataDict)")
let allValues = Array(dataDict.values)
print(allValues)
data_array1.append(allValues[0] as! Double)
data_array2.append(allValues[1] as! Double)
//print(data_array1)
//print(data_array2)
temp_time += 5
time.append("\(temp_time)")
setChart(dataPoints: time, values: data_array1)
}
It is working but It doesnt seem like realtime. What am I missing?
Thank You!

Related

Which to use, addSnapshotListener() or getDocuments()

I'm a little bit confused about addSnapshotListener and getDocuments. As I read in the firebase docs, getDocuments() is retrieving data once and addSnapshotListener is retrieving in real-time.
What I want to ask.
If I'm using getDocuments, and im changing some documents in the Firestore , it will not make the change in the app ? But if im using addSnapshotListener it will ?
I'm making an delivery app, which is the best to use to store pictures of food , descriptions etc.
This is what im using to retrieve labels and pictures from my app :
db.collection("labels").getDocuments { (snapshot, error) in
if let error = error {
print(error)
return
} else {
for document in snapshot!.documents {
let data = document.data()
let newEntry = Labels(
firstLabel: data["firstLabel"] as! String,
secondLabel: data["secondLabel"] as! String,
photoKey: data["photoKey"] as! String
)
self.labels
.append(newEntry)
}
}
DispatchQueue.main.async {
self.tableViewTest.reloadData()
}
getDocuments will return results one time, with the current Firestore data.
addSnapshotListener will return an initial result set (same as getDocuments) and get called any time that data changes.
If your data is modified in Firestore and you've used getDocuments, your app will not be notified of those changes. For example, in your delivery app, perhaps the item goes out-of-stock while the user is using it. Or, the price gets changed, the user is logged in from another device, etc -- many possibilities for why the data might change. By using a snapshot listener, you'd get notified if any of these changes happen.
However, if you're relatively confident you don't need updates to the data (like getting a user's address from the database, for example), you could opt to just use getDocuments.

Apple Watch input values via scribble only

I'm working on WatchKit App. In this app, there are some fields that the user should fill it,
I searched how to deal with input fields in iWatch, and I found the following code:
presentTextInputController(withSuggestions: ["1"], allowedInputMode: WKTextInputMode.plain) { (arr: [Any]?) in
if let answers = arr as? [String] {
if let answer = answers[0] as? String {
self.speechLabel.setText(answer)
}
}
}
and this code gives me two choices: Diction and scribble, i.e
In my App, I want to support only the scribble not both of them,
I tried to pass withSuggestions parameter as nil, but the app direct me to dictiation, not to scribble.
Is there a way to let the user only use scribble?

Send and receive data from GameCenter: Swift

I'm creating a game that uses GameCenter and I'm trying to send and retrieve data.
This is how I'm sending data: (the function 'sendData' is provided by GameCenter with GameKit)
let nick = GCHelper()
let data = NSData(contentsOfFile: "")
try! nick.match.sendData(toAllPlayers: data as! Data, with: .reliable)
'GCHelper' is a class I'm using that contains many functions for Game Center, a download is further through the questions if you're interested. I just needed to call it to access the function.
Then to retrieve data I'm attempting to use this:
nick.match(GKMatch, didReceive: Data, fromPlayer: String)
Note: I have not filled in any of the above parameters
Here is the function I'm using to retrieve the data:
public func match(_ theMatch: GKMatch, didReceive data: Data, fromPlayer playerID: String) {
if match != theMatch {
return
}
delegate?.match(theMatch, didReceiveData: data, fromPlayer: playerID)
}
The function I'm using 'match()' is apart of the GCHelper class. GCHelper allows for you to create GameCenter game easier. Here is a link in case you want to reference it: https://github.com/jackcook/GCHelper
QUESTION
Now that I've showed you all the methods, how would I use the previous method to retrieve data? One of its parameters is 'fromPlayer' and asks for the playerId(String), but how would I know what the other players playerID is? Better yet, how would I retrieve it?
If you don't think this is a good way to handle retrieving data, how could I do it better? Is there another way to do this?
Key Facts:
The game requires 2 people and data is being exchanged between these 2 people only. I need to know how to send and retrieve data amongst the 2.
Thanks for the help! If you have any questions let me know.
This is the function I'm using to retrieve the data:
open func match(_ theMatch: GKMatch, didReceive data: Data, fromPlayer playerID: String) {
}
Now, the data I'm sending is a string. So I create a variable that unarchives the data and sets it to string format.
let myString = NSKeyedUnarchiver.unarchiveObject(with: data) as! String
After this, I need a way to get that string from the view controller or game center file to my game scene. In which I simply just stored the data using UserDefaults.
let user = UserDefaults.standard
user.set(myString, forKey: "myString")
Then in my SKScene I created a timer, in which it checks every couple of seconds to see if there's a change. It stores the values so that when a new values arrives it can compare and if it is different it does something with it, for example: update player points.
Note: This is what I found to work, someone else may have a better way, but it works fine for me.

Custom Dimensions Swift not showing up in Google Analytics Dashboard

I am trying to send custom dimensions as data from my app to the google analytics dashboard. I have successfully got screenviews and events showing in Google Analytics.
Below is my code for sending the custom dimension
func logScreenTrackingWithCustomDimension(screenName: String, data: AnyObject) {
let customDimension = data
let tracker = GAI.sharedInstance().defaultTracker
tracker.set(GAIFields.customDimensionForIndex(1), value: customDimension as! String)
tracker.set(kGAIScreenName, value: screenName)
tracker.send(GAIDictionaryBuilder.createScreenView().set(customDimension as! String, forKey: GAIFields.customDimensionForIndex(1)).build() as NSDictionary as [NSObject : AnyObject])
}
the function argument "data" is the string value I am passing in from another controller where I call this function.
I have also set up the dimension correctly within google analytics
P.S i am tracking screenviews and events for the above code and they show up in google analytics. Just not the actual data of the dimension which is not being tracked for some reason
Any help would really be appreciated because I am trying to track a product ID when click on a product screen. This will enable me to see what products are being viewed etc.
Thanks
For dimensions, use this:
let customDimension = data as! String
tracker.set(GAIFields.customDimension(for: UInt(indexNo)), value: customDimension)

How do I use a firebase server timestamp, with queryStartingAtValue, to track a user's current actions, for a firebase listener in iOS & Swift

I am developing an iOS app in Swift which has a like feature which is the same concept as liking a Facebook post, a Twitter Tweet etc.
I want to create a listener that only listens to the user liking posts with a timestamp that starts from now. i.e once they open the app. I wanted to use a firebase server timestamp value to get the current timestamp
I have the following structure in my database
"userLikes": {
"$uid":{
"$messageId": {
"timestamp": 1212121212121 // timestamp created using fb server
}
}
}
This was my attempted solution but it doesn't work and the problem I have is to do with -> FIRServerValue.timestamp()
let queryRef = ref.child("userLikes").child(uid).queryOrdered(byChild: "timestamp").queryStarting(atValue: FIRServerValue.timestamp())
queryRef.observe(.childAdded, with: { (snapshot) in
let utterId = snapshot.key
self.newsFeedModel.uttersInfo[utterId]?[Constants.UttersInfoKeys.isLikedByCurrentUser] = true as AnyObject
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}, withCancel: nil)
Any ideas how I Can implement this? Perhaps I should just use NSDate to get the current time for comparison but thought that using a firebase server timestamp would be the optimum way for comparison purposes.
You can estimate the ServerTime by taking the local time and correcting for the clock-skew and latency. The Firebase documentation has a section on Clock Skew.
Clock Skew
While firebase.database.ServerValue.TIMESTAMP is much more accurate, and preferable for most read/write ops, it can occasionally be useful to estimate the clients clock skew with respect to the Firebase Realtime Database's servers. We can attach a callback to the location /.info/serverTimeOffset to obtain the value, in milliseconds, that Firebase Realtime Database clients will add to the local reported time (epoch time in milliseconds) to estimate the server time. Note that this offset's accuracy can be affected by networking latency, and so is useful primarily for discovering large (> 1 second) discrepancies in clock time.
let offsetRef = FIRDatabase.database().referenceWithPath(".info/serverTimeOffset")
offsetRef.observeEventType(.Value, withBlock: { snapshot in
if let offset = snapshot.value as? Double {
let estimatedServerTimeMs = NSDate().timeIntervalSince1970 * 1000.0 + offset
}
})
This will likely work better than purely using a client-side timestamp, since that is likely to be different between clients.
Update for Swift 3/4:
public func getCurrentTime(completionHandler:#escaping (Double) -> ()){
Database.database().reference(withPath: ".info/serverTimeOffset").observeSingleEvent(of: .value) { (snapshot) in
if let time = snapshot.value as? Double{
completionHandler(Date().timeIntervalSince1970 + time)
}else{
completionHandler(0)
}
}
}
Usage:
getCurrentTime(){ (date) in
print(date)
}

Resources