dilluns, 20 de febrer del 2017

Asynchronous task in iOS. Completion Handlers

Recently I started to develop apps for iOS, and my first step was to port an app that I have for Android. During the implementation I encountered the same problem which in Android I solved with AsyncTask, but how to solve it in iOS?

Say that the programming language used is Swift 2.0 because my system is Mavericks and last version of Xcode is the 7.2.1

Well having said that, we continue. Making a little memory, I will remember the problem. It consist in a JSON request and wait the data. For that, an easy and quickly way to do it is use completion handlers.

A completion handler is a closure and the template is as that


   {(data: NSData!, response: NSURLResponse!, error: NSError!) in 

            // code
   }

And to use it


   let task = session.dataTaskWithRequest(request: NSURLRequest, 
                completionHandler: {(data, response, error) in 
         
                //code

              })

   task.resume()       



In the body of the closure, first check if an error has ocurred

   guard error == nil else {
      print (error!)
      return
   }


Next check if we have data

   guard let jsonData = data else {
      print("Error retriving data")
      return
   }


And finally obtains the data


   do {
      let json: AnyObject = 
                  try NSJSONSerialization.
                  JSONObjectWithData(jsonData, options: .AllowFragments)

      let desc = 
          json[2]!.description.dataUsingEncoding(NSUTF8StringEncoding)

      self.description = 
          NSString(data: desc!, encoding: NSUTF8StringEncoding)

      let set = NSCharacterSet(charactersInString: "()")

      self.description = 
          self.description.stringByTrimmingCharactersInSet(set)
   } catch {
      print("Error JSON: \(error)")
   }


And to update te UI first should return to the main thread for this you can used semaphores. First we create the semaphore

   let semaphore = dispatch_semaphore_create(0)


In the body of completion handler we send the signal

   dispatch_semaphore_signal(semaphore)


And after launch the task waits for a semaphore

   dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)


Finally the function to get description look as this
   func getDescription (var name: String){
        
        name = name.stringByReplacingOccurrencesOfString(" ", 
                                                   withString: "%20")
        
        let semaphore = dispatch_semaphore_create(0)
        
        let lang: String = self.lang as! String
        let url: String = "https://" + lang + wikiURL + 
                            "?action=opensearch&search=\(name)&
                             limit=1&explaintext&format=json"
        
        
        
        let url1: NSURL = (NSURL(string: url))!
        let request: NSURLRequest = NSURLRequest(URL: url1)
        let config = NSURLSessionConfiguration.defaultSessionConfiguration()
        let session = NSURLSession(configuration: config)
        
        let task = session.dataTaskWithRequest(request, completionHandler: 
                                        {(data, response, error) -> Void in
            
 
            //check errors
            guard error == nil else {
                print(error!)
                return
            }
            

            guard let jsonData = data else {
                print("Error retriving data")
                return
            }
            
            do {
                let json: AnyObject = try NSJSONSerialization.
                           JSONObjectWithData(jsonData, options: 
                                                .AllowFragments)

                

                let desc = json[2]!.description.
                                   dataUsingEncoding(NSUTF8StringEncoding)
                
                self.description = NSString(data: desc!, 
                                encoding: NSUTF8StringEncoding)! as String
                
                let set = NSCharacterSet(charactersInString: "()")
                self.description = self.description.
                                       stringByTrimmingCharactersInSet(set)
                

                dispatch_semaphore_signal(semaphore)
                
            } catch {
                print ("error serializing JSON: \(error)")
            }

        })
        
        task.resume()
        
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
       
    }


And the result looks like


Cap comentari:

Publica un comentari a l'entrada