IPv4とIPv6の両方のネットワーク環境で機能するiOSでインターネット接続を確認する最良の方法を見つけるために、インターネットを検索してきました。考えられる答えはたくさんありますが、どれを当てはめるか混乱しています。私がする必要があるのは次のとおりです:
// Check for internet connection
if (internetConnectionIsAvailable) {
// make rest calls
}else
// show cached data
}
インターネットで提案されている次のオプションが見つかりました。
オプション1:Use Apple Reachability class
到達可能性を使用すると、インターネット接続を次のように確認できます。これは短くて直接であり、応答を待つ必要はありません。
- (BOOL)connected
{
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [reachability currentReachabilityStatus];
return !(networkStatus == NotReachable);
}
- (void)viewDidLoad {
[super viewDidLoad];
if (![self connected]){
// Not connected
}else{
// Connected
}
}
ただし、ここではインターネットチェックは飛行前に行われます。これは、Appleエンジニア WWDCビデオ に見られるエンジニア)の提案に反しています。また、ReadMe.mdをチェックすると、 ReachabilityはIPv6を完全にサポートしていることを述べましたが、メソッドreachabilityForInternetConnectionがReachability.mでチェックされている場合、sockaddr_inを使用しているため、sockaddr_in6は使用されていません。 IPv6ネットワークなので、IPv6ネットワークで機能するかどうかはわかりません。
オプション2:Alamofireを使用して接続します
stackoverflow answer のように接続してみてください。以下に示すコード:-
Alamofire.request(.GET,"http://superrandomdomainnamethatisnotused.com/superrandompath").responseString {
(request, response, stringData, error) in
if let networkError = error {
if (networkError.code == -1009) {
println("No Internet \(error)")
}
}
}
しかし、一部のホストに接続して、応答を待ってから、オンラインかオフラインかを知るのは時間がかかりませんか。
オプション3:到達可能性 のTony Millionバージョンを使用します。しかし、作者はこれを使用しているときにアプリが拒否されることを警告しています。これを以下のコードとして使用できます:-
// Checks if we have an internet connection or not
- (void)testInternetConnection
{
internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com"];
// Internet is reachable
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"There in internet connection");
});
};
// Internet is not reachable
internetReachableFoo.unreachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"Someone broke the internet :(");
});
};
[internetReachableFoo startNotifier];
}
しかし、このオプションでは、私の質問は、 http://google.com に接続してインターネットをテストするこの正しいアプローチですか?これは100%の結果を保証しますか?グーグルがダウンした場合はどうなりますか?アプリがgoogle.comが許可されていない国で使用されている場合、結果はどうですか?
したがって、これらのオプションが正しい方法であるか、100%の結果を保証し、IPv4とIPv6の両方のネットワークで機能するインターネットをチェックするより良い方法があるかどうか、私はどのオプションを選択するかという大きなジレンマに陥っています。誰かが私にどのオプションがより良いか、または私が他のアプローチに行くべきか、これを達成するためのより良い方法は何かを提案できますか?.
ご返信いただければ幸いです。
Swift 3、Xcode 8 ......
func isInternetAvailable() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}
このリンクが役立つと思います: SwiftのIPv6ネットワークでネットワーク接続チェックがクラッシュします
import SystemConfiguration
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
}
}
//使用事例
if Reachability.isConnectedToNetwork() {
//do something
}
研究のための他のリンクをいくつか以下に示します。
https://developer.Apple.com/reference/systemconfiguration/1514904-scnetworkreachabilitycreatewithn
すべてのRESTful APIにすでにAlamofireを使用している場合、そのメリットを次に示します。
次のクラスをアプリに追加し、MNNetworkUtils.main.isConnected()
を呼び出して、接続されているかどうかのブール値を取得できます。
#import Alamofire
class MNNetworkUtils {
static let main = MNNetworkUtils()
init() {
manager = NetworkReachabilityManager(Host: "google.com")
listenForReachability()
}
private let manager: NetworkReachabilityManager?
private var reachable: Bool = false
private func listenForReachability() {
self.manager?.listener = { [unowned self] status in
switch status {
case .notReachable:
self.reachable = false
case .reachable(_), .unknown:
self.reachable = true
}
}
self.manager?.startListening()
}
func isConnected() -> Bool {
return reachable
}
}
これはシングルトンクラスです。ユーザーがネットワークを接続または切断するたびに、シングルトン初期化でNetworkReachabilityManager
のリッスンを開始するため、self.reachable
をtrue/falseに正しくオーバーライドします。
また、到達可能性を監視するために、ホストを提供する必要があります。現在、私はgoogle.com
を使用しています。必要に応じて、他のホストまたはホストに自由に変更してください。
最善の方法として、すでにAlamofireを使用している場合、これが最善の方法になると思います。 google.com
の監視は悪い設計だとは思いません。私が間違っている場合は、遠慮なく訂正してください。
Github から.Zipフォルダーをダウンロードします
添付されたフォルダを解凍し、ファイルをプロジェクトにドラッグアンドドロップします。
bridge.h
ファイルを作成し、#import "Reachability.h"
を使用してインポートします。
APIを呼び出す前に、次のコードでインターネット接続を確認できます。
if kNetworkController.checkNetworkStatus() {
// call your api
}
それでおしまい。