Swiftでインターネット接続を確認する


251

iPhoneでインターネット接続を確認しようとすると、たくさんのエラーが表示されます。誰かがこれを修正するのを手伝ってくれる?

コード:

import Foundation
import SystemConfiguration

public class Reachability {

class func isConnectedToNetwork() -> Bool {

    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
    zeroAddress.sin_family = sa_family_t(AF_INET)

    let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
        SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
    }

    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
}

}

コードのエラー:

エラー

読み取れない場合、エラー1は次のように述べます。

「Int」は「SCNetworkReachabilityFlags」に変換できません

エラー2&3:

指定された引数を受け入れる 'init'のオーバーロードが見つかりませんでした


1
:コードは、私がここで提案していたものに似ていますstackoverflow.com/a/25623647/1187415私はスウィフト2.のために1つ更新しましたので、
マーティンR

2
ここに完全に機能するSwift 2 Reachability実装があります… github.com/ashleymills/ Reachability.swift- 参考としてご利用ください。
アシュリーミルズ

1
stackoverflow.com/a/25623647/1187415がSwift 3、Xcode 8ベータ6向けに更新されました
Martin R

1
Appleは公式のSwiftサンプルを提供しており、CocoaPodsで入手できます。それはあらゆるSwiftプロジェクトと互換性があります。
・クール

回答:


368

コメントで言及されている4Gの問題を解決するために、@ AshleyMillsの到達可能性の実装を参照として使用し、Swift 3.1のReachabilityを書き直しました。

更新:Xcode 10.1•Swift 4以降


Reachability.swiftファイル

import Foundation
import SystemConfiguration

class Reachability {
    var hostname: String?
    var isRunning = false
    var isReachableOnWWAN: Bool
    var reachability: SCNetworkReachability?
    var reachabilityFlags = SCNetworkReachabilityFlags()
    let reachabilitySerialQueue = DispatchQueue(label: "ReachabilityQueue")
    init(hostname: String) throws {
        guard let reachability = SCNetworkReachabilityCreateWithName(nil, hostname) else {
            throw Network.Error.failedToCreateWith(hostname)
        }
        self.reachability = reachability
        self.hostname = hostname
        isReachableOnWWAN = true
        try start()
    }
    init() throws {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
        zeroAddress.sin_family = sa_family_t(AF_INET)
        guard let reachability = withUnsafePointer(to: &zeroAddress, {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                SCNetworkReachabilityCreateWithAddress(nil, $0)
            }
        }) else {
            throw Network.Error.failedToInitializeWith(zeroAddress)
        }
        self.reachability = reachability
        isReachableOnWWAN = true
        try start()
    }
    var status: Network.Status {
        return  !isConnectedToNetwork ? .unreachable :
                isReachableViaWiFi    ? .wifi :
                isRunningOnDevice     ? .wwan : .unreachable
    }
    var isRunningOnDevice: Bool = {
        #if targetEnvironment(simulator)
            return false
        #else
            return true
        #endif
    }()
    deinit { stop() }
}

extension Reachability {

    func start() throws {
        guard let reachability = reachability, !isRunning else { return }
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        context.info = Unmanaged<Reachability>.passUnretained(self).toOpaque()
        guard SCNetworkReachabilitySetCallback(reachability, callout, &context) else { stop()
            throw Network.Error.failedToSetCallout
        }
        guard SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue) else { stop()
            throw Network.Error.failedToSetDispatchQueue
        }
        reachabilitySerialQueue.async { self.flagsChanged() }
        isRunning = true
    }

    func stop() {
        defer { isRunning = false }
        guard let reachability = reachability else { return }
        SCNetworkReachabilitySetCallback(reachability, nil, nil)
        SCNetworkReachabilitySetDispatchQueue(reachability, nil)
        self.reachability = nil
    }

    var isConnectedToNetwork: Bool {
        return isReachable &&
               !isConnectionRequiredAndTransientConnection &&
               !(isRunningOnDevice && isWWAN && !isReachableOnWWAN)
    }

    var isReachableViaWiFi: Bool {
        return isReachable && isRunningOnDevice && !isWWAN
    }

    /// Flags that indicate the reachability of a network node name or address, including whether a connection is required, and whether some user intervention might be required when establishing a connection.
    var flags: SCNetworkReachabilityFlags? {
        guard let reachability = reachability else { return nil }
        var flags = SCNetworkReachabilityFlags()
        return withUnsafeMutablePointer(to: &flags) {
            SCNetworkReachabilityGetFlags(reachability, UnsafeMutablePointer($0))
            } ? flags : nil
    }

    /// compares the current flags with the previous flags and if changed posts a flagsChanged notification
    func flagsChanged() {
        guard let flags = flags, flags != reachabilityFlags else { return }
        reachabilityFlags = flags
        NotificationCenter.default.post(name: .flagsChanged, object: self)
    }

    /// The specified node name or address can be reached via a transient connection, such as PPP.
    var transientConnection: Bool { return flags?.contains(.transientConnection) == true }

    /// The specified node name or address can be reached using the current network configuration.
    var isReachable: Bool { return flags?.contains(.reachable) == true }

    /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set, the kSCNetworkReachabilityFlagsConnectionOnTraffic flag, kSCNetworkReachabilityFlagsConnectionOnDemand flag, or kSCNetworkReachabilityFlagsIsWWAN flag is also typically set to indicate the type of connection required. If the user must manually make the connection, the kSCNetworkReachabilityFlagsInterventionRequired flag is also set.
    var connectionRequired: Bool { return flags?.contains(.connectionRequired) == true }

    /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. Any traffic directed to the specified name or address will initiate the connection.
    var connectionOnTraffic: Bool { return flags?.contains(.connectionOnTraffic) == true }

    /// The specified node name or address can be reached using the current network configuration, but a connection must first be established.
    var interventionRequired: Bool { return flags?.contains(.interventionRequired) == true }

    /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. The connection will be established "On Demand" by the CFSocketStream programming interface (see CFStream Socket Additions for information on this). Other functions will not establish the connection.
    var connectionOnDemand: Bool { return flags?.contains(.connectionOnDemand) == true }

    /// The specified node name or address is one that is associated with a network interface on the current system.
    var isLocalAddress: Bool { return flags?.contains(.isLocalAddress) == true }

    /// Network traffic to the specified node name or address will not go through a gateway, but is routed directly to one of the interfaces in the system.
    var isDirect: Bool { return flags?.contains(.isDirect) == true }

    /// The specified node name or address can be reached via a cellular connection, such as EDGE or GPRS.
    var isWWAN: Bool { return flags?.contains(.isWWAN) == true }

    /// The specified node name or address can be reached using the current network configuration, but a connection must first be established. If this flag is set
    /// The specified node name or address can be reached via a transient connection, such as PPP.
    var isConnectionRequiredAndTransientConnection: Bool {
        return (flags?.intersection([.connectionRequired, .transientConnection]) == [.connectionRequired, .transientConnection]) == true
    }
}

