New swift guy here! I'm having problems conceptualizing how to store this information of a location with multiple details. Is user defaults the best way? Perhaps json array file?
I've got two view controllers 1. favorites and 2. info.
FavoritesViewController displays multiple groups of data in the order in which they were favorited like this
Favorites
Group 1 Remove button
- Name of location
- Address
- latitude
- longitude
- Hours
then continues groups
On the infoViewController it shows locations from a database. It has a favorite button which stores it for use in the favoritesViewController.
@IBAction func favoriteThis(_ sender: Any) {
// check the state of favorited button
if toggleState == 1 {
toggleState = 2
favoriteThis.setTitle("favorited!", forState: .normal)
UserDefaults.standard.set(toggleState, forKey: "favorited")
} else {
toggleState = 1
favoriteThis.setTitle("favorite", forState: .normal)
UserDefaults.standard.set(toggleState, forKey: "favorited")
}
//set the current values to variables
let name = self.selectedLocation!.name
let address = self.selectedLocation!.address
let lat = self.selectedLocation!.latitude
let long = self.selectedLocation!.longitude
// set them to an array and store them with a unique id
let array = [id, name, address, lat, long]
let defaults = UserDefaults.standard
defaults.set(array, forKey: "FavArray")
}
This does store in the FavArray, but if I need to save and display more than one of these groups in favoriteViewController, What do you think is a better solution to approaching this?
Thanks everyone!
UserDefaults is meant for small pieces of data. So instead of using User defaults, I would recommend making your custom PList file (You can think of it as your custom UserDefaults file) special for your array of custom Types.
To solve your problem I created a custom Type which will hold all your location data like so: -
struct FavoriteLocation: Codable {
let name: String
let address: String
let latitude:CLLocationDegrees
let longitude: CLLocationDegrees
init(name: String,address: String, latitude: CLLocationDegrees,longitude: CLLocationDegrees) {
self.name = name
self.address = address
self.latitude = latitude
self.longitude = longitude
}
}
NOTE: Your Custom type should conform to Codable protocol so that it can be encoded and decoded to and from Custom Plist file.
NEXT:- In your ViewController you can populate an array of this type and use it to save as well as retrieve data from your customPList file. I have summarized everything in a ViewController with Comments as shown below. Let me know if you don't understand any part of it.
class CustomPListViewController: UIViewController {
/// Make your array of Favorite Locations
let favLocationArray:[FavoriteLocation] = []
/**
Create our own directory to save data locally in a custom Plist file, inside our apps Document directory.
This is used both when writing and retrieving.
*/
let dataFilePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("FavoriteLocations.plist")
/// Save your array in custom PList file (Encode)
func saveFavoritePLacesInCustomPList(favLocationArray: [FavoriteLocation]) {
let encoder = PropertyListEncoder()
do {
let data = try encoder.encode(favLocationArray)
guard let dataFilePath = self.dataFilePath else { return }
do {
try data.write(to: dataFilePath)
} catch {
// Handle error
}
} catch {
// Handle error
}
}
// Retrieve your saved data (Decode)
func retrieveFavoriteLocations() {
guard let filePath = self.dataFilePath else {return }
do {
let data = try Data(contentsOf: filePath)
let decoder = PropertyListDecoder()
do {
let favoriteLocationsArray = try decoder.decode(Array<FavoriteLocation>.self, from: data)
// This is your data ready to use
print(favoriteLocationsArray)
} catch {
// Handle error
}
} catch {
// Handle error
}
}
}
How does it work?
We are using PropertyListEncoder
to encode
ie to transform your custom object into a format which can be saved in .plist file. and to get your data back to your app's model (FavoriteLocation
) we use PropertyListDecoder
which does the opposite ie decode
.plist formatted data back to your custom Object.
How to view your custom .plist file?
On your viewDidLoad
method call print(dataFilePath!)
This will print the full file path which you can naviagate to it and see your FavoriteLocations.plist