Alamofireにインターネット接続がないときにエラーが発生した場合、どうすればよいですか?データがnilかどうかを確認しようとしましたが、機能しません。
以下は私が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;
}
@Shripadaに同意します。最初に、到達可能性を使用して接続を確認する必要があります。 Swiftここにライブラリがあります: https://github.com/ashleymills/Reachability.Swift
さらに、Alamofire検証メソッドの1つを使用できます。
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
}
Swift 3ソリューション
Error
インスタンスがあるとすると、次のことができます。
if let err = error as? URLError, err.code == URLError.Code.notConnectedToInternet
{
// No internet
}
else
{
// Other errors
}
単にerror
をURLError
にキャストします。 URLError
がError
プロトコルを実装しているため、これは機能します。参考のためにAppleドキュメントからの引用です:
URLError:URLエラードメインのエラーについて説明します。
URLError
インスタンスを取得したら、そのcode
プロパティを単純に比較できます。これはURLError.Code
列挙型、関連する列挙型のケースに対して(この例ではURLError.Code.notConnectedToInternet
)。
これは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
}
}
}
インターネット接続が存在するかどうかを確認する別の方法
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()
Info.plistの編集 NSAppTransportSecurity :
コード:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key><true/>
</dict>
Network Reachability を使用します
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()
}
}
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
}
}
詳細: SwiftでSCNetworkReachabilityを使用する方法
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
}
}
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)")
}
}
Swift 5
.catchError { (error: Error) in
if let err = error as? URLError, err.code == URLError.Code.notConnectedToInternet {
// No internet
} else {
// Other errors
}
}