func callout(reachability: SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
    guard let info = info else { return }
    DispatchQueue.main.async {
        Unmanaged<Reachability>
            .fromOpaque(info)
            .takeUnretainedValue()
            .flagsChanged()
    }
}

extension Notification.Name {
    static let flagsChanged = Notification.Name("FlagsChanged")
}

struct Network {
    static var reachability: Reachability!
    enum Status: String {
        case unreachable, wifi, wwan
    }
    enum Error: Swift.Error {
        case failedToSetCallout
        case failedToSetDispatchQueue
        case failedToCreateWith(String)
        case failedToInitializeWith(sockaddr_in)
    }
}

使用法

AppDelegate.swift didFinishLaunchingWithOptionsメソッドで初期化し、発生する可能性のあるエラーを処理します。

import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        do {
            try Network.reachability = Reachability(hostname: "www.google.com")
        }
        catch {
            switch error as? Network.Error {
            case let .failedToCreateWith(hostname)?:
                print("Network error:\nFailed to create reachability object With host named:", hostname)
            case let .failedToInitializeWith(address)?:
                print("Network error:\nFailed to initialize reachability object With address:", address)
            case .failedToSetCallout?:
                print("Network error:\nFailed to set callout")
            case .failedToSetDispatchQueue?:
                print("Network error:\nFailed to set DispatchQueue")
            case .none:
                print(error)
            }
        }
        return true
    }
}

そして、ビューコントローラのサンプル:

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default
            .addObserver(self,
                         selector: #selector(statusManager),
                         name: .flagsChanged,
                         object: nil)
        updateUserInterface()
    }
    func updateUserInterface() {
        switch Network.reachability.status {
        case .unreachable:
            view.backgroundColor = .red
        case .wwan:
            view.backgroundColor = .yellow
        case .wifi:
            view.backgroundColor = .green
        }
        print("Reachability Summary")
        print("Status:", Network.reachability.status)
        print("HostName:", Network.reachability.hostname ?? "nil")
        print("Reachable:", Network.reachability.isReachable)
        print("Wifi:", Network.reachability.isReachableViaWiFi)
    }
    @objc func statusManager(_ notification: Notification) {
        updateUserInterface()
    }
}

サンプルプロジェクト


2
if SCNetworkReachabilityGetFlags(…)xCodeは最新バージョンでBoolを返すため、 `== 0` を削除する必要があります。
メルビン

64
@NickMが言及したように、これは正しくありませんセルラー接続では機能しません。これは使わないでください。投票数が非常に多いことに驚いています。これはiOS 9の新機能かもしれませんが、そうは思いません。
ジョーダンスミス

1
IOS9では動作せず、非常に困難な方法を見つけました-アプリがストアにあるので... 100%正確でなくても動作する場合があると思いますが、うまくいかないこともあります。運が良ければ馬やわんわんに賭ける。
Nick M

2
@NickM-それはなぜ多くの賛成票を投じるのかを説明しています。@ Leo他の人が同じ罠にぶつかるのを防ぐために、iOS 9の回答を更新するのは良い考えかもしれません。iOS 9では(少なくとも状況によっては)機能しないことを確認できます。ただし、github.com / ashleymills / Reachability.swiftに変更しても正常に機能します。
ジョーダンスミス

1
ええ、iOS10ブランチで発売されたようです
Ace Green

225

Swift 3、Swift 4(携帯電話およびWi-Fiで動作):

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(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 = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }

        /* Only Working for WIFI
        let isReachable = flags == .reachable
        let needsConnection = flags == .connectionRequired

        return isReachable && !needsConnection
        */

        // Working for Cellular and WIFI
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        let ret = (isReachable && !needsConnection)

        return ret

    }
}

使用法:

if Reachability.isConnectedToNetwork(){
    print("Internet Connection Available!")
}else{
    print("Internet Connection not Available!")
}

3
このソリューション+ CoreTelephony(CTTelephonyNetworkInfo()。currentRadioAccessTechnology)は、現在のネットワークタイプを取得するための最良のソリューションであり、サードパーティのライブラリに依存する必要はありません。
アレハンドロヒメネスアグド

3
Swift 3.1でセルラーとWiFiに対応!iPhone 6および7で動作確認済み。携帯電話がオフの場合、「.. Connection not Available」と表示されます。機内モードをオンにすると、同じ「...利用不可」になります。セルラーをオフにしてwifiをオンにすると、「..接続が利用可能」になります。最後に、wifiをオフにしてセルラーをオンにすると、「..接続が利用可能」になります。私のセルラー接続がLTEであることに注意してください
ブライアン

1
こんにちは、これは物理デバイスのiOS 11、機内モードでは機能しません。機内モードに設定されている場合、isReachableは引き続きtrueになります。
ローレンスタン

