How to store users location on CloudKit in swift? - swift

I'm trying to store a users journey and upload it to CloudKit.
The following takes the users location whenever they move more than 5 meters and uploads as a string but I want it to be uploaded as a location list or similar so it can be pulled down later.
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
addCrumbPoint(center)
let message = "{\"lat\":\(location!.coordinate.latitude),\"lng\":\(location!.coordinate.longitude), \"alt\": \(location!.altitude)}"
let newSweet = CKRecord(recordType: "Sweet")
newSweet["content"] = message
let publicData = CKContainer.defaultContainer().publicCloudDatabase
publicData.saveRecord(newSweet, completionHandler: { (record:CKRecord?, error:NSError?) -> Void in
if error == nil {
print("woo")
}else{
print(error)
}
})
}
The documentation on using Location and CloudKit is written in Objective-C so any help would be brilliant.
CloudKit
CLLocationManager

You create a CKRecordID and a CKRecord. Then you set the last retrieved CLLocation on the CKRecord.
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last!
let id = CKRecordID(recordName: "01")
let locationRecord = CKRecord(recordType: "location", recordID: id)
locationRecord.setObject(location, forKey: "location")
// or locationRecord["location"] = location
let publicData = CKContainer.defaultContainer().publicCloudDatabase
publicData.saveRecord(locationRecord) { record, error in
//
}
}

Related

Calling locationManager within a IBAction function

I'm working on a weather application and I want the user to get data about the weather either by inserting a location or by the current GPS location.
For the GPS location, there is a push button in the interface that can be pressed. At the click of the button, I want to call the locationManager function, but it does not work. Do you think it's something linked with the scope?
I simply put the locationManager function into the IBAction function of the button. That's because I do not know how to call locationManager within IBAction.
class ViewController: UIViewController, CLLocationManagerDelegate {
let key = "d79ac3fea08fac5d21deeabef00*****"
var lat = 11.344533
var lon = 104.33322
let managLoc = CLLocationManager()
#IBAction func locationOption(_ sender: Any, forEvent event: UIEvent) {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
lat = location.coordinate.latitude
lon = location.coordinate.longitude
Alamofire.request("https://api.openweathermap.org/data/2.5/weather?lat=\(lat)&lon=\(lon)&appid=\(key)").responseJSON {
response in
if let responseStr = response.result.value {
let jsonResponse = JSON(responseStr)
let jsonWeather = jsonResponse["weather"].array![0]
let jsonTemp = jsonResponse["main"]
let iconName = jsonWeather["icon"].stringValue
self.locationLabel.text = jsonResponse["name"].stringValue
self.typeView.image = UIImage(named: iconName)
self.typeLabel.text = jsonWeather["main"].stringValue
self.tempLabel.text = "\(Int(round(jsonTemp["temp"].doubleValue-273.15)))"
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE"
self.dayLabel.text = dateFormatter.string(from: date)
}
}
self.managLoc.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
}
Get the locationManager functions out of the action
class ViewController: UIViewController, CLLocationManagerDelegate {
let key = "d79ac3fea08fac5d21deeabef00*****"
var lat = 11.344533
var lon = 104.33322
let managLoc = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
managLoc.delegate = self
}
#IBAction func locationOption(_ sender: Any, forEvent event: UIEvent) {
self.managLoc.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations[0]
lat = location.coordinate.latitude
lon = location.coordinate.longitude
Alamofire.request("https://api.openweathermap.org/data/2.5/weather?lat=\(lat)&lon=\(lon)&appid=\(key)").responseJSON {
response in
if let responseStr = response.result.value {
let jsonResponse = JSON(responseStr)
let jsonWeather = jsonResponse["weather"].array![0]
let jsonTemp = jsonResponse["main"]
let iconName = jsonWeather["icon"].stringValue
self.locationLabel.text = jsonResponse["name"].stringValue
self.typeView.image = UIImage(named: iconName)
self.typeLabel.text = jsonWeather["main"].stringValue
self.tempLabel.text = "\(Int(round(jsonTemp["temp"].doubleValue-273.15)))"
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE"
self.dayLabel.text = dateFormatter.string(from: date)
}
}
self.managLoc.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
}

