Stjepan Stjepan - 1 year ago 137
Swift Question

Check for slow (not just if device is connected) Internet connection in Swift iOS 9.3

I'm having some trouble handling the case when there is a very slow internet connection. First, let me explain. I can handle when device is not connected to the Internet and function that handles that is:

public class Reachability
class func isConnectedToNetwork() -> Bool
var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)

let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0))

var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
return false

let isReachable = flags == .Reachable
let needsConnection = flags == .ConnectionRequired

return isReachable && !needsConnection

So when device is connected to the Internet and connection is fast and stable, everything works fine. When device is not connected to the Internet, I get warning(s) that I need to be connected and that is handled too.

Problem is, when I'm connected and Internet is very slow like 16 kbps. A lot of things are requested through Alamofire, and it takes years to download on that speed. I wouldn't mind that either if it didn't stop my app and eventually crash it.

I've tried this function:

class func isInternetActive(input: String, completion: (result: String) -> Void)
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {

Alamofire.request(.GET, "").response
{ response in
if response.3 != nil
completion(result: "NOK")
completion(result: "OK")


Also I'm using Alamofire to fetch data for my social media viewcontrollers and for Twitter I'm using Fabric.

I would like something like this: Try to fetch data. If you can't fetch them within 3-4 sec. then stop requesting. So, if you can't download image within few secs let that imageView be white or empty, just like when I'm not connected to the Internet.

Answer Source

I solved the problem. I request an img URL through Alamofire, and then set the image (with that url) with code for example:

var url:NSURL = NSURL.URLWithString("http://myURL/ios8.png")
var data:NSData = NSData.dataWithContentsOfURL(url, options: nil, error: nil)

And that's the problem. Alamofire is in the background thread, and the code above is in the main thread. So, code has to be run when Alamofire finishes his request.

Here is the example:

dispatch_async(dispatch_get_global_queue(qualityOfServiceClass, 0), {
            Alamofire.request(.GET, "").responseJSON(completionHandler:
                { (json) -> Void in
                    if let jsonData = json.result.value
                        if jsonData.isKindOfClass(NSArray)
                            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                                let secondImageURLL = jsonData[x][ImgURL] as! String
                                setImageToUrlImageViewForHomeSlider(sliderData, imageToSetL: imageToSetL)

Here you can see that request is in the global queue and the code in the main queue has to wait for background queue to finish, function setImageToUrlImageViewForHomeSlider is called:

func setImageToUrlImageViewForHomeSlider(sliderDataL: WBMHomeSliderDataM, imageToSetL: UIImageView)
    let url = NSURL(string: sliderDataL.imageURL!)
    imageToSetL.sd_setImageWithURL(url, placeholderImage: UIImage(named: "cloudErrorHomeSlider"))

In this function I used SDWebImage framework (which is also run asynchronous) to set the image with downloaded URL and if it fails, placeholder image is set.

In that way, your app is free for loading and it won't stop, freeze or crash the App because of slow Internet connection.