3
これは、すべてのシナリオで私にとって完璧に機能しています。また、iPhone 6にiOSの12ランニングでテストしています
r3dm4n

3
インターネットに接続せずにWi-Fiネットワークに接続している場合、これは機能しません
Nathan Barreto 2018

58

プロジェクト内に新しいSwiftファイルを作成し、名前を付けReachability.swiftます。次のコードをカットアンドペーストしてクラスを作成します。

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(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() {
    println("Internet connection OK")
} else {
    println("Internet connection FAILED")
}

ユーザーがインターネットに接続していない場合は、警告ダイアログを表示して通知することができます。

if Reachability.isConnectedToNetwork() {
    println("Internet connection OK")
} else {
    println("Internet connection FAILED")
    var alert = UIAlertView(title: "No Internet Connection", message: "Make sure your device is connected to the internet.", delegate: nil, cancelButtonTitle: "OK")
    alert.show()
}

説明:

再利用可能なパブリッククラスと、プロジェクトのどこでもインターネット接続を確認するために使用できるメソッドを作成しています。FoundationとSystem Configurationフレームワークを追加する必要があります。

パブリッククラスReachabilityでは、このメソッドisConnectedToNetwork() -> Bool { }はインターネット接続に関するブール値を返します。ifループを使用して、必要なアクションをケースで実行します。これで十分だと思います。乾杯!


4
解決策を提示するときは、少し説明してください。ソリューションを提供することは重要ではありませんが、読者にソリューションとその概念を理解してもらうことがより重要です。
G.Abhisek

1
iOSプログラミングは初めてです。目的のためにC構造体を初期化する必要があるのはなぜですか。どのような場合にC構造体を使用できますか?
G.Abhisek

1
私はこれを「viewdidload」にテストのためだけに置きました。私はアプリを開いてOKですが、インターネットがありますが、インターネットを撃墜すると、インターネットが表示され続けます...これは永続的ですか?または私は毎回「アクションを呼び出す」必要がありますか?
Daniel Arantes Loverde、2016

16
@AlvinGeorgeこれは、セルラーネットワークに接続されている場合は機能しません。これはwifiを使用している場合にのみ機能します。他の誰かに-あなたはあなたのアプリでこれを使いたくない!@アルビン-答えを更新するか、削除することを提案できますか?19票の投票で、同じ罠に陥る可能性のある他の開発者に誤解を招く可能性があります。
ジョーダンスミス

@Jordan:このメソッドは、ネットワークステータスにデフォルトのAppleフレームワークを使用しています。新しいiOSバージョンで変更される場合があります。したがって、Ashely Millの到達可能性クラスを確認して実装することをお勧めします。依存関係のない実装を行い、上記のリンクを共有しました。ぜひご覧ください。
AG

56

誰かがすでにAlamofireを使用して いる場合-

struct Connectivity {
  static let sharedInstance = NetworkReachabilityManager()!
  static var isConnectedToInternet:Bool {
      return self.sharedInstance.isReachable
    }
}

使用法:

if Connectivity.isConnectedToInternet {
     print("Connected")
 } else {
     print("No Internet")
}

1
Alamofireのドキュメントから:> NetworkReachabilityManagerクラスは、WWANとWiFiネットワークインターフェースの両方のホストとアドレスの到達可能性の変更をリッスンします。>到達可能性を使用して、ネットワーク操作が失敗した理由に関する背景情報を判断したり、接続が確立されたときにネットワーク要求を再試行したりできます。到達可能性を確立するために最初の要求が必要になる可能性があるため、ユーザーがネットワーク要求を開始するのを防ぐために使用しないでください。
fespinozacast

1
@fespinozacastも、あなたはでインターネット接続コードを確認することができますNetworkReachabilityManager.swift :)全く問題あり
ジャック・

15

Cocoa Pods / Dependancy ManagerなしでAshley MillのReachabilityクラスを実装することを確認しました。アイデアは、プロジェクトでReachability依存関係を自由にすることです。

Xcode 7.2-Swift 2.1

1)https://github.com/ashleymills/Reachability.swift。Reachabilityクラスをプロジェクトにダウンロードして追加します。

注:追加する際は、[必要に応じてアイテムをコピーする]がチェックされていることを確認してください。

2)AppManager.swiftクラスを作成します。このクラスは、パブリックメソッドとデータが追加され、任意のVCで利用できるパブリックモデルクラスとして機能します。

//  AppManager.swift

import UIKit
import Foundation

class AppManager: NSObject{
    var delegate:AppManagerDelegate? = nil
    private var _useClosures:Bool = false
    private var reachability: Reachability?
    private var _isReachability:Bool = false
    private var _reachabiltyNetworkType :String?

    var isReachability:Bool {
        get {return _isReachability}
    }  
   var reachabiltyNetworkType:String {
    get {return _reachabiltyNetworkType! }
   }   




    // Create a shared instance of AppManager
    final  class var sharedInstance : AppManager {
        struct Static {
            static var instance : AppManager?
        }
        if !(Static.instance != nil) {
            Static.instance = AppManager()

        }
        return Static.instance!
    }

