How to use Alamofire with Codable in Swift?

Hello after long time I am writing this blog regarding use of Alamofire with Codable model object for the ease of MVC architecture.

Let’s rewind with some of the post which is used to cover this point:

  1. How to use Alamofire and SwiftyJSON with Swift?
  2. How to create a wrapper for Alamofire and SwiftyJSON?
  3. Use of Codable and Coding Key with JSONEncoder and JSONDecoder in Swift 4

Let see about use of Alamofire with Codable model object

Step 1 – Create Codable object based on JSON response.

Here I am taking an example of a web service which contains JSON related to the contact.

So, we can create two Codable files from this JSON as per hierarchy. These would be like as follows:

As you can see we have created 2 objects Contact and Phone. Here Phone is in sub hierarchy.

Step 2 – Let’s update AFWrapper

As we have previously revised blogs, there is a blog mentioned about to create a wrapper of the Alamofire and SwiftyJSON. We have to replace the SwiftyJSON code to return normal dictionary objects, and after that we will convert that dictionary to the Codable object.

So here I have updated the AFWrapper class file to do that thing:

Step 3 – Implement and convert the response in object

We will call a web service which contain that kind of JSON response. And after calling the web-service we will decode the object to create the Codable object.

In above sample I have added one text view in the view controller and I am fetching the data from the contacts API. After that using JSONSerialization and JSONDecoder we will get our decoded Contact object with Phone object.

Conclusion

Swift 4 comes with so many updates. We are going to have a great time exploring them all and finding out so much more by using it on further projects. We have learned about Codable and use of it. You too should go check it out and share your experiences with us in the comments section.

Hope you liked the article.

Happy Coding 🙂

How to create a wrapper for Alamofire and SwiftyJSON? Swift – iOS

This blogpost updated with Swift 3 – Xcode 8 – iOS 10 – Alamofire 4.0

AFWrapper
AFWrapper

I have posted a basic tutorial about Alamofire and SwiftyJSON How to use Alamofire and SwiftyJSON with Swift?

And some day before we have learned about Use of Blocks(Closures) or Completion Handlers with Function in Swift – iOS

Let’s combine both the topics to make a WRAPPER of Alamofire and SwiftyJSON.
Continue reading

How to use Alamofire and SwiftyJSON with Swift? – Swift 3 – iOS 10 – Xcode 8

Swift JSON
Swift JSON

Alamofire is an HTTP networking library written in Swift.
SwiftyJSON makes it easy to deal with JSON data in Swift.
Continue reading

Google Place Autocomplete View With Swift Language through Alamofire networking library

Google Place Autocomplete
Google Place Autocomplete

Add the Alamofire CocoaPods in your swift project.

alamofire
alamofire

Find your Google place API key on Google APIs Console.

GOOGLE PLACE API KEY
GOOGLE PLACE API KEY

ViewConroller.swift

import UIKit

class ViewController: UIViewController {
  override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let gpaViewController = GooglePlacesAutocomplete(
      apiKey: "YOUR API KEY",
      placeType: .Address
    )

    gpaViewController.placeDelegate = self

    presentViewController(gpaViewController, animated: true, completion: nil)
  }
}

extension ViewController: GooglePlacesAutocompleteDelegate {
  func placeSelected(place: Place) {
    println(place.description)
  }

  func placeViewClosed() {
    dismissViewControllerAnimated(true, completion: nil)
  }
}

GooglePlacesAutocomplete.xib

GooglePlacesAutocomplete.xib
GooglePlacesAutocomplete.xib

GooglePlacesAutocomplete.swift

import UIKit
import Alamofire

enum PlaceType: Printable {
  case All
  case Geocode
  case Address
  case Establishment
  case Regions
  case Cities

  var description : String {
    switch self {
    case .All: return ""
    case .Geocode: return "geocode"
    case .Address: return "address"
    case .Establishment: return "establishment"
    case .Regions: return "regions"
    case .Cities: return "cities"
    }
  }
}

