6

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, "http://www.google.hr").response
                { response in
                    if response.3 != nil
                    {
                        print("NOK")
                        completion(result: "NOK")
                    }
                    print("OK")
                    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.

Ariel
  • 2,471
  • 1
  • 26
  • 43
  • Take a look here: http://stackoverflow.com/questions/33865843/swift-2-1-alamofire-timeout-method and http://stackoverflow.com/questions/36626075/handle-timeout-with-alamofire – Feldur Jul 27 '16 at 09:48
  • Nah, those things only checks for connection. In my case connection is fine, but connection is slow –  Jul 27 '16 at 13:35

1 Answers1

1

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, "http://blabla.com").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.