emresancaktar
emresancaktar

Reputation: 1567

Show AlertView on VC. When custom class catches the error in closure

I want to ask question about new UIAlertController. How can I detect the errors on custom class to show alert view to users ? I want to execute my alert view when the switch case goes the default statement. There is my NetworkOperation class which is custom class with closures for download some JSON data from web.

class NetworkOperation {

lazy var config: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
lazy var session: NSURLSession = NSURLSession(configuration: self.config)

let mainURL: NSURL

typealias JSONWeatherDataDictionary = ([String: AnyObject]?) -> Void

init(url: NSURL) {

    mainURL = url
}

func downloadWeatherDataFromWeb(completion: JSONWeatherDataDictionary) {

    let request = NSURLRequest(URL: mainURL)

    let dataTask = session.dataTaskWithRequest(request) {

        (let data, response, error) in

        if let httpResponse = response as? NSHTTPURLResponse {

            switch httpResponse.statusCode {

            case 200:
                // HTTP Response success use the weather data !

                do {

                    let weatherDataDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? [String: AnyObject]

                    completion(weatherDataDictionary)

                } catch {

                    print("Data can't get")
                }

            default:
// I want to execute my alert view in there. showAlertView()
                print("Http Response failed with this code: \(httpResponse.statusCode)")
            }

        } else {

            print("HTTP Response convert fail !")
        }
    }

    dataTask.resume()
}
}

If the default case is executed, how can I see my alert view in view controller ? I tried to solve this problem with UIAlertViewDelegate but its deprecated for iOS9 so I want to learn best common way to solve this problem. Thank you everyone...

Upvotes: 2

Views: 296

Answers (1)

Unheilig
Unheilig

Reputation: 16302

If all you would like to do is to present an alert that lets the user know about the error, providing along a cancel button to dismiss the button, you could make use of UIAlertController.

I tested the following code with a HTTP URL, causing it to fail, the alert view pops up displaying the status code; and upon tapping on the "cancel" button, dismisses itself.

func downloadWeatherDataFromWeb(completion: JSONWeatherDataDictionary)
{
    let request = NSURLRequest(URL: mainURL)
    let dataTask = session.dataTaskWithRequest(request)
    {
        (let data, response, error) in

        if let httpResponse = response as? NSHTTPURLResponse
        {
            switch httpResponse.statusCode
            {
                case 200:
                do
                {
                    let weatherDataDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? [String: AnyObject]
                    completion(weatherDataDictionary)
                }
                catch
                {
                    print("Could not retrieve data")
                }
            default:
                print("Http Response failed with the following code: \(httpResponse.statusCode)")

                let alert = UIAlertController(title: "HTTP Error", message:String(httpResponse.statusCode), preferredStyle: UIAlertControllerStyle.Alert)
                //set up cancel action
                let cancelAction: UIAlertAction = UIAlertAction(title: "Cancel", style: .Cancel)
                {
                    action -> Void in
                    //should you want to carry some other operations upon canceling
                }
                //add the action
                alert.addAction(cancelAction)
                dispatch_async(dispatch_get_main_queue(),
                {
                    self.presentViewController(alert, animated:true, completion:
                    {
                        //alert controller presented
                    })
                })
            }
        }
        else
        {
            print("HTTP Response conversion failed!")
        }
    }
    dataTask.resume()
}

Update: in response to your comment

Please add a UIViewController variable:

class NetworkOperation 
{
    var viewController : UIViewController = UIViewController()
....

And make modification to the default: case above:

dispatch_async(dispatch_get_main_queue(),
{
     self.addChildViewController(self.viewController)
     self.view.addSubview(self.viewController.view)                     
     self.viewController.didMoveToParentViewController(self)
     self.viewController.presentViewController(alert, animated:true,   
     completion:
     {
         //alert controller presented
     })
})

I just took the liberty of testing it a minute ago; it pops and dismisses.

Another Update:

Then, we could do the following:

dispatch_async(dispatch_get_main_queue(),
{
    let topViewController = UIApplication.sharedApplication().keyWindow?.rootViewController
    topViewController!.presentViewController(alert, animated:true,   
    completion:
    {
     //alert controller presented
    })
})

Upvotes: 2

Related Questions