2016-09-18 182 views
40

对于iOS 9,我使用Reachability public class检查设备是否连接到互联网。我将我的Swift 2代码转换为Swift 3,并且Reachability不再适用。有人能告诉我如何检查iOS 10上的互联网连接吗?谢谢! 下面的代码片段:检查互联网连接(iOS 10)

open 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) { 
      SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0)) 
     } 
     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) 
    } 
} 
+1

请参阅http:// stackoverflow.com/questions/39046377/swift-3-unsafepointer0-no-longer-compile-in-xcode-8-beta-6 – MartinMcB

+2

请注意,http://stackoverflow.com/questions/25623272/how-to-use -s-scnetworkreachability-in-swift/25623647#25623647已更新为Swift 3. –

+0

我认为这将帮助您与您的问: http:// stackoverflow。com/a/39783037/4301118 – sharon

回答

92
import Foundation 
import SystemConfiguration 

func isInternetAvailable() -> 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.contains(.reachable) 
     let needsConnection = flags.contains(.connectionRequired) 
     return (isReachable && !needsConnection) 
    } 

这个工作在iOS的10

+0

如何检测swift中的网络变化3 –

+2

这个答案很好,但还不够。如果您要使用此功能,则必须导入SystemConfiguration –

+4

如果您连接到Wi-Fi但无法连接到互联网(打开谷歌页面),它仍会返回true以便可达。这是不对的。 –

11

试试这个,它为我工作 第一进口SystemConfiguration上您的课。

import SystemConfiguration 

现在执行波纹管功能。

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

    return (isReachable && !needsConnection) 

} 
+1

iOS 10 Swift 3.0 - 效果很好! –

+0

这段代码看起来有缺陷。使用==检查标志无法正常工作。 – ryantxr

+0

亲爱的@ryantxr这段代码对我来说工作正常,我希望你使用的是swift 3.0,如果你找到了更好的解决方案,那么你可以把它放在这里,请不要将问题标记为 –

59

SWIFT 3.0: 这里是很简单的方法来做到这一点:

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

} 

,然后简单,你可以在项目的任何地方使用它,例如:

func viewDidLoad(){ 
     print(currentReachabilityStatus != .notReachable) //true connected 
    } 
+0

谢谢,但我已经有了一个解决方案(你可以阅读以上) – LOLXDXPLOL

+0

谢谢你在swift3帮助我。 –

+3

这是最好的解决方案。非常Swifty。 –

0

你可以在swift中使用3

import SystemConfiguration 

class Connection { 

    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.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0 
     let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0 

     return isReachable && !needsConnection 

    } 
} 
5

第1步:在您的项目中创建一个swift文件。我创建 “ConnectionCheck.swift”

第2步:在您的 “ConnectionCheck.swift” 文件和 “进口SystemConfiguration” 文件到您的 “ConnectionCheck.swift” 和 “ViewController.swift”

import Foundation 
import SystemConfiguration 
public class ConnectionCheck { 

class 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) 
} 
添加以下代码

}

步骤3:现在,在 “ViewController.swift” 使用该代码来检查网络可达性

if ConnectionCheck.isConnectedToNetwork() { 
     print("Connected") 
    } 
    else{ 
     print("disConnected") 
    } 
+0

谢谢,但我已经标记为工作 – LOLXDXPLOL

+0

答案如果我提交我的应用程序到苹果,我需要更改任何代码,以通过苹果验证? –

+0

@LOLXDXPLOL是的,我们可以看到...但是SO工作多个答案,以便其他人可以看到不同的版本,也许,也许,更好的解决方案显示出来......我试图保持礼貌。 –

3

这里是夫特通过回调函数,溶液是由Yasin Ugurlu从上面的解决方案中提取的。

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() 
    } 
+0

你的答案看起来不错,你的评论以上有关接受的答案连接到WiFi,但没有互联网是正确的。你如何调用你的函数并在视图控制器中使用它?请举例 –

2

此代码对您有所帮助。它为我工作在斯威夫特4和Xcode的9

转到https://github.com/ashleymills/Reachability.swift/tree/master/Reachability 和Reachability.swift文件复制到你的项目

瓦西Nunev解释清楚可达 https://www.youtube.com/watch?v=wDZmz9IsB-8

class ViewController: UIViewController { 

    let reachability = Reachability(); 
    override func viewDidLoad() { 
     super.viewDidLoad() 

     reachability?.whenReachable = { _ in 

      DispatchQueue.main.async { 
       self.view.backgroundColor = UIColor.green 
      } 
     } 

     reachability?.whenUnreachable = { _ in 
      DispatchQueue.main.async { 
       self.view.backgroundColor = UIColor.red 
      } 
     } 
     NotificationCenter.default.addObserver(self, selector: #selector(internetChanged), name: Notification.Name.reachabilityChanged , object: reachability) 
     do{ 

      try reachability?.startNotifier() 
     }catch{ 
      print("Could not start notifier:\(error)") 
     } 

    } 

    @objc func internetChanged(note:Notification) { 
     let reachability = note.object as! Reachability 

     if reachability.connection != .none { 

      if reachability.connection == .wifi{ 
       DispatchQueue.main.async { 
        self.view.backgroundColor = #colorLiteral(red: 0.3411764801, green: 0.6235294342, blue: 0.1686274558, alpha: 1) 
       } 
      }else if reachability.connection == .cellular{ 
       DispatchQueue.main.async { 
        self.view.backgroundColor = #colorLiteral(red: 0.3647058904, green: 0.06666667014, blue: 0.9686274529, alpha: 1) 
       } 
      } 
     }else{ 
      DispatchQueue.main.async { 
       self.view.backgroundColor = #colorLiteral(red: 0.7450980544, green: 0.1568627506, blue: 0.07450980693, alpha: 1) 
      } 
     } 
    } 
} 
+0

谢谢,但很久以前我已经有了一个可行的答案 – LOLXDXPLOL

+0

此方法适用于蜂窝数据以及wifi吗?它是否区分简单地连接到无线网络和连接到互联网连接的WiFi *? –

+0

此代码不适用于我。我不知道我做错了什么。当你进入网络时,它返回true,然后返回false。 –