iOSでインターネット接続を検出する最も簡単な方法は?
-
26-10-2019 - |
質問
私はこの質問が他の多くの人々のdupeであるように見えることを知っていますが、ここで簡単なケースがよく説明されているとは思わない。 AndroidとBlackBerryの背景から来て、リクエストを介して HTTPUrlConnection
使用可能な接続がない場合、すぐに失敗します。これは完全に正気な行動のように思えます、そして私は見つけて驚きました NSURLConnection
iOSではそれをエミュレートしませんでした。
私は、Apple(およびそれを拡張した他の人)が提供することを理解しています Reachability
ネットワーク状態の決定を支援するクラス。私は最初にこれを見て幸せで、 bool isNetworkAvailable()
, 、しかし、驚いたことに、通知登録とコールバックを必要とする複雑なシステム、そして一見不必要な詳細が多いことを見つけました。より良い方法がなければなりません。
私のアプリは、接続なしを含む接続障害を優雅に処理しています。ユーザーに失敗が通知され、アプリが移動します。
したがって、私の要件は単純です。すべてのHTTPリクエストの前に呼び出すことができ、実際にリクエストを送信するかどうかを判断することができます。理想的には、セットアップを必要とせず、ブールを返すだけです。
これは本当にiOSで不可能ですか?
解決
もう少し調査を行い、より最新の解決策で答えを更新しています。あなたがすでにそれを見たかどうかはわかりませんが、Appleが提供する素晴らしいサンプルコードがあります。
サンプルコードをダウンロードします ここ
プロジェクトにReachability.hとReachability.mファイルを含めます。 Reachabilityappdelegate.mをご覧ください。WWANなどのWWANなどのホストの到達可能性、WiFiの到達可能性を決定する方法の例をご覧ください。
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
NSLog(@"There IS NO internet connection");
} else {
NSLog(@"There IS internet connection");
}
@Benjaminpiette's:SystemConfiguration.Frameworkをプロジェクトに追加することを忘れないでください。
他のヒント
このスレッドがこのタイプの質問のトップグーグルの結果であると見て、私は自分のために働いたソリューションを提供すると考えました。私はすでに使用していました アフネットワーキング, 、しかし、検索は私のプロジェクトの途中までこのタスクをアフネットワーキングで達成する方法を明らかにしませんでした。
あなたが望むのはですAfnetWorkingReachabilityManager.
// -- Start monitoring network reachability (globally available) -- //
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
// -- Reachable -- //
NSLog(@"Reachable");
break;
case AFNetworkReachabilityStatusNotReachable:
default:
// -- Not reachable -- //
NSLog(@"Not Reachable");
break;
}
}];
また、以下を使用して、到達可能性を同期してテストすることもできます(監視が開始されたら):
-(BOOL) isInternetReachable
{
return [AFNetworkReachabilityManager sharedManager].reachable;
}
返信が遅すぎて申し訳ありませんが、この答えが将来誰かを助けることができることを願っています。
以下は、余分なクラスなしでインターネット接続を確認できる小さなネイティブCコードスニペットです。
次のヘッダーを追加します。
#include<unistd.h>
#include<netdb.h>
コード:
-(BOOL)isNetworkAvailable
{
char *hostname;
struct hostent *hostinfo;
hostname = "google.com";
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL){
NSLog(@"-> no connection!\n");
return NO;
}
else{
NSLog(@"-> connection established!\n");
return YES;
}
}
スウィフト3
func isConnectedToInternet() -> Bool {
let hostname = "google.com"
//let hostinfo = gethostbyname(hostname)
let hostinfo = gethostbyname2(hostname, AF_INET6)//AF_INET6
if hostinfo != nil {
return true // internet available
}
return false // no internet
}
私は現在、あなたのプロジェクトや代表者に追加のファイルを必要としないこの単純な同期方法を使用しています。
輸入:
#import <SystemConfiguration/SCNetworkReachability.h>
この方法を作成します:
+(bool)isNetworkAvailable
{
SCNetworkReachabilityFlags flags;
SCNetworkReachabilityRef address;
address = SCNetworkReachabilityCreateWithName(NULL, "www.apple.com" );
Boolean success = SCNetworkReachabilityGetFlags(address, &flags);
CFRelease(address);
bool canReach = success
&& !(flags & kSCNetworkReachabilityFlagsConnectionRequired)
&& (flags & kSCNetworkReachabilityFlagsReachable);
return canReach;
}
次に、これをaに入れた場合 MyNetworkClass
:
if( [MyNetworkClass isNetworkAvailable] )
{
// do something networky.
}
シミュレータでテストしている場合は、シミュレーターが電話設定を無視するように見えるため、MacのWiFiをオンとオフにします。
アップデート:
最終的に、メインスレッドのブロックを避けるために、スレッド/非同期コールバックを使用しました。そして、私がキャッシュされた結果を使用できるように定期的に再テストすることができますが、データ接続を不必要に開いたままにしないようにする必要があります。
@Thunkが説明したように、使用するより良いURLがあり、Apple自身が使用しています。 http://cadinc.com/blog/why-your-apple-ios-7-device-wont-connect-to-the-wifi-network
それは可能であり、実装を完了したときにそれを見ると本当に簡単です。これは再び - 非常に単純です。必要な項目は2つのブール変数だけです。 )。接続ステータスを決定できるヘルパークラスを組み立てると、これらの手順を知るために必要な実装を再び気にしません。
例:
#import <Foundation/Foundation.h>
@class Reachability;
@interface ConnectionManager : NSObject {
Reachability *internetReachable;
Reachability *hostReachable;
}
@property BOOL internetActive;
@property BOOL hostActive;
- (void) checkNetworkStatus:(NSNotification *)notice;
@end
および.mファイル:
#import "ConnectionManager.h"
#import "Reachability.h"
@implementation ConnectionManager
@synthesize internetActive, hostActive;
-(id)init {
self = [super init];
if(self) {
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus:) name:kReachabilityChangedNotification object:nil];
internetReachable = [[Reachability reachabilityForInternetConnection] retain];
[internetReachable startNotifier];
hostReachable = [[Reachability reachabilityWithHostName:@"www.apple.com"] retain];
[hostReachable startNotifier];
return self;
}
- (void) checkNetworkStatus:(NSNotification *)notice {
NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
switch (internetStatus)
{
case NotReachable:
{
NSLog(@"The internet is down.");
self.internetActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(@"The internet is working via WIFI.");
self.internetActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(@"The internet is working via WWAN.");
self.internetActive = YES;
break;
}
}
NetworkStatus hostStatus = [hostReachable currentReachabilityStatus];
switch (hostStatus)
{
case NotReachable:
{
NSLog(@"A gateway to the host server is down.");
self.hostActive = NO;
break;
}
case ReachableViaWiFi:
{
NSLog(@"A gateway to the host server is working via WIFI.");
self.hostActive = YES;
break;
}
case ReachableViaWWAN:
{
NSLog(@"A gateway to the host server is working via WWAN.");
self.hostActive = YES;
break;
}
}
}
// If lower than SDK 5 : Otherwise, remove the observer as pleased.
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
@end
誰か もっている これを以前にシンプルで再利用可能な方法で解決しました。 DDGReachability
.
コードを抽出し、1つの方法に入れました。それが他の方法を助けることを願っています。
#import <SystemConfiguration/SystemConfiguration.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
...
- (BOOL)isInternetReachable
{
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr*)&zeroAddress);
SCNetworkReachabilityFlags flags;
if(reachability == NULL)
return false;
if (!(SCNetworkReachabilityGetFlags(reachability, &flags)))
return false;
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0)
// if target host is not reachable
return false;
BOOL isReachable = false;
if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0)
{
// if target host is reachable and no connection is required
// then we'll assume (for now) that your on Wi-Fi
isReachable = true;
}
if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) ||
(flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0))
{
// ... and the connection is on-demand (or on-traffic) if the
// calling application is using the CFSocketStream or higher APIs
if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0)
{
// ... and no [user] intervention is needed
isReachable = true;
}
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
// ... but WWAN connections are OK if the calling application
// is using the CFNetwork (CFSocketStream?) APIs.
isReachable = true;
}
return isReachable;
}
これは役立つと思います。
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
if([AFNetworkReachabilityManager sharedManager].isReachable)
{
NSLog(@"Network reachable");
}
else
{
NSLog(@"Network not reachable");
}
私は受け入れられた答えの迅速なバージョンを書いています ここ, 、誰かが有用であると判断した場合、コードはSwift 2と書かれています。
必要なファイルをからダウンロードできます samplecode
追加 Reachability.h
と Reachability.m
プロジェクトにファイル、
これで作成する必要があります Bridging-Header.h
プロジェクトに存在しない場合はファイル、
あなたの内側 Bridging-Header.h
ファイルこの行を追加します:
#import "Reachability.h"
インターネット接続を確認するために今
static func isInternetAvailable() -> Bool {
let networkReachability : Reachability = Reachability.reachabilityForInternetConnection()
let networkStatus : NetworkStatus = networkReachability.currentReachabilityStatus()
if networkStatus == NotReachable {
print("No Internet")
return false
} else {
print("Internet Available")
return true
}
}
また、プロジェクトでAfnetWorkingをすでに構成している場合は、これを試すこともできます。
-(void)viewDidLoad{ // -- add connectivity notification --//
[[NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(ReachabilityDidChangeNotification:) name:AFNetworkingReachabilityDidChangeNotification object:nil];}
-(void)ReachabilityDidChangeNotification:(NSNotification *)notify
{
// -- NSLog(@"Reachability changed: %@", AFStringFromNetworkReachabilityStatus(status)); -- //
NSDictionary *userInfo =[notif userInfo];
AFNetworkReachabilityStatus status= [[userInfo valueForKey:AFNetworkingReachabilityNotificationStatusItem] intValue];
switch (status)
{
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
// -- Reachable -- //
// -- Do your stuff when internet connection is available -- //
[self getLatestStuff];
NSLog(@"Reachable");
break;
case AFNetworkReachabilityStatusNotReachable:
default:
// -- Not reachable -- //
// -- Do your stuff for internet connection not available -- //
NSLog(@"Not Reachable");
break;
}
}
到達可能性を使用せずに、Swiftを使用して接続性をチェックするための良いソリューションを次に示します。これで見つけました ブログ.
プロジェクトで新しいSwiftファイルを作成します Network.swift
(例えば)。そのファイル内にこのコードを貼り付けます。
import Foundation
public class Network {
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
}
}
その後、以下を使用して、プロジェクトのどこでも接続を確認できます。
if Network.isConnectedToNetwork() == true {
println("Internet connection OK")
} else {
println("Internet connection FAILED")
}
編集:これはネットワークURLで機能しません(コメントを参照)
iOS 5の時点で、新しいNSURLインスタンスメソッドがあります。
- (BOOL)checkResourceIsReachableAndReturnError:(NSError **)error
気にかけているウェブサイトに指しているか、Apple.comを指してください。インターネットがデバイスで動作しているかどうかを確認するための新しいワンラインコールだと思います。
私はまた、インターネットチェックオプションに満足していませんでした(なぜこれがネイティブAPIではないのですか?!?!)
私自身の問題は、デバイスがルーターに接続されているが、ルーターがインターネットに接続されていない場合、100%のパケット損失でした。到達可能性と他の人は何年もかかっています。 Asynchのタイムアウトを追加することで、それに対処するために、ユーティリティシングルトンクラスを作成しました。私のアプリでは正常に動作します。それが役に立てば幸い。これがGitHubのリンクです:
(iOS)xcode 8.2、Swift 3.0でインターネット接続の可用性を確認する
これは、ネットワークの可用性を確認するための簡単な方法です。私はそれをなんとかSwift 2.0に翻訳し、ここで最終コードを翻訳しました。既存のApple Reachabilityクラスおよびその他のサードパーティライブラリは、Swiftに翻訳するには複雑すぎるように見えました。
これは、3G接続とWiFi接続の両方で機能します。
プロジェクトビルダーに「SystemConfiguration.Framework」を追加することを忘れないでください。
//Create new swift class file Reachability in your project.
import SystemConfiguration
public class Reachability {
class func isConnectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
}
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability! , &flags) {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
}
// Check network connectivity from anywhere in project by using this code.
if Reachability.isConnectedToNetwork() == true {
print("Internet connection OK")
} else {
print("Internet connection FAILED")
}
Appleの到達可能性の交換が書き直されました 閉鎖とともにスウィフト, 、Tormilionに触発されました: https://github.com/ashleymills/reachability.swift
ファイルをドロップします
Reachability.swift
あなたのプロジェクトに。または、使用してください ココアポッド また カルタゴ - を参照してください インストール プロジェクトのreadmeのセクション。ネットワーク接続に関する通知を取得します:
//declare this property where it won't go out of scope relative to your listener let reachability = Reachability()! reachability.whenReachable = { reachability in if reachability.isReachableViaWiFi { print("Reachable via WiFi") } else { print("Reachable via Cellular") } } reachability.whenUnreachable = { _ in print("Not reachable") } do { try reachability.startNotifier() } catch { print("Unable to start notifier") }
通知を停止するため
reachability.stopNotifier()
alamofire
すでに使用している場合 alamofire すべてのRESTFUL APIについて、ここからあなたがそれからベニフィットできるものがあります。
次のクラスをアプリに追加して電話をかけることができます 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
}
}
これはシングルトンのクラスです。毎回、ユーザーがネットワークを接続または切断すると、オーバーライドします self.reachable
私たちが聞き始めるので、true/falseを正しく正しく NetworkReachabilityManager
シングルトンの初期化について。
また、到達可能性を監視するには、ホストを提供する必要があります。現在、私は使用しています google.com
必要に応じて、他のホストまたはあなたのホストに自由に変更してください。