uchicago-mobi / MPCS51030-2017-Winter-Forum

7 stars 0 forks source link

AlertView Sometimes Loading Slowly #175

Open lakshman111 opened 7 years ago

lakshman111 commented 7 years ago

I have an alert view that sometimes takes about 10 seconds to popup. Sometimes it loads immediately. Would a TA mind taking a quick look at my code to check out if I am doing something wrong?

I get the following logged in my console when the alert view is loading, but from googling, it seems appropriate as pressing "OK" on the alert should load a new view controller:

2017-03-10 16:54:30.115 ZooTalk[23991:1030748] pushViewController:animated: called on <UINavigationController 0x7fd04f810c00> while an existing transition or presentation is occurring; the navigation stack will not be updated.

I just pushed my code. The code that is firing is in the bottom of the CompanyTableViewController class (reproduced below).

        ```

let message = "If you log into LinkedIn, I'll make all your hopes and dreams come true..." let alert = UIAlertController(title: "Wait!!!", message: message, preferredStyle: .alert)

        let action = UIAlertAction(title: "OK", style: .default, handler: {action in
            print("Message was shown.")
            // MARK: -Attribution: http://stackoverflow.com/questions/24035984/instantiate-and-present-a-viewcontroller-in-swift?rq=1
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let controller = storyboard.instantiateViewController(withIdentifier: "WebViewController")
            self.present(controller, animated: true, completion: nil)
        })
        alert.addAction(action)
        self.present(alert, animated: true, completion: nil)
susanstevens commented 7 years ago

I'll take a look at it. 😃

susanstevens commented 7 years ago

It looks like the problem is that you're presenting the alert inside of prepareForSegue. As the error message indicates, you shouldn't try to present two view controllers (the alert view controller and the segue.destination controller) at the same time.

Try implementing func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool (documentation here). Inside of that function, determine whether you want to perform the segue to the destination view controller OR cancel the segue by returning false and present the alert controller instead.

lakshman111 commented 7 years ago

Thank you! I implemented that function, and then also used "CATransaction.setCompletionBlock({" from this stackoverflow as is suggested. This seems to have helped (I'd say on average faster load times), however the alert on first load of the app (after first install) occasionally still takes ~10 seconds to load. Subsequent loads usually load normally. Does my implementation seem correct? (new code is pushed to git and copied below).

`override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { // If I have the LinkedIn profile, you can load the communicate page if UserDefaults.standard.string(forKey: "profileURLString") != nil{ print("The user is already logged in, so load the form page.") return true } // Else, make the user sign in else { print("The user is not logged in, make them login.") let message = "If you log into LinkedIn, I'll make all your hopes and dreams come true..." let alert = UIAlertController(title: "Wait!!!", message: message, preferredStyle: .alert)

        let action = UIAlertAction(title: "OK", style: .default, handler: {action in
            // MARK: -Attribution: http://stackoverflow.com/questions/40367565/perform-segue-after-uialertcontroller-is-dismissed
            CATransaction.setCompletionBlock({
                print("Login alert was shown.")
                // MARK: -Attribution: http://stackoverflow.com/questions/24035984/instantiate-and-present-a-viewcontroller-in-swift?rq=1
                let storyboard = UIStoryboard(name: "Main", bundle: nil)
                let controller = storyboard.instantiateViewController(withIdentifier: "WebViewController")
                self.present(controller, animated: true, completion: nil)
            })
        })
        alert.addAction(action)
        self.present(alert, animated: true, completion: nil)
        return false
    }
}

`

susanstevens commented 7 years ago

Here's a StackOverflow post that makes me think this could be related to the fact that you're presenting the alert when the user taps on a table view cell. According to the post, this might be an Apple bug. Their solution is to wrap the line where you present the alert in a dispatch block:

DispatchQueue.main.async {
    self.present(alert, animated: true, completion: nil)
}

I pulled down your project and this work-around seemed to fix the problem.

lakshman111 commented 7 years ago

Got it, thanks!!!