【问题标题】:Check iOS app internet connection after app is launched应用启动后检查 iOS 应用互联网连接
【发布时间】:2017-06-12 10:49:59
【问题描述】:

我正在制作一个需要 API 请求的应用。如果以任何方式(移动连接、wifi 等)没有互联网连接,我的应用程序中就没有使用。因此,每当我的应用中没有互联网连接时,我都会尝试填充活动指示器视图。

我发现了非常好的 Stack Overflow 帖子,它可以让我检查设备的连接状态 (Check for internet connection with Swift)。

但是,我不确定一件事。如果我在 AppDelegate didFinishLaunchingWithOptions 方法中放置了一个检查 iOS 设备网络连接的方法,那么它只会在应用启动时检查,对吗?我想在没有连接时显示活动指示器视图。为了方便这个功能,我想知道将方法放在应用程序中的哪个地方最有意义。

【问题讨论】:

  • 您可以创建一个函数并在进行任何 API 调用之前检查互联网连接是否可用
  • @Coder,每次打电话之前检查连接会很昂贵吗??
  • 这个视频做了一个功能,你可以通过调用它来检查项目中任何地方的互联网连接。链接:youtube.com/…
  • 我已经更新了我的答案,请检查。希望这会有所帮助

标签: ios swift networking


【解决方案1】:

有一个很棒的库不适合使用它。它只是这个库的一小部分。使用alamofire

怎么做?

您只能使用此代码检查可达性。

let reachabilityManager = Alamofire.NetworkReachabilityManager(host: "www.apple.com")

func listenForReachability() {
    self.reachabilityManager?.listener = { status in
        print("Network Status Changed: \(status)")
        switch status {
        case .NotReachable:
            //Show error state
        case .Reachable(_), .Unknown:
            //Hide error state
        }
    }

    self.reachabilityManager?.startListening()
}

您可以将此代码用作单例。请记住保留可达性管理器参考。