distance between current location and updated location

i want to get the distance between two location.
first location is my current location and the other location is the user updated location.
so, how to track user location and measure the distance between the current location and user updated location
i tried this code and the measure is not true.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let loc = locations.last else {return}
guard let startLocation = startLocation else {
self.startLocation = loc
return
}
guard let current = manager.location else { return }
let distance = current.distance(from: startLocation)
print("Distance: \((distance))")
}

Swift 4 MapKit check if mark is near to my location

I want to check when my position is changing if my location is near the Mark. I have marks with unique position. If i near for example 10m from mark i want to display alert. How i can do that?
Get visible annotations.
Calculate distance between your position and the mark.
e.g.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let myLocation = locations.first else { return }
let annotationSet = mapView.annotations(in: mapView.visibleMapRect)
for annotation in annotationSet {
guard let annotation = annotation as? MKPointAnnotation else { continue }
let loc = CLLocation(latitude: annotation.coordinate.latitude,
longitude: annotation.coordinate.longitude)
let distance = myLocation.distance(from: loc)
if distance < 10.0 { Show Alert }
}
}
}
You can implement this delegate from CLLocationManager:
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let myLoc:CLLocationCoordinate2D = manager.location!.coordinate
let distance : CLLocationDistance = mark1.distanceFromLocation(myLoc)
if distance < 10.0 { //Show Alert }
}

Swift using a variable in another function

How can I call testArray from locationManager() in callTestArray() ?
I tried outputting it but that doesn’t seem to work. I also tried to declare at the top of my class but then it’s always nil.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let userLocation:CLLocation = locations[0] as CLLocation
let rootRef = Database.database().reference()
let geoRef = GeoFire(firebaseRef: rootRef.child(“X”))
let query = geoRef.query(at: userLocation, withRadius: 1000)
query.observe(.keyEntered, with: { key, location in
self.testArray.insert(key, at: self.testArray.count)
})
}
func callTestArray() {
var testOuput = testArray[0]
}
Try this approach:
func locationManager(_ manager: String, didUpdateLocations locations: String, completion: #escaping () -> Void) {
let userLocation:CLLocation = locations[0] as CLLocation
let rootRef = Database.database().reference()
let geoRef = GeoFire(firebaseRef: rootRef.child(“X”))
let query = geoRef.query(at: userLocation, withRadius: 1000)
query.observe(.keyEntered, with: { key, location in
self.testArray.append(key)
completion()
})
}
Usage:
locationManager(XXXXXX, didUpdateLocations: YYYYYY) {
callTestArray()
}

Fetch CloudKit records from current iCloud user

I want to fetch all of the location records from a user that is currently logged in.
This creates the location record on CloudKit:
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last!
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
addCrumbPoint(center)
let locationRecord = CKRecord(recordType: "location")
locationRecord["location"] = location
let publicData = CKContainer.defaultContainer().publicCloudDatabase
publicData.saveRecord(locationRecord) { record, error in
}
}
But how would I go about pulling out the location records for only the currently logged in user?
I want to use this to create a breadcrumb of previous journeys on a map but just getting it to print a list would be a great start!
Here is my code so far:
func getLocationAsync(complete: (instance: CKRecordID?, error: NSError?) -> ()) {
let container = CKRecordID(recordName: "Location")
publicDB.fetchRecordWithID(location) { fetchedLocation, error in
if error != nil {
print(error!.localizedDescription)
complete(instance: nil, error: error)
} else {
print("fetched Location \(recordID?.recordName)")
complete(instance: recordID, error: nil)
}
}
}
If your goal is to save the breadcrumbs locations of an user and not sharing it to other users, then use the private database.
Like that you can retrieve all the location records of the user.
If you want to use the public DB, then add an entry of type CKReference to the Location record pointing to the user record. So that you can use a predicate based on the user recordID