I would like to save/store user's current location but don't know which specific data I should store in DB and what should my database structure be? I would like to retrieve the location information and display it back on the map view. What's the best approach to achieve this? Regarding the database structure, should I have separate latitude and longitude columns on my database table?
You can save it as NSData using NSKeyedarchiver and NSKeyedUnarchiver as follow:
let locationData = NSKeyedArchiver.archivedDataWithRootObject(yourLocation)
NSUserDefaults.standardUserDefaults().setObject(locationData, forKey: "myLocation")
if let loadedData = NSUserDefaults.standardUserDefaults().dataForKey("myLocation") {
if let loadedLocation = NSKeyedUnarchiver.unarchiveObjectWithData(loadedData) as? CLLocation {
println(loadedLocation.description)
}
}
You should store latitude and longitude as separate columns.
If you archive the location into an object that contains both values you can't access the individual values on the database level. You have to get the object and extract latitude and longitude from it.
While saving latitude and longitude in individual colums makes your code a couple of lines longer you have the advantage that you can use the coordinates in a database query.
Related
I followed a tutorial on how to parse from a JSON file and preload a sqlite database according to this:
https://medium.com/#jamesrochabrun/parsing-json-response-and-save-it-in-coredata-step-by-step-fb58fc6ce16f
In this method the parsed data, which is an array of dictionaries, gets mapped:
private func saveInCoreDataWith(array: [[String: AnyObject]]) {
_ = array.map{self.createPhotoEntityFrom(dictionary: $0)}
do {
try CoreDataStack.sharedInstance.persistentContainer.viewContext.save()
} catch let error {
print(error)
}
}
And in this method the mapped data gets inserted one by another into the database file:
private func createPhotoEntityFrom(dictionary: [String: AnyObject]) -> NSManagedObject? {
let context = CoreDataStack.sharedInstance.persistentContainer.viewContext
if let photoEntity = NSEntityDescription.insertNewObject(forEntityName: "Photo", into: context) as? Photo {
photoEntity.author = dictionary["author"] as? String
photoEntity.tags = dictionary["tags"] as? String
let mediaDictionary = dictionary["media"] as? [String: AnyObject]
photoEntity.mediaURL = mediaDictionary?["m"] as? String
return photoEntity
}
return nil
}
I noticed, that the data gets inserted in an unsorted manner and not according to the sorted way the array is prior of being inserted.
Normally this would not bother me when I would only have one entity. However in my project I have 3 entities and different relationships between them. Therefore I also need to set foreign keys into the tables. But this is not possible, since I don’t know which primary keys are going to be set initially when inserting the data into the tables.
Is there a way to tell SWIFT to insert the data sorted or at least according to the sorted array ? Or is there another way to determine the correct foreign keys when inserting into the table?
The only order in Core Data is the order you tell it about. Ordering is not automatic. In most cases it's better to use a sort descriptor when fetching data, so that you can get fetch results sorted by a property of the entity (sorted by date, for example). If you need to force a specific order, your entity needs to have a property that indicates the order. Add an extra integer field called sortOrder and give it whatever values you like. Then have your sort descriptor sort using the sortOrder field.
Related, your question applies SQL concepts to Core Data in ways that don't make sense. Expecting an auto-incrementing index, for example. Wanting to use foreign keys for relationships as well. Core Data uses SQLite internally but it doesn't work like SQL, and thinking of it as SQL will lead you into bad design decisions like using foreign keys. If you really want SQLite, you can use it directly without Core Data. If you're going to use Core Data, you'll benefit from reading up on how it works instead of treating it like SQL.
CoreData insertion doesn't guarantee storing order of managed objects. To keep order of Your records You need to create custom field responsible for order and perform sorting while fetching.
I'm a new programmer. I know how to get the latitude/longitude and how to save items in core data, but I'm not sure how to save latitude and longitude.
https://www.youtube.com/watch?v=GeM7Zw12wbM
I've been watching this tutorial because I want a similar app, but I want to save latitude and longitude too. Any ideas how to do this?
CoreData supports a wide range of number size values. Apple's preferred data type to store latitude and longitudinal values is a CLLocationDegrees object, which has a typealias of Double. So you would store your latitude and longitude values as Double's inside CoreData.
In terms of how your CoreData NSManagedObjectModel should be set up, it would make the most sense to save the coordinates by location. In this case you would have two entities: a location entity with a name property that stores the location as a string, and a coordinate entity with both a latitude and longitude property that stores their corresponding values as a Double. You would need to create a "one to many" relationship linking your location to your coordinates.
Then to retrieve your coordinates you would send a fetch request to your location entity and then simply retrieve each location of type NSManagedObject's corresponding coordinates.
You said you were a new programmer, so know that CoreData is not something to be taken lightly. I recommend you read through Apple's programming guide for Core Data as it explains how to set up your CoreData stack, NSManagedObjectModel, and how to create relationships between two entities; Which I am thinking you will most likely need to relate your location to your coordinates. Good Luck.
Core Data Programming Guide
I'm trying to make something where you search for something and it shows the locations a map. I am wondering if there is a way to get a unique id for a location (using mapkit and corelocation) so that I can store it for later. After that, when someone searches some locations and the one with the id that is saved is there, I do something else
Basically I need to get a unique id for a certain location to do something to it later. Right now I'm using the latitude and longitude, but I was wondering if there is a better way.
I think you might want to look into MKAnnotation. That way you can create an annotation for each location you want to save and then later retrieve them.
From the MKAnnotation docs:
The MKAnnotation protocol is used to provide annotation-related
information to a map view. To use this protocol, you adopt it in any
custom objects that store or represent annotation data. Each object
then serves as the source of information about a single map annotation
and provides critical information, such as the annotation’s location
on the map. Annotation objects do not provide the visual
representation of the annotation but typically coordinate (in
conjunction with the map view’s delegate) the creation of an
appropriate MKAnnotationView object to handle the display.
A position is identified by its latitude and longitude (and altitude if you consider 3 dimensions).
When you say location, however I assume you mean more than just position. For example, a restaurant and a bar may be at the same position in terms of latitude and longitude, but are different locations when you consider their name, type of business and so on.
If you create a table in Parse to store locations then you can add columns for all of these attributes, and when you save an object to this table, Parse will assign that object a unique identifier. This object is how you will identify and refer to locations in your app.
You can store a position in Parse using a PFGeoPoint, which is simply a convenient way of storing a latitude and longitude (and Parse has support for identifying nearby positions in a query).
For my iOS application, I need to organize a list of Parse objects by their distance from the user's current location. Each of the Parse objects has an attribute for location, but the location is a regular address in the form of an NSString, rather than GPS coordinates or a CLLocation.
I have two questions for this situation:
How do I find the distance between an NSString location and the user's current location?
How do I query for the distance in Parse (for example, only display the objects within 5 miles)?
Thanks for any help!
To perform distance queries, you need a GeoPoint. There are many ways to look up a GeoPoint given a string address.
You could create an Cloud Code after-save method that uses Google to lookup the GeoPoint and add it to the record. Looking up the GeoPoint from a string is an expensive operation, you only want to do this once for each data point when the data changes.
To attempt to find distance based on a string address within a query (would require every record to be evaluated every time) would unfairly tax the geo-lookup facility and probably be a breach of the terms of use.
Once you have an actual GeoPoint in your data then the query is quite easy, as per the documentation:
To limit the results using distance check out whereKey:nearGeoPoint:withinMiles, whereKey:nearGeoPoint:withinKilometers, and whereKey:nearGeoPoint:withinRadians.
I have a list of core data objects each has a longitude and latitude properties.
I have the user location from core location.
I wish to retrieve the nearest object to the user location?
How can I do that?
I'm not going to give you an answer with code as you are only asking a general question.
But, there is a useful function in CLLocation called distanceFromLocation: which has the signature:
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
The way to do this would be to store (or create) create CLLocation objects from the locations in your Core Data store, and using the users current location you can iterate through the list of locations using this function to get the distances and then return the location with the smallest return value as the nearest location.