Asynchronous Networking Callbacks January 11, 2017

Here I am making a network request with a callback response object, where the innerds of the closure will not be called until the network request comes back.

            
          let url = "http://robbroadwell.com/api/spanish.json"
          
          // #1 - Attempt to download collections from API
          networkRequest(withUrl: url) { response, error in
              if error == nil {
                  print("Collections downloaded from API.")
                  print("Loading from fresh JSON...")
                  let json = JSON(data: response!)
                  self.updateCollectionsFromJSON(json)
                  
              } else {
                  // #2 - If that fails, attempt to load from NSUserDefaults
                  print("Unable to download from API.")
                  print("Attempting to load from NSUserDefaults...")
                  let loaded: Bool = self.load()
                  if !loaded {
                      
                      // #3 - As worst cast scenario use bundled collections
                      print("Unable to load from NSUserDefaults.")
                      print("Loading bundled collections...")
                      self.getBundledCollections()
                  }
              }
             
          

Alamofire handles the network request, and returns a response object with optionals for response (of type Data?) or error (of type NSError?).

            
      func networkRequest(withUrl url: String, completionHandler: @escaping (Data?, NSError?) -> ()) {
          Alamofire.request(url).responseJSON { response in
              switch response.result {
              case .success:
                  completionHandler(response.data!, nil)
              case .failure(let error):
                  completionHandler(nil, NSError())
              }
          }
      }
      
          

A breakdown of the full process, with each step along the way. The first process will make the network request, if it comes back as failure then it will attempt to load in from NSUserDefaults. If that fails, it will load from a static JSON file.

            
      // #1 - Attempt to download collections from API
      networkRequest(withUrl: url) { response, error in
          // stuff inside here will not happen until either
          // a response or an error comes back from the API
          if error == nil {
              // if the request worked, the error will be nil
              print("Collections downloaded from API.")
              print("Loading from fresh JSON...")
              // and you can update your data model with the new data
              let json = JSON(data: response!)
              self.updateCollectionsFromJSON(json)
              
          } else {
              // #2 - If that fails, attempt to load from NSUserDefaults
              // (see my last post about Persisting Data in NSUserDefaults)
              print("Unable to download from API.")
              print("Attempting to load from NSUserDefaults...")
              let loaded: Bool = self.load()
              if !loaded {
                  
                  // #3 - As worst cast scenario use bundled collections
                  // This is just default data, hardcoded into the app bundle
                  print("Unable to load from NSUserDefaults.")
                  print("Loading bundled collections...")
                  self.getBundledCollections()
              }
          }
      }

          

That's it! Have fun and #CompileSwift.