lifewithelliott lifewithelliott - 7 months ago 89
Swift Question

Swift - Crashing With Reachability

I call the method testReachability() when a UIButton is pressed to check for internet connection before it completes the action. This is using Ashley Mill's reachability class.

On Line 24 I call completed() so that if the app can reach the network then it will complete the closure and continue on with the rest of the action. However the app becomes glitchy and this error displays in the debug console:

"This application is modifying the autolayout engine from a background thread, which can lead to engine corruption and weird crashes. This will cause an exception in a future release.”

And If I call completed() on lets say, line 26, then the app runs flawlessly, quick and smooth until I lose internet connection/enter airplane mode. Then the app crashes instantly and xcode loses connection to the device on the tap of the button.

My question is what can I do to resolve the crashing of my application when checking for reachability.

func testReachability(completed: DownloadComplete)
{
let reachability: Reachability
do {
reachability = try Reachability.reachabilityForInternetConnection()
} catch {
return
}

reachability.whenReachable = { reachability in
// this is called on a background thread, but UI updates must
// be on the main thread, like this:
dispatch_async(dispatch_get_main_queue())
{
if reachability.isReachableViaWiFi()
{
print("Reachable via WiFi")
}
else
{
print("Reachable via Cellular")
}
}
completed()
}

reachability.whenUnreachable = { reachability in
// this is called on a background thread, but UI updates must
// be on the main thread, like this:
dispatch_async(dispatch_get_main_queue())
{
self.presentReachabilityAlertController()
}
}

do
{
try reachability.startNotifier()
}
catch
{

}
}

func presentReachabilityAlertController()
{
let alert = UIAlertController( title: "Network Connection Lost", message:"Try Again", preferredStyle: .Alert)
alert.addAction(UIAlertAction( title: "ok" , style: .Default) { _ in } )
presentViewController ( alert, animated: true ) { }
connected = false
}

Answer

It sounds like the call to complete needs to execute on the main thread. It will do so when inside dispatch_async(dispatch_get_main_queue()). Try putting the call to complete inside dispatch_async as follows:

dispatch_async(dispatch_get_main_queue())
{
    if reachability.isReachableViaWiFi()
    {
        print("Reachable via WiFi")
    }
    else
    {
        print("Reachable via Cellular")
    }
    complete()   
}

If this doesn't fix the scenario when you are in airplane mode/offline I think we are going to need more code to help you figure it out. If you could show how/when this function is called, the complete callbacks, and maybe even the presentReachabilityAlertController function that would be helpful.

Comments