Storing a user-selected location in LocationViewController

At present, LocationDataManager loads data from Locations.plist and stores location information in an array of strings. You will create a new structure, LocationItem, and configure LocationDataManager to use it to store a location. After that, you'll modify LocationViewController so that it can store a LocationItem instance containing the location selected by the user. You can then pass this LocationItem instance to the other view controllers in your project. Perform the following steps:

  1. Right-click on the Model folder inside the Location folder and select New File.
  2. iOS should already be selected. Choose Swift File and then click Next.
  3. Name this file LocationItem. Click Create.
  4. Click the LocationItem.swift file in the Project navigator.
  5. Add the following under the import statement to declare and define the LocationItem structure:
struct LocationItem {
var state: String?
var city: String?
}

extension LocationItem {
init(dict: [String:AnyObject]) {
self.state = dict["state"] as? String
self.city = dict["city"] as? String
}

var full: String {
guard let city = self.city, let state = self.state else { return "" }
return "(city), (state)"
}
}

As you can see, LocationItem has two properties, city and state, which are both strings.

The init() method in the extension takes a dictionary, dict, as a parameter and assigns the value of the state and city keys to the state and city properties.

The full computed property returns a string made from combining the state and city values.

Next, you will update LocationDataManager so that it can store city and state information in an array of LocationItem instances instead of strings.

  1. Click LocationDataManager.swift in the Project navigator and modify the locations property declaration, as shown:
private var locations:[LocationItem] = []

So, locations now stores LocationItem instances instead of strings.

  1. The fetch() method will now show an error. Modify the fetch() method as shown:
func fetch() {
for location in loadData() {
locations.append(LocationItem(dict: location))
}
}

The fetch() method now gets each dictionary provided in the loadData() method and uses it to initialize LocationItem instances, which are appended to the locations array. Note that loadData() still uses the same Locations.plist file that you added in an earlier chapter.

  1. The locationItem(at:) method now shows an error. Modify it as follows:
func locationItem(at index:IndexPath) -> LocationItem {
return locations[index.item]
}

Now, this method returns a LocationItem instance instead of a string. You are done with LocationDataManager at this point. Next, you need to update LocationViewController:

  1. Click LocationViewController.swift in the Project navigator.
  2. You will see an error in the tableView(_:cellForRowAtIndexPath:) method. This error is because you can't assign a LocationItem instance to the cell's textLabel, which is a string. Modify tableView(_:cellForRowAtIndexPath:) as follows: 
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:
"locationCell", for: indexPath) as UITableViewCell
cell.textLabel?.text = manager.locationItem(at:indexPath).full
return cell
}

The full property of LocationItem returns a string that combines a location's city and state strings, so this fixes the error.

  1. Now, you need a property to keep track of the user's selection. Add the following property declaration just below the manager declaration:
var selectedCity:LocationItem?

Next, you need to adopt the UITableViewDelegate protocol. You learned about this in Chapter 15, Getting Started with Table Views. This protocol specifies the messages that a table view will send to its delegate when the user interacts with the rows in it.

  1. Add the following after the UITableViewDataSource extension to adopt UITableViewDelegate protocol:
//MARK: UITableViewDelegate
extension LocationViewController: UITableViewDelegate {

}

The //MARK: syntax makes this extension easy to find in the Editing area, and the extension helps to organize code within this class.

  1. The UITableViewDelegate method is triggered when a user taps a row in the table view is tableView(_:didSelectRowAt:). Add this method between the extension's curly braces. It should look like the following:
//MARK: UITableViewDelegate
extension LocationViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt
indexPath:IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark
selectedCity = manager.locationItem(at:indexPath)
tableView.reloadData()
}
}
}

You are done with LocationDataManager at this point. Now you need to modify locationCell.

When the user taps a row in the Locations screen, a checkmark will appear in that row, and the selectedCity property is assigned the corresponding LocationItem instance in the locations array of LocationDataManager. For example, if you tap the third row, the LocationItem instance containing the string Charleston, NC is assigned to selectedCity.

For the checkmark to be visible, you need to update the attributes of locationCell in Main.storyboard. Do the following:

  1. Click Main.storyboard in the Project navigator.
  2. In the document outline, select locationCell in the Location View Controller Scene.
  1. In the Attributes inspector, under Table View Cell, set Selection and Accessory to None:

LocationViewController can now store the location selected by the user, but when the user selects a location in the Locations screen and taps Done, nothing happens. You will need to create an unwind action in ExploreViewController and assign it to the Done button to go back to the Explore screen. Before you do that, you'll add a view controller for the collection view section header in the next section, so you can display the user-selected location in the collection view section header's label.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.192.3