Handle No Internet Connection Error Before Try to Parse the Result in Alamofire
Solution 1
I agree with @Shripada. First you should use Reachability to check for connectivity. There is a Swift library here: https://github.com/ashleymills/Reachability.swift
additionally you can use one of the Alamofire validation methods:
Alamofire.request(.POST, REGISTER_URL, parameters: parameters, encoding: .JSON, headers: getAuthenticationHeader()).validate(statusCode: 200 ..< 300).response { (request, response, data, error) -> Void in
if error != nil {
println("Server responded with: \(response.statusCode)")
return
}
// Handle your response data here
}
Solution 2
Swift 3 Solution
Assuming you have an Error
instance you can do the following:
if let err = error as? URLError, err.code == URLError.Code.notConnectedToInternet
{
// No internet
}
else
{
// Other errors
}
You simply cast error
into a URLError
. This works since URLError
implements the Error
protocol. Here is a quote from the apple documentation for reference:
URLError: Describes errors in the URL error domain.
Once you have a URLError
instance you can simply compare its code
property, which is a URLError.Code
enum, against the any relevant enum cases (in our example URLError.Code.notConnectedToInternet
).
Solution 3
This works for me in Swift2.x
Alamofire.request(.POST, url).responseJSON { response in
switch response.result {
case .Success(let json):
// internet works.
case .Failure(let error):
if let err = error as? NSURLError where err == .NotConnectedToInternet {
// no internet connection
} else {
// other failures
}
}
}
Solution 4
Other way to check for internet connection existing
import SystemConfiguration
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(&zeroAddress, {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}) else {
return false
}
var flags : SCNetworkReachabilityFlags = []
if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == false {
return false
}
let isReachable = flags.contains(.Reachable)
let needsConnection = flags.contains(.ConnectionRequired)
return (isReachable && !needsConnection)
}
let hasInternet = connectedToNetwork()
Solution 5
Details
- Xcode 10.2.1 (10E1001), Swift 5
Prepare
Edit NSAppTransportSecurity in Info.plist:
Code:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
Sample 1 (need Alamofire pod)
import UIKit
import Alamofire
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
button.setTitle("Check", for: .normal)
button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
}
@objc func checkInternetConnection() {
guard let networkReachabilityManager = NetworkReachabilityManager(host: "http://google.com") else { return }
networkReachabilityManager.listener = { [weak self] status in
let alert = UIAlertController(title: "Network Status ", message: "\(status)", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] _ in
alert?.dismiss(animated: true, completion: nil)
}))
self?.present(alert, animated: true, completion: nil)
}
networkReachabilityManager.startListening()
}
}
Sample 2 (need Alamofire pod)
import UIKit
import Alamofire
class ViewController: UIViewController {
private lazy var networkManager = NetworkManager()
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
button.setTitle("Check", for: .normal)
button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
}
@objc func checkInternetConnection() {
let urlString = "http://dummy.restapiexample.com/api/v1/employees"
networkManager.sessionManager.request(urlString).validate().response { response in
print("\(response.data as Any)")
}
}
}
class NetworkManager {
lazy var sessionManager: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpCookieStorage = nil
configuration.httpCookieAcceptPolicy = HTTPCookie.AcceptPolicy.never
let manager = SessionManager(configuration: configuration)
manager.retrier = self
return manager
}()
}
extension NetworkManager: RequestRetrier {
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
let error = error as NSError
switch error.code {
case -1009:
DispatchQueue.main.async {
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] _ in
alert?.dismiss(animated: true, completion: nil)
}))
UIApplication.topMostViewController?.present(alert, animated: true, completion: nil)
}
default: break
}
print("-- Error code: \(error.code)")
print("-- Error descriptiom: \(error.localizedDescription)")
}
}
// https://stackoverflow.com/a/52932487
extension UIViewController {
var topMostViewController: UIViewController {
if let presented = self.presentedViewController {
return presented.topMostViewController
}
if let navigation = self as? UINavigationController {
return navigation.visibleViewController?.topMostViewController ?? navigation
}
if let tab = self as? UITabBarController {
return tab.selectedViewController?.topMostViewController ?? tab
}
return self
}
}
extension UIApplication {
class var topMostViewController : UIViewController? {
return UIApplication.shared.keyWindow?.rootViewController?.topMostViewController
}
}
Sample 3 (without third party library)
More info: How to use SCNetworkReachability in Swift
import UIKit
import SystemConfiguration
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
button.setTitle("Check", for: .normal)
button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
}
@objc func checkInternetConnection() {
print("-- \(URLSession.connectedToNetwork())")
}
}
extension URLSession {
class func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr()
zeroAddress.sa_len = UInt8(MemoryLayout<sockaddr>.size)
zeroAddress.sa_family = sa_family_t(AF_INET)
guard let networkReachability = SCNetworkReachabilityCreateWithAddress(nil, &zeroAddress) else { return false }
var flags = SCNetworkReachabilityFlags()
SCNetworkReachabilitySetDispatchQueue(networkReachability, DispatchQueue.global(qos: .default))
if SCNetworkReachabilityGetFlags(networkReachability, &flags) == false { return false }
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return isReachable && !needsConnection
}
}
Sample 4 (need Reachability.swift pod)
import UIKit
import Reachability
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(frame: .init(x: 80, y: 80, width: 100, height: 40))
button.setTitle("Check", for: .normal)
button.addTarget(self, action: #selector(checkInternetConnection), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
view.addSubview(button)
}
@objc func checkInternetConnection() {
guard let reachability = Reachability(hostname: "google.com", queueQoS: .utility) else { return }
try? reachability.startNotifier()
print("-- \(reachability.connection as Any)")
}
}
JayVDiyk
Updated on July 25, 2022Comments
-
JayVDiyk almost 2 years
How should I handle if there is an error occurs when there is no internet connection in Alamofire. I tried checking if data is nil or not but it does not work.
Below is how I use Alamofire
Alamofire.request(.POST, REGISTER_URL, parameters: parameters, encoding: .JSON, headers: getAuthenticationHeader()).response { (request, response, data, errorType) -> Void in let resultObject: APIResults = APIResults(JSONDecoder(data!)); let responseCode: Int = Int(resultObject.code!)!;// THIS CRASHES WHEN THERE IS NO INTERNET CONNECTION if (responseCode == 200) { available = true; } finished = true; }
-
Luda about 8 yearsI get "Use of unresolved identifiers 'getAuthenticationHeader' "
-
ergoon about 8 yearsjust remove this method call. it is specific to the question
-
rocky raccoon almost 7 yearsSometimes, Alamofire returns
Error
without any sort of error code after it. This happens only when I'm not running localhost. I forgot the error code, but it had to do with not connecting to a server even though the internet was on and I want to be able to catch that. -
HotFudgeSunday over 6 yearsReachability is a problem you don't need unless your App needs to be constantly connected, for whatever reason. I generally don't need it. Users only need connectivity when they're requesting data, the rest of the time they can use cached data in most Apps.