struct Place {
  let id: String
  let description: String
}

protocol GooglePlacesAutocompleteDelegate {
  func placeSelected(place: Place)
  func placeViewClosed()
}

// MARK: - GooglePlacesAutocomplete
class GooglePlacesAutocomplete: UINavigationController {
  var gpaViewController: GooglePlacesAutocompleteContainer?

  var placeDelegate: GooglePlacesAutocompleteDelegate? {
    get { return gpaViewController?.delegate }
    set { gpaViewController?.delegate = newValue }
  }

  convenience init(apiKey: String, placeType: PlaceType = .All) {
    let gpaViewController = GooglePlacesAutocompleteContainer(
      apiKey: apiKey,
      placeType: placeType
    )

    self.init(rootViewController: gpaViewController)
    self.gpaViewController = gpaViewController

    let closeButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Stop, target: self, action: "close")

    gpaViewController.navigationItem.leftBarButtonItem = closeButton
    gpaViewController.navigationItem.title = "Enter Address"
  }

  func close() {
    placeDelegate?.placeViewClosed()
  }
}

// MARK: - GooglePlaceSearchDisplayController
class GooglePlaceSearchDisplayController: UISearchDisplayController {
  override func setActive(visible: Bool, animated: Bool) {
    if active == visible { return }

    searchContentsController.navigationController?.navigationBarHidden = true
    super.setActive(visible, animated: animated)

    searchContentsController.navigationController?.navigationBarHidden = false

    if visible {
      searchBar.becomeFirstResponder()
    } else {
      searchBar.resignFirstResponder()
    }
  }
}

// MARK: - GooglePlacesAutocompleteContainer
class GooglePlacesAutocompleteContainer: UIViewController {
  var delegate: GooglePlacesAutocompleteDelegate?
  var apiKey: String?
  var places = [Place]()
  var placeType: PlaceType = .All

  convenience init(apiKey: String, placeType: PlaceType = .All) {
    self.init(nibName: "GooglePlacesAutocomplete", bundle: nil)
    self.apiKey = apiKey
    self.placeType = placeType
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    let tv: UITableView? = searchDisplayController?.searchResultsTableView
    tv?.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
  }
}

// MARK: - GooglePlacesAutocompleteContainer (UITableViewDataSource / UITableViewDelegate)
extension GooglePlacesAutocompleteContainer: UITableViewDataSource, UITableViewDelegate {
  func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return places.count
  }

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.searchDisplayController?.searchResultsTableView?.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell

    // Get the corresponding candy from our candies array
    let place = self.places[indexPath.row]

    // Configure the cell
    cell.textLabel.text = place.description
    cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator

    return cell
  }

  func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    delegate?.placeSelected(self.places[indexPath.row])
  }
}

// MARK: - GooglePlacesAutocompleteContainer (UISearchDisplayDelegate)
extension GooglePlacesAutocompleteContainer: UISearchDisplayDelegate {
  func searchDisplayController(controller: UISearchDisplayController, shouldReloadTableForSearchString searchString: String!) -> Bool {
    getPlaces(searchString)
    return false
  }

  private func getPlaces(searchString: String) {
    Alamofire.request(.GET,
      "https://maps.googleapis.com/maps/api/place/autocomplete/json",
      parameters: [
        "input": searchString,
        "type": "(\(placeType.description))",
        "key": apiKey ?? ""
      ]).responseJSON { request, response, json, error in
        if let response = json as? NSDictionary {
          if let predictions = response["predictions"] as? Array<AnyObject> {
            self.places = predictions.map { (prediction: AnyObject) -> Place in
              return Place(
                id: prediction["id"] as String,
                description: prediction["description"] as String
              )
            }
          }
        }

        self.searchDisplayController?.searchResultsTableView?.reloadData()
    }
  }
}

I have learned this thing from Howard Wilson’s(watsonbox) Github Repository : watsonbox/ios_google_places_autocomplete

Happy coding 🙂