    // Reachability Methods
    func initRechabilityMonitor() {
        print("initialize rechability...")
        do {
            let reachability = try Reachability.reachabilityForInternetConnection()
            self.reachability = reachability
        } catch ReachabilityError.FailedToCreateWithAddress(let address) {
            print("Unable to create\nReachability with address:\n\(address)")
            return
        } catch {}
        if (_useClosures) {
            reachability?.whenReachable = { reachability in
                self.notifyReachability(reachability)
            }
            reachability?.whenUnreachable = { reachability in
                self.notifyReachability(reachability)
            }
        } else {
            self.notifyReachability(reachability!)
        }

        do {
            try reachability?.startNotifier()
        } catch {
            print("unable to start notifier")
            return
        }


    }        
    private func notifyReachability(reachability:Reachability) {
        if reachability.isReachable() {
            self._isReachability = true

//Determine Network Type 
      if reachability.isReachableViaWiFi() {   
        self._reachabiltyNetworkType = CONNECTION_NETWORK_TYPE.WIFI_NETWORK.rawValue
      } else {
        self._reachabiltyNetworkType = CONNECTION_NETWORK_TYPE.WWAN_NETWORK.rawValue
      }

        } else {
            self._isReachability = false
self._reachabiltyNetworkType = CONNECTION_NETWORK_TYPE.OTHER.rawValue

        }

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged:", name: ReachabilityChangedNotification, object: reachability)
    }
    func reachabilityChanged(note: NSNotification) {
        let reachability = note.object as! Reachability
        dispatch_async(dispatch_get_main_queue()) {
            if (self._useClosures) {
                self.reachability?.whenReachable = { reachability in
                    self.notifyReachability(reachability)
                }
                self.reachability?.whenUnreachable = { reachability in
                    self.notifyReachability(reachability)
                }
            } else {
                self.notifyReachability(reachability)
            }
            self.delegate?.reachabilityStatusChangeHandler(reachability)
        }
    }
    deinit {
        reachability?.stopNotifier()
        if (!_useClosures) {
            NSNotificationCenter.defaultCenter().removeObserver(self, name: ReachabilityChangedNotification, object: nil)
        }
    }
}

3)デリゲートクラスを作成します。デリゲートメソッドを使用して、接続ステータスを通知します。

//  Protocols.swift

import Foundation
@objc protocol AppManagerDelegate:NSObjectProtocol {

    func reachabilityStatusChangeHandler(reachability:Reachability)
}

4)UIViewController(継承メソッド)の親クラスを作成します。親クラスには、すべての子VCにアクセスできるメソッドがあります。

//  UIappViewController.swift

    import UIKit

    class UIappViewController: UIViewController,AppManagerDelegate {
        var manager:AppManager = AppManager.sharedInstance

        override func viewDidLoad() {
            super.viewDidLoad()
            manager.delegate = self
        }
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
        func reachabilityStatusChangeHandler(reachability: Reachability) {
            if reachability.isReachable() {
                print("isReachable")
            } else {
                print("notReachable")
            }
        }
    }

5)AppDelegateでリアルタイムのインターネット接続監視を開始します。

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    AppManager.sharedInstance.initRechabilityMonitor()
return true
}

6)定数列挙値を格納するためにSwiftファイル名AppReferenceを追加しました。

//  AppReference.swift

import Foundation

enum CONNECTION_NETWORK_TYPE : String {

  case WIFI_NETWORK = "Wifi"
  case WWAN_NETWORK = "Cellular"
  case OTHER = "Other"

}

7)ViewControllerで(例:ネットワークが利用可能な場合にのみAPIを呼び出したい)

//  ViewController.swift

        import UIKit

class ViewController: UIappViewController {
  var reachability:Reachability?

  override func viewDidLoad() {
    super.viewDidLoad()
    manager.delegate = self

    if(AppManager.sharedInstance.isReachability)
    {
      print("net available")
      //call API from here.

    } else {
      dispatch_async(dispatch_get_main_queue()) {
        print("net not available")
        //Show Alert
      }
    }


    //Determine Network Type
    if(AppManager.sharedInstance.reachabiltyNetworkType == "Wifi")
    {
      print(".Wifi")
    }
    else if (AppManager.sharedInstance.reachabiltyNetworkType == "Cellular")
    {
      print(".Cellular")
    }
    else {
      dispatch_async(dispatch_get_main_queue()) {
        print("Network not reachable")
      }
    }

  }
  override func viewWillAppear(animated: Bool) {
  }
  override func didReceiveMemoryWarning() {
  }
}

サンプルは、https://github.com/alvinreuben/Reachability-Sampleからダウンロードできます

Swift 3.1にアップグレード-https ://github.com/alvinvgeorge/Reachability-UpgradedToSwift3


ステップ4 ... UIappViewController.swiftで、なぜこのクラスが必要なのですか?
Learn2Code

UIappViewController.swiftはUICollectionViewControllerでは機能しないため、UICollectionViewControllerのビューがある場合、UIappViewControllerを継承できません!?
Learn2Code

12

AppleはiOS12にNetwork Frameworkを導入しました。

import Foundation
import Network

class NetworkReachability {

   var pathMonitor: NWPathMonitor!
   var path: NWPath?
   lazy var pathUpdateHandler: ((NWPath) -> Void) = { path in
    self.path = path
    if path.status == NWPath.Status.satisfied {
        print("Connected")
    } else if path.status == NWPath.Status.unsatisfied {
        print("unsatisfied")
    } else if path.status == NWPath.Status.requiresConnection {
        print("requiresConnection")
    } 
}

let backgroudQueue = DispatchQueue.global(qos: .background)

init() {
    pathMonitor = NWPathMonitor()
    pathMonitor.pathUpdateHandler = self.pathUpdateHandler
    pathMonitor.start(queue: backgroudQueue)
   } 

 func isNetworkAvailable() -> Bool {
        if let path = self.path {
           if path.status == NWPath.Status.satisfied {
            return true
          }
        }
       return false
   }
 }

var path:NWPath?はありません。このプロパティをどのように初期化しますか?
Vitya Shurapov

@VityaShurapovパスを割り当てることにより、pathUpdateHandlerブロックに入ります。
Yogendra Singh

これは奇妙に見えますが、ラップトップのwifiをオフにしてからオンにすると、コールバックが発生しますが、「満たされていない」と表示され、その後コールバックが呼び出されないことがわかりました(少なくともシミュレータ上では)。
zaitsman

セルラーがオン/オフを繰り返すとき、ハンドラーはオン/オフのために一度だけトリガーします。WiFiがオン/オフを繰り返すと、オン/オフの2つの同じトリガーを取得します(すべてのプロパティは同じです)。何故ですか?
geohei