【讨论】:

    【解决方案2】:

    创建以下 2 个类文件 单例类

    import Foundation
    import UIKit
    
    class Constants:NSObject{
    
    
        let defaults = UserDefaults.standard
        var isNetworkon:Bool?
    
    
    
        override init() {
            super.init()
            CLIENTKEY = ""
        }
    
        class var sharedInstance: Constants {
            struct Singleton {
                static let instance = Constants()
            }
            return Singleton.instance
        }
    
        func checkNetwork(vc:UIViewController) -> Bool {
            NotificationCenter.default.addObserver(self, selector: #selector(networkStatusChanged(_:)), name: NSNotification.Name(rawValue: ReachabilityStatusChangedNotification), object: nil)
            Reach().monitorReachabilityChanges()
    
    
            let status = Reach().connectionStatus()
            switch status {
            case .unknown, .offline:
                print("Not connected")
                MyCustomAlert .sharedInstance.ShowAlert(vc: vc, myTitle: "No Internet Connection", myMessage: "Make sure your device is connected to the internet.")
                isNetworkon = false;
            case .online(.wwan):
                print("Connected via WWAN")
                isNetworkon = true;
            case .online(.wiFi):
                print("Connected via WiFi")
                isNetworkon = true;
            }
            return isNetworkon!;
        }
    
        @objc func networkStatusChanged(_ notification: Notification) {
            let userInfo = (notification as NSNotification).userInfo
            print(userInfo?.capacity)
        }
    
    
    }
    

    达到等级

        import Foundation
    import SystemConfiguration
    
    
    let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"
    
    enum ReachabilityType: CustomStringConvertible {
        case wwan
        case wiFi
    
        var description: String {
            switch self {
            case .wwan: return "WWAN"
            case .wiFi: return "WiFi"
            }
        }
    }
    
    enum ReachabilityStatus: CustomStringConvertible  {
        case offline
        case online(ReachabilityType)
        case unknown
    
        var description: String {
            switch self {
            case .offline: return "Offline"
            case .online(let type): return "Online (\(type))"
            case .unknown: return "Unknown"
            }
        }
    }
    
    public class Reach {
    
        func connectionStatus() -> 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 .unknown
            }
    
            var flags : SCNetworkReachabilityFlags = []
            if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
                return .unknown
            }
    
            return ReachabilityStatus(reachabilityFlags: flags)
        }
    
    
        func monitorReachabilityChanges() {
            let host = "holidaycenterglobal.com"
            var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
            let reachability = SCNetworkReachabilityCreateWithName(nil, host)!
    
            SCNetworkReachabilitySetCallback(reachability, { (_, flags, _) in
                let status = ReachabilityStatus(reachabilityFlags: flags)
    
                NotificationCenter.default.post(name: Notification.Name(rawValue: ReachabilityStatusChangedNotification),
                                                object: nil,
                                                userInfo: ["Status": status.description])
    
                }, &context)
    
            SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), RunLoopMode.commonModes as CFString)
        }
    
    }
    
    extension ReachabilityStatus {
        init(reachabilityFlags flags: SCNetworkReachabilityFlags) {
            let connectionRequired = flags.contains(.connectionRequired)
            let isReachable = flags.contains(.reachable)
            let isWWAN = flags.contains(.isWWAN)
    
            if !connectionRequired && isReachable {
                if isWWAN {
                    self = .online(.wwan)
                } else {
                    self = .online(.wiFi)
                }
            } else {
                self =  .offline
            }
        }
    }
    

    使用访问它

    if(Constants.sharedInstance.checkNetwork(vc: self)){
     // Call api here
    }
    

    【讨论】:

      【解决方案3】:

      对于 Swift 3

      import SystemConfiguration
      
      
      public func isConnectedToNetwork() -> 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)
      }
      

      然后检查:

      if isConnectedToNetwork() 
      {
      // connected 
      
      }else 
      {
      // not  connected 
      }
      

      【讨论】:

        【解决方案4】:
        - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
        {
         ........
        
         internetReachable = [Reachability reachabilityForInternetConnection];
            [internetReachable startNotifier];
         [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(checkInternetConnectionStatus:)
                                                         name:kReachabilityChangedNotification object:nil];
        ............
        
        }
        
        - (void)checkInternetConnectionStatus:(NSNotification *)notice {
            // called after network status changes
        
            NetworkStatus internetStatus = [internetReachable currentReachabilityStatus];
            switch (internetStatus)
            {
                case NotReachable:
                {
                    NSLog(@"No active internet connection");
                    break;
                }
                case ReachableViaWiFi:
                {
                     NSLog(@"The internet is Connected.");
                    break;
                }
                case ReachableViaWWAN:
                {
                    NSLog(@"The internet is working via WWAN!");
                    break;
                }
            }
        }
        

        使用苹果的可达性类

        如果你想手动检查,那么

         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
                }
        
                let isReachable = flags == .reachable
                let needsConnection = flags == .connectionRequired
        
                return isReachable && !needsConnection
        
            }
        
        
        
            if self.isConnectedToNetwork() == true
        {
        //make API call
        }
        else
        {
        //Display alert(No internet connection)
        }
        

        【讨论】:

        • 是的,我打算使用上面解释的可达性。最后请阅读我的问题。
        • NSNotificationCenter 会在每次连接状态改变时触发通知。
        【解决方案5】:

        斯威夫特 3: 您可以使用以下类来检查网络可达性:

        import Foundation
        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)
            }
        }
        

        用法:

        guard Reachability.isConnectedToNetwork() else {
                    completion({ throw Errors.Network.noInternet(message: "No internet connection")  })
                    return
        }
        

        【讨论】:

          猜你喜欢
          • 2013-08-08
          • 1970-01-01
          • 1970-01-01
          • 2015-08-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-14
          • 1970-01-01
          相关资源
          最近更新 更多