This question already has answers here:
Check for internet connection with Swift
(31 answers)
Closed 6 years ago.
Is there an Apple framework bundle to detect if there's an internet connection? Currently my application crashes when it tries to geolocate the user's position without an internet connection.
/*inside locationManager didUpdateLocations method*/
var currentLocation:CLLocation? = locations[0] as? CLLocation
geocoder = CLGeocoder()
//Crashes on line below when there isn't an internet connection
//Need to add function to check if internet connection is live
//Before running reverseGeocodeLocation
geocoder.reverseGeocodeLocation (currentLocation,handleGeocode)
I'm a bit new to swift and ios programming - my apologies.
Not a full-fledged network checking library but I found this simple method for checking the network availability. I managed to translate it to Swift and here the final code.
import Foundation
import SystemConfiguration
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(nil, UnsafePointer($0)).takeRetainedValue()
}
var flags: SCNetworkReachabilityFlags = 0
if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == 0 {
return false
}
let isReachable = (flags & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection) ? true : false
}
}
It works for both 3G and WiFi connections. I've also uploaded it to my Github with a working example. If you're looking for a simple way to check for network availability purely in Swift, you can use it.
Using Babatunde's code sample but here is an updated version for Swift 2.0 and error handling:
EDIT: Also changed the URL for Google as HTTPS for iOS 9.
EDIT2: Original article: http://www.brianjcoleman.com/tutorial-check-for-internet-connection-in-swift/
import Foundation
import SystemConfiguration
public class Reachability {
// Check if internet connection is available
class func isConnectedToNetwork() -> Bool {
var status:Bool = false
let url = NSURL(string: "https://google.com")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "HEAD"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
request.timeoutInterval = 10.0
var response:NSURLResponse?
do {
let _ = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response) as NSData?
}
catch let error as NSError {
print(error.localizedDescription)
}
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode == 200 {
status = true
}
}
return status
}
}
As Reachability has not been fully ported to swift yet, you can use the sample code below to check for internet connection:
public class Reachability {
/**
* Check if internet connection is available
*/
class func isConnectedToNetwork() -> Bool {
var status:Bool = false
let url = NSURL(string: "http://google.com")
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "HEAD"
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
request.timeoutInterval = 10.0
var response:NSURLResponse?
var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) as NSData?
if let httpResponse = response as? NSHTTPURLResponse {
if httpResponse.statusCode == 200 {
status = true
}
}
return status
}
}
See sample usage of the function below:
// Check if internet is available before proceeding further
if Reachability.isConnectedToNetwork() {
// Go ahead and fetch your data from the internet
// ...
} else {
println("Internet connection not available")
var alert = UIAlertView(title: "No Internet connection", message: "Please ensure you are connected to the Internet", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
Related
I am trying to setup server using Vapor. As client, I have simple iOS app using NSUrlSession - URLSessionWebSocketTask. My question is... how I can set session.data from iOS app?
iOS App - Connect method
func connect(completion: #escaping ()->() = { }) {
guard webSocketTask == nil else { return }
self.username = "Name"
self.userID = UUID().uuidString
let url = URL(string: "ws://localhost:8080/connect")!
webSocketTask = URLSession.shared.webSocketTask(with: url)
webSocketTask?.receive(completionHandler: onReceive)
webSocketTask?.resume()
}
Vapor:
app.webSocket("connect") { request, ws in
let controller = Controller()
let userName = request.session.data["nickname"] ?? "Unknown user"
let data = request.session.data["data"] ?? "Empty Data"
controller.addUser(userName, with: room, withConnection: ws)
.....
....
...
..
.
You may use NSURLSessionDataTask.
https://developer.apple.com/documentation/foundation/nsurlsessiondatatask
I am wondering if there is an easy way to find out if a user is on wifi or cellular data (perhaps CoreTelephony)?
I am mainly interested in just actual network speed to determine the level of quality of video I should set for AVPLayer (via preferredPeakBitRate).
there are two steps involved. First detect what type of network are you on.
second is what is the bandwidth. There are two functions below to perform each task
This function is to identify the network you are on.
enum ReachabilityType: CustomStringConvertible {
case wwan
case wiFi
var description: String {
switch self {
case .wwan: return "WWAN"
case .wiFi: return "WiFi"
}
}
}
This function is to get the bandwidth speed.
func bandWidthCheck() {
let sample = URL(string: "http:exampleURL")
let request = URLRequest(url: sample!)
let session = URLSession.shared
let startTime = Date()
let task = session.dataTask(with: request) { (data, resp, error) in
guard error == nil && data != nil else{
print("connection error or data is nill")
return
}
guard resp != nil else{
print("response is nill")
return
}
let size = CGFloat( (resp?.expectedContentLength)!) / 1000000.0
print(size)
let time = CGFloat( Date().timeIntervalSince(startTime))
print("elapsed: \(time)")
print("Speed: \(size/time) Mb/sec")
}
task.resume()
}
Have a Traccar server at http://188.120.235.97:8082/, trying to connect websocket using Swift library Starscream (https://github.com/daltoniam/Starscream).
There is my code:
func connect(_ token: String) {
var urlString = "\(self.serverURL)api/socket"
urlString = urlString.replacingOccurrences(of: "http", with: "ws")
self.socket = WebSocket(url: URL(string: urlString)!, protocols: ["chat"])
guard let socket = self.socket else { return }
socket.headers["Cookie"] = "JSESSIONID=\(token)"
socket.headers["Sec-WebSocket-Key"] = "\(token)"
socket.headers["Sec-WebSocket-Protocol"] = "chat"
socket.headers["Sec-WebSocket-Version"] = "13"
socket.headers["Host"] = self.serverURL
socket.headers["Upgrade"] = "websocket"
socket.headers["Connection"] = "Upgrade"
socket.headers["Origin"] = self.serverURL
socket.headers["Sec-WebSocket-Accept"] = "application/json, text/html"
socket.delegate = self
socket.connect()
print("isConnected: \(socket.isConnected)")
print("socket: \(socket)")
print("headers: \(socket.headers)")
}
Nothing happened, status of websocket is CONNECTING, never OPEN.
Using Fiddler cannot see any GET request also, when calling socket.connect...
Does it work in iOS simulator?
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.
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.
I am new in swift and i am implement one demo in which i have dictionary with multiple object in which there are some UIImage objects.
How i can differentiate UIImage object? I am using isKindClass but it is not work for me and give the error like "'AnyObject' dose not have member name isKindOfClass"
Code is like this
func initURLConnectionWithRequest(requestUrl:NSURL,apiTag:NSInteger,paramDic:NSDictionary,obj:NSObject) ->IMDRequest
{
var newRequest = IMDRequest()
request1 = newRequest;
self.tag=apiTag
var request = NSMutableURLRequest(URL: requestUrl)
var timeInterval = NSTimeInterval(60)
request.timeoutInterval = timeInterval
request.HTTPMethod = "POST"
var strBoundry = "---------------------------14737809831466499882746641449"
var contentType = "multipart/form-data; boundary=\(strBoundry)"
request.addValue(contentType, forHTTPHeaderField:"Content-Type")
var bodyData = NSMutableData()
var arrParamKey = paramDic.allKeys
for var i = 0; i<arrParamKey.count; i++
{
if (paramDic.objectForKey(arrParamKey[i]).isKindOfClass(UIImage))
{
}
}
urlConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)!
self.senderObj = obj;
urlConnection.start()
self.isResponseReceived = false
return request1;
}
If you want to check whether the variable is of a type that you want, or that it conforms to some protocol, then you can use this as a reference:
var abc = …
if abc is <UIImage> {
//the variable is of type <UIImage>
} else {
//variable is not of type <UIImage>
}
This is same as isKindOfClass in Objective-C.
Hope this will help you.