pathUpdateHandlerとの強い参照を導入し、それを解決するためにself追加[weak self]します:)
Andrea de Marco

11

これをSwift-5 +に使用します

import Foundation
import UIKit
import SystemConfiguration

public class InternetConnectionManager {


    private init() {

    }

    public static func isConnectedToNetwork() -> Bool {

        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        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.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        return (isReachable && !needsConnection)
    }

}

使用法:

InternetConnectionManager.isConnectedToNetwork{
    print("Connected")
}else{
    print("Not Connected")
}

または、これframeworkをさらに使用するだけですUtilitiesリンク


@ DocAsh59 :)ようこそ!幸せなコーディング!
Jamil Hasnine Tamim

使い方がわかりません。コンパイラーは、「引数を取らない呼び出しに渡された引数」というエラーを表示します。
ローランドラリオット

1
@RolandLariotte-"InternetConnectionManager"という名前のプロジェクトでクラスを作成し、必要な場所から呼び出します。
Jamil Hasnine Tamim

完璧に動作します。Combineを使用してAnyPublisher <Bool、Never>を返すことで、このコードがより反応的になると思いますか?このように書いてもらえますか?
ローランドラリオット

@RolandLariotteそうだね。後で別のコードを書きます。感謝し、サポートすることを忘れないでください!:)
Jamil Hasnine Tamim

7

これを自分で理解しただけです。

Xcode:7.3.1、iOS 9.3.3

プロジェクトでashleymills / Reachability.swiftをReachability.swiftとして使用して、次の関数を作成しました。

func hasConnectivity() -> Bool {
    do {
        let reachability: Reachability = try Reachability.reachabilityForInternetConnection()
        let networkStatus: Int = reachability.currentReachabilityStatus.hashValue

        return (networkStatus != 0)
    }
    catch {
        // Handle error however you please
        return false
    }
}

hasConnectivity()接続を確認する必要がある場所に電話してください。これはWifiとCellularで機能します。


ashleymillsのReachability.swiftを追加すると、サイト間を移動する必要がなくなります。

Copyright (c) 2014, Ashley Mills
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/

// Reachability.swift version 2.2beta2

import SystemConfiguration
import Foundation

public enum ReachabilityError: ErrorType {
    case FailedToCreateWithAddress(sockaddr_in)
    case FailedToCreateWithHostname(String)
    case UnableToSetCallback
    case UnableToSetDispatchQueue
}

public let ReachabilityChangedNotification = "ReachabilityChangedNotification"

func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
    let reachability = Unmanaged<Reachability>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()

    dispatch_async(dispatch_get_main_queue()) {
        reachability.reachabilityChanged(flags)
    }
}


public class Reachability: NSObject {

    public typealias NetworkReachable = (Reachability) -> ()
    public typealias NetworkUnreachable = (Reachability) -> ()

    public enum NetworkStatus: CustomStringConvertible {

        case NotReachable, ReachableViaWiFi, ReachableViaWWAN

        public var description: String {
            switch self {
            case .ReachableViaWWAN:
                return "Cellular"
            case .ReachableViaWiFi:
                return "WiFi"
            case .NotReachable:
                return "No Connection"
            }
        }
    }

    // MARK: - *** Public properties ***
    public var whenReachable: NetworkReachable?
    public var whenUnreachable: NetworkUnreachable?
    public var reachableOnWWAN: Bool
    public var notificationCenter = NSNotificationCenter.defaultCenter()

    public var currentReachabilityStatus: NetworkStatus {
        if isReachable() {
            if isReachableViaWiFi() {
                return .ReachableViaWiFi
            }
            if isRunningOnDevice {
                return .ReachableViaWWAN
            }
        }
        return .NotReachable
    }

    public var currentReachabilityString: String {
        return "\(currentReachabilityStatus)"
    }

    private var previousFlags: SCNetworkReachabilityFlags?

    // MARK: - *** Initialisation methods ***

    required public init(reachabilityRef: SCNetworkReachability) {
        reachableOnWWAN = true
        self.reachabilityRef = reachabilityRef
    }

    public convenience init(hostname: String) throws {

        let nodename = (hostname as NSString).UTF8String
        guard let ref = SCNetworkReachabilityCreateWithName(nil, nodename) else { throw ReachabilityError.FailedToCreateWithHostname(hostname) }

        self.init(reachabilityRef: ref)
    }

    public class func reachabilityForInternetConnection() throws -> Reachability {

        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)

        guard let ref = withUnsafePointer(&zeroAddress, {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }) else { throw ReachabilityError.FailedToCreateWithAddress(zeroAddress) }

        return Reachability(reachabilityRef: ref)
    }

    public class func reachabilityForLocalWiFi() throws -> Reachability {

        var localWifiAddress: sockaddr_in = sockaddr_in(sin_len: __uint8_t(0), sin_family: sa_family_t(0), sin_port: in_port_t(0), sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        localWifiAddress.sin_len = UInt8(sizeofValue(localWifiAddress))
        localWifiAddress.sin_family = sa_family_t(AF_INET)

        // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
        let address: UInt32 = 0xA9FE0000
        localWifiAddress.sin_addr.s_addr = in_addr_t(address.bigEndian)

        guard let ref = withUnsafePointer(&localWifiAddress, {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }) else { throw ReachabilityError.FailedToCreateWithAddress(localWifiAddress) }

        return Reachability(reachabilityRef: ref)
    }

    // MARK: - *** Notifier methods ***
    public func startNotifier() throws {

        guard !notifierRunning else { return }

        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque())

        if !SCNetworkReachabilitySetCallback(reachabilityRef!, callback, &context) {
            stopNotifier()
            throw ReachabilityError.UnableToSetCallback
        }

        if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef!, reachabilitySerialQueue) {
            stopNotifier()
            throw ReachabilityError.UnableToSetDispatchQueue
        }

        // Perform an intial check
        dispatch_async(reachabilitySerialQueue) { () -> Void in
            let flags = self.reachabilityFlags
            self.reachabilityChanged(flags)
        }

        notifierRunning = true
    }

    public func stopNotifier() {
        defer { notifierRunning = false }
        guard let reachabilityRef = reachabilityRef else { return }

        SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
        SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
    }

    // MARK: - *** Connection test methods ***
    public func isReachable() -> Bool {
        let flags = reachabilityFlags
        return isReachableWithFlags(flags)
    }

    public func isReachableViaWWAN() -> Bool {

        let flags = reachabilityFlags

        // Check we're not on the simulator, we're REACHABLE and check we're on WWAN
        return isRunningOnDevice && isReachable(flags) && isOnWWAN(flags)
    }

    public func isReachableViaWiFi() -> Bool {

        let flags = reachabilityFlags

        // Check we're reachable
        if !isReachable(flags) {
            return false
        }

        // Must be on WiFi if reachable but not on an iOS device (i.e. simulator)
        if !isRunningOnDevice {
            return true
        }

        // Check we're NOT on WWAN
        return !isOnWWAN(flags)
    }

    // MARK: - *** Private methods ***
    private var isRunningOnDevice: Bool = {
        #if (arch(i386) || arch(x86_64)) && os(iOS)
            return false
        #else
            return true
        #endif
    }()

    private var notifierRunning = false
    private var reachabilityRef: SCNetworkReachability?
    private let reachabilitySerialQueue = dispatch_queue_create("uk.co.ashleymills.reachability", DISPATCH_QUEUE_SERIAL)

    private func reachabilityChanged(flags: SCNetworkReachabilityFlags) {

        guard previousFlags != flags else { return }

        if isReachableWithFlags(flags) {
            if let block = whenReachable {
                block(self)
            }
        } else {
            if let block = whenUnreachable {
                block(self)
            }
        }

        notificationCenter.postNotificationName(ReachabilityChangedNotification, object:self)

        previousFlags = flags
    }

    private func isReachableWithFlags(flags: SCNetworkReachabilityFlags) -> Bool {

        if !isReachable(flags) {
            return false
        }

        if isConnectionRequiredOrTransient(flags) {
            return false
        }

        if isRunningOnDevice {
            if isOnWWAN(flags) && !reachableOnWWAN {
                // We don't want to connect when on 3G.
                return false
            }
        }

        return true
    }

    // WWAN may be available, but not active until a connection has been established.
    // WiFi may require a connection for VPN on Demand.
    private func isConnectionRequired() -> Bool {
        return connectionRequired()
    }

    private func connectionRequired() -> Bool {
        let flags = reachabilityFlags
        return isConnectionRequired(flags)
    }

    // Dynamic, on demand connection?
    private func isConnectionOnDemand() -> Bool {
        let flags = reachabilityFlags
        return isConnectionRequired(flags) && isConnectionOnTrafficOrDemand(flags)
    }

    // Is user intervention required?
    private func isInterventionRequired() -> Bool {
        let flags = reachabilityFlags
        return isConnectionRequired(flags) && isInterventionRequired(flags)
    }

    private func isOnWWAN(flags: SCNetworkReachabilityFlags) -> Bool {
        #if os(iOS)
            return flags.contains(.IsWWAN)
        #else
            return false
        #endif
    }
    private func isReachable(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.Reachable)
    }
    private func isConnectionRequired(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.ConnectionRequired)
    }
    private func isInterventionRequired(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.InterventionRequired)
    }
    private func isConnectionOnTraffic(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.ConnectionOnTraffic)
    }
    private func isConnectionOnDemand(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.ConnectionOnDemand)
    }
    func isConnectionOnTrafficOrDemand(flags: SCNetworkReachabilityFlags) -> Bool {
        return !flags.intersect([.ConnectionOnTraffic, .ConnectionOnDemand]).isEmpty
    }
    private func isTransientConnection(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.TransientConnection)
    }
    private func isLocalAddress(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.IsLocalAddress)
    }
    private func isDirect(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.IsDirect)
    }
    private func isConnectionRequiredOrTransient(flags: SCNetworkReachabilityFlags) -> Bool {
        let testcase:SCNetworkReachabilityFlags = [.ConnectionRequired, .TransientConnection]
        return flags.intersect(testcase) == testcase
    }

    private var reachabilityFlags: SCNetworkReachabilityFlags {

        guard let reachabilityRef = reachabilityRef else { return SCNetworkReachabilityFlags() }

        var flags = SCNetworkReachabilityFlags()
        let gotFlags = withUnsafeMutablePointer(&flags) {
            SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0))
        }

        if gotFlags {
            return flags
        } else {
            return SCNetworkReachabilityFlags()
        }
    }

    override public var description: String {

        var W: String
        if isRunningOnDevice {
            W = isOnWWAN(reachabilityFlags) ? "W" : "-"
        } else {
            W = "X"
        }
        let R = isReachable(reachabilityFlags) ? "R" : "-"
        let c = isConnectionRequired(reachabilityFlags) ? "c" : "-"
        let t = isTransientConnection(reachabilityFlags) ? "t" : "-"
        let i = isInterventionRequired(reachabilityFlags) ? "i" : "-"
        let C = isConnectionOnTraffic(reachabilityFlags) ? "C" : "-"
        let D = isConnectionOnDemand(reachabilityFlags) ? "D" : "-"
        let l = isLocalAddress(reachabilityFlags) ? "l" : "-"
        let d = isDirect(reachabilityFlags) ? "d" : "-"

        return "\(W)\(R) \(c)\(t)\(i)\(C)\(D)\(l)\(d)"
    }

    deinit {
        stopNotifier()

        reachabilityRef = nil
        whenReachable = nil
        whenUnreachable = nil
    }
}

@ Xitcod13これは4Gネットワ​​ークで動作します。そうは言っても、プリフライトをテストしないことをお勧めします。Reachability.swiftテストケースを使用する代わりに、接続の試行でスローされた例外を処理します。
cmeadows


Reachabilty.swiftはSwift 3に問題があります
Famic Tech '24

Swift 3でlet reachability: Reachability = try Reachability.reachabilityForInternetConnection()let reachability: Reachability = try Reachability()!
正常に動作し

7

それはあなたの質問に直接答えることはしませんが、私は最近Appleがこの話をしたことを述べたいと思います:

https://developer.apple.com/videos/play/wwdc2018/714/

09:55頃、彼はあなたが尋ねているこのようなことをすることについて話します:

  1. 接続を確認する
  2. 接続の場合->何かをする
  3. 接続がない場合->他に何かします(待機?再試行?)

ただし、これにはいくつかの落とし穴があります。

  • ステップ2で接続があると表示されているが、0.5秒後に接続されていない場合はどうなりますか?
  • ユーザーがプロキシの背後にいる場合
  • 最後に重要なことですが、ここでいくつかの回答が接続権を決定できない場合はどうなりますか?(接続をすばやく切り替えてwi-fiに移動し、電源をオフにした場合(複雑にしてください)、接続を取得したかどうかを正確に判断することはほとんど不可能です)。
  • ビデオからの引用:「将来のオペレーションが成功するかどうかを保証する方法はありません」

Appleによると、次のポイントがいくつかのベストプラクティスです。

話によると、サーバーにリクエストを送信する時点では正確でない可能性があるため、インターネット接続を取得したかどうかを事前に確認する理由はありません


2

NSTimerとAlamofireを使用して独自のソリューションを作成しました。

import Alamofire

public class ConnectionHelper: NSObject {
    var request: Alamofire.Request?

    func isInternetConnected(completionHandler: Bool -> Void) {
        NSTimer.scheduledTimerWithTimeInterval(5.0, target: self, selector: "requestTimeout", userInfo: nil, repeats: false)

        request = Alamofire
            .request(
                Method.HEAD,
                "http://www.testurl.com"
            )
            .response { response in
                if response.3?.code == -999 {
                    completionHandler(
                        false
                    )
                } else {
                    completionHandler(
                        true
                    )
                }
        }
    }

    func requestTimeout() {
        request!.cancel()
    }
}

NSTimerはタイムアウトとして使用され、Alamofireタイムアウトを使用した信頼できない結果のために使用されました。リクエストは、自分のサーバーや、依存するサービスをホストしているサーバーなど、信頼できると信頼できるURLに対して行う必要があります。

タイマーが期限切れになると、リクエストはキャンセルされ、完了ハンドラを使用して結果が返されます。

使用法:

ConnectionHelper().isInternetConnected() { internetConnected in
    if internetConnected {
        // Connected
    } else {
        // Not connected
    }
}

1
Webサイトサーバーがダウンした場合はどうなりますか?
TechBee 2016

その後requestTimeout()、指定されたタイムアウトに達した後に呼び出されます
Mark Tickner、

マークありがとう!あなたのアプローチは一般的でなければなりません!!
TechBee 2016

1
どのように?使用しているサイトは?使用されているサイトは、アプリが依存しているサイトであるという考え方になります
Mark Tickner、

ネットワーク接続を確立し、応答が返されるかどうかを確認することは、おそらくお勧めできません。What if if質問が
GoodSp33d

2

Alamofireを使用している場合は、次のようなことができます。

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.timeoutIntervalForRequest = 15 //Set timeouts in sec
configuration.timeoutIntervalForResource = 15

let alamoFireManager = Alamofire.Manager(configuration:configuration)
alamoFireManager?.request(.GET, "https://yourURL.com", parameters: headers, encoding: .URL)
                     .validate()
                              .responseJSON { response in

                                if let error = response.result.error {
                                   switch error.code{
                                    case -1001:
                                        print("Slow connection")
                                        return
                                    case -1009:
                                        print("No Connection!")
                                        return
                                    default: break
                                    }
                                }

2

スウィフト5

import SystemConfiguration    

protocol Utilities {}
extension NSObject: Utilities {
    enum ReachabilityStatus {
        case notReachable
        case reachableViaWWAN
        case reachableViaWiFi
    }

    var currentReachabilityStatus: ReachabilityStatus {

        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 .notReachable
        }

        var flags: SCNetworkReachabilityFlags = []
        if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
            return .notReachable
        }

        if flags.contains(.reachable) == false {
            // The target host is not reachable.
            return .notReachable
        }
        else if flags.contains(.isWWAN) == true {
            // WWAN connections are OK if the calling application is using the CFNetwork APIs.
            return .reachableViaWWAN
        }
        else if flags.contains(.connectionRequired) == false {
            // If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi...
            return .reachableViaWiFi
        }
        else if (flags.contains(.connectionOnDemand) == true || flags.contains(.connectionOnTraffic) == true) && flags.contains(.interventionRequired) == false {
            // The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed
            return .reachableViaWiFi
        }
        else {
            return .notReachable
        }
    }
}

どの方法でも、以下の条件を使用します

if currentReachabilityStatus == .notReachable {
    // Network Unavailable
 } else {
    // Network Available
 }

1

ここに、lib(Reachability.swift)を使用したSwift 2.3の私の解決策

に移動してPodfile追加します:

pod 'ReachabilitySwift', '~> 2.4' // swift 2.3

次にあなたにterminal

pod install

次に、新しいファイルReachabilityManagerを作成し、以下のコードを追加します。

import Foundation
import ReachabilitySwift

enum ReachabilityManagerType {
    case Wifi
    case Cellular
    case None
}

class ReachabilityManager {
    static let sharedInstance = ReachabilityManager()

    private var reachability: Reachability!
    private var reachabilityManagerType: ReachabilityManagerType = .None


    private init() {
        do {
            self.reachability = try Reachability.reachabilityForInternetConnection()
        } catch {
            print("Unable to create Reachability")
            return
        }

        NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ReachabilityManager.reachabilityChanged(_:)),name: ReachabilityChangedNotification,object: self.reachability)
        do{
            try self.reachability.startNotifier()
        }catch{
            print("could not start reachability notifier")
        }
    }

    @objc private func reachabilityChanged(note: NSNotification) {

        let reachability = note.object as! Reachability

        if reachability.isReachable() {
            if reachability.isReachableViaWiFi() {
                self.reachabilityManagerType = .Wifi
            } else {
                self.reachabilityManagerType = .Cellular
            }
        } else {
            self.reachabilityManagerType = .None
        }
    }
}

extension ReachabilityManager {

    func isConnectedToNetwork() -> Bool {
        return reachabilityManagerType != .None
    }

}

使い方:

あなたの中に行きAppDelegate.swift、以下のコードを追加してください:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
     ReachabilityManager.sharedInstance
}

次に、デバイスがインターネットに接続されているかどうかを確認する場合は、次の操作を行います。

if ReachabilityManager.sharedInstance.isConnectedToNetwork() {
   // Connected
} else {
  // Not connected
}

1

電話がネットワークに接続されているかどうかを直接判断することはできませんが、最も簡単な(最もクリーンな?)ソリューションは、Googleまたは他のサーバーに「ping」することです(電話がネットワークに接続されていないと不可能です)。 ):

private var urlSession:URLSession = {
    var newConfiguration:URLSessionConfiguration = .default
    newConfiguration.waitsForConnectivity = false
    newConfiguration.allowsCellularAccess = true
    return URLSession(configuration: newConfiguration)
}()

public func canReachGoogle() -> Bool
{
    let url = URL(string: "https://8.8.8.8")
    let semaphore = DispatchSemaphore(value: 0)
    var success = false
    let task = urlSession.dataTask(with: url!)
    { data, response, error in
        if error != nil
        {
            success = false
        }
        else
        {
            success = true
        }
        semaphore.signal()
    }

    task.resume()
    semaphore.wait()

    return success
}

サーバーがダウンしているか、IPをブロックしているのではないかと心配している場合は、常に同じ方法で複数のサーバーにpingを実行し、到達可能なサーバーがあるかどうかを返すことができます。または、この目的のためだけに専用サーバーをセットアップしてもらいます。


0

以下のコードを使用して、セルラーネットワークとwifiの両方のインターネット接続を確認できます。言語-Swift 3.0

import UIKit
import Foundation
import SystemConfiguration

class NetworkConnection: UIViewController {

  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(MemoryLayout.size(ofValue: zeroAddress))
    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 = SCNetworkReachabilityFlags(rawValue: 0)
    if SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) == false {
      return false
    }
    let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
    let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
    return (isReachable && !needsConnection)
  }

  class func checkConnection(sender:UIViewController){
    if NetworkConnection.isConnectedToNetwork() == true {
      print("Connected to the internet")
      //  Do something
    } else {
      print("No internet connection")
      let alertController = UIAlertController(title: "No Internet Available", message: "", preferredStyle: UIAlertControllerStyle.alert)
      let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default){(result:UIAlertAction) -> Void in
        return
      }
      alertController.addAction(okAction)
      sender.present(alertController, animated: true, completion: nil)
      //  Do something
    }
  }

}

0

Swift 3では、RAJAMOHAN-Sソリューションからの到達可能性だけを使用することはできませんでした。WiFiがあるがインターネットがない場合は「true」が返されるためです。したがって、URLSessionクラスと完了ハンドラーを介して2番目の検証を実装しました。

ここにクラス全体があります。

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(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 = SCNetworkReachabilityFlags(rawValue: 0)
if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
  return false
}

// Working for Cellular and WIFI
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
let ret = (isReachable && !needsConnection)

return ret
}



class func isInternetAvailable(webSiteToPing: String?, completionHandler: @escaping (Bool) -> Void) {

// 1. Check the WiFi Connection
guard isConnectedToNetwork() else {
  completionHandler(false)
  return
}

// 2. Check the Internet Connection
var webAddress = "https://www.google.com" // Default Web Site
if let _ = webSiteToPing {
  webAddress = webSiteToPing!
}

guard let url = URL(string: webAddress) else {
  completionHandler(false)
  print("could not create url from: \(webAddress)")
  return
}

let urlRequest = URLRequest(url: url)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest, completionHandler: { (data, response, error) in
  if error != nil || response == nil {
    completionHandler(false)
  } else {
    completionHandler(true)
  }
})

  task.resume()
}
}

そして、あなたはこれをこのように呼びます、例えば:

Reachability.isInternetAvailable(webSiteToPing: nil) { (isInternetAvailable) in
  guard isInternetAvailable else {
    // Inform user for example
    return
  }

  // Do some action if there is Internet
}

0

これは私のバージョンです。本質的には、新しいことは何もありません。UIDeviceにバインドしました。

import UIKit
import SystemConfiguration

extension UIDevice {

    open class var isConnectedToNetwork: Bool {
        get {
            var zeroAddress = sockaddr_in()
            zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
            zeroAddress.sin_family = sa_family_t(AF_INET)

            guard
                let defaultRouteReachability: SCNetworkReachability = withUnsafePointer(to: &zeroAddress, {
                    $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
                        SCNetworkReachabilityCreateWithAddress(nil, $0)
                    }
                }),
                var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags() as SCNetworkReachabilityFlags?,
                SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags)
                else { return false }

            return flags.contains(.reachable) && !flags.contains(.connectionRequired)
        }
    }

}

print("Network status availability: " + ( UIDevice.isConnectedToNetwork ? "true" : "false" ))

0
struct Connectivity {
        static let sharedInstance = NetworkReachabilityManager()!
        static var isConnectedToInternet:Bool {
            return self.sharedInstance.isReachable
        }
    }

今それを呼び出します

if Connectivity.isConnectedToInternet{
            call_your_methods_here()
        }else{
            show_alert_for_noInternet()
        }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.