Swift'de internet bağlantısı olup olmadığını kontrol edin


107

Swift ile internet bağlantısının olup olmadığını kontrol etmenin bir yolu var mı?

Bunu yapacak birçok üçüncü taraf kitaplığı olduğunu biliyorum ama hepsi Objective-C'de yazılmıştır. Swift alternatifi arıyorum.


5
Swift'in en büyük avantajlarından biri, Objective-C (ve bunun gibi kütüphaneler) ile iyi entegre olması.
user2864740

Aslında. Mevcut kütüphanelerden birini kullanırken ne gibi sorunlar yaşıyorsunuz? Swift'in bir Objective C kütüphanesini kullanmak oldukça basit ve eğer yapamazsanız, Swift'de herhangi bir tür uygulamayı yazmanız son derece zor olacak.
Matt Gibson

1
@MattGibson, ObjC'de yapabileceğiniz hemen hemen her şey, göreceli kolaylıkla Swift ile yapılabilir. Kabul edelim ki, bu durumda fazladan birkaç satır olacak ama yine de "aşırı zor" olmaktan çok uzak
Byron Coetsee

@ByronCoetsee AppKit, vb. Gibi kitaplıkları dahil ettim — benim açımdan, Swift'de yararlı bir şey yazmak için Objective C kitaplıkları ile nasıl etkileşim kuracağınızı bilmeniz gerekecek.
Matt Gibson

Alamofire cevabını görün - stackoverflow.com/a/46562290/7576100
Jack

Yanıtlar:


228

Yorumlarda belirtildiği gibi, Swift'de Objective-C kitaplıklarını kullanmak mümkün olsa da, daha saf bir Swift çözümü istedim. Mevcut Apple Reachability sınıfı ve diğer üçüncü taraf kitaplıkları Swift'e tercüme edemeyeceğim kadar karmaşık görünüyordu. Google'da biraz daha araştırdım ve ağ kullanılabilirliğini kontrol etmek için basit bir yöntem gösteren bu makaleye rastladım . Bunu Swift'e çevirmek için yola çıktım. Pek çok engelle karşılaştım ancak StackOverflow'dan Martin R sayesinde bunları çözmeyi ve sonunda Swift'de uygulanabilir bir çözüm bulmayı başardım. İşte kod.

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(nil, UnsafePointer($0)).takeRetainedValue()
        }

        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
    }

}

Swift> 3.0 için

public class Reachability {
    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
        }
        if flags.isEmpty {
            return false
        }

        let isReachable = flags.contains(.reachable)
        let needsConnection = flags.contains(.connectionRequired)

        return (isReachable && !needsConnection)
    }
}

Bu hem 3G hem de WiFi bağlantıları için çalışır. Ayrıca bunu çalışan bir örnekle GitHub'ıma yükledim .


7
Hızlı yanıt için teşekkürler (kelime oyunu değil). MIT veya Apache ideal olacaktır - teşekkürler!
Andrew Ebling

4
Bitti. MIT olarak değiştirildi.
Isuru

11
Ben eğer bir başka sorun bulduk 3G açıkken ama artık veri kapasitesi daha sonra sahip isConnectedToNetworktrue döndürür, ama benim web hizmetini arayamazsınız
János

11
@Isuru'nun dediği gibi, bu, artık Swift 2 için güncellenen stackoverflow.com/a/25623647/1187415'e dayanıyor .
Martin R

2
@ János: Bir bildirim geri araması ayarlamak artık Swift 2 ile mümkün, bkz. Güncellenmiş yanıt stackoverflow.com/a/27142665/1187415 .
Martin R

16

Sana daha iyi bir yol veriyorum ...

Bu kodla bir sınıf oluşturmalısınız

 import Foundation
 public class Reachability {

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

Ardından, bu kodu kullanarak projenizin herhangi bir yerinde internet bağlantısını kontrol edebilirsiniz:

if Reachability.isConnectedToNetwork() == true {
     println("Internet connection OK")
} else {
     println("Internet connection FAILED")
}

Çok kolay!

* Bu yol Vikram Pote cevabına dayanmaktadır!


15
Lütfen yukarıda kullanılan yöntem yerine bu yöntemi kullanmamanız gerektiğini unutmayın . Sürekli bağlantı gerektiren uygulamalarda, bu yöntem gibi bir yanıt kontrolü, internet bağlantınızın zayıf olduğu durumlarda (yani Edge / GPRS'de) uygulamanın askıda kalmasına neden olacaktır. Lütfen bu çözümü kullanmayın !!
İmran Ahmed

7
Kötü yol 1) Her seferinde sunucuya fazladan isabet gerekiyor 2) google.com da kapalı olabilir
Vijay Singh Rana

2
1. Evet, bu yolun her seferinde sunucuya fazladan vurulması gerekir, ancak İnternetin mevcut olduğuna dair% 100 garanti verir ... Cihazın bir wifi ağına bağlı olduğu ancak internet erişimi sağlamadığı zamanlar olabilir! Bu durumda, bu yol İnternete erişim eksikliğini belirler ... diğer yollar - hayır! 2. google.com yerine kendi sunucunuzu kullanabilirsiniz ... Bu aslında ...
Dmitry

1
kötü çözüm, bağlantı katil.
gokhanakkurt

2
gokhanakkurt, lütfen İnternetin% 100 çalışmasını sağlayan başka bir çözüm önerin
Dmitry

15

Swift 3.1 (iOS 10.1) için

Ağ türü (yani WiFi veya WWAN) arasında bir ayrım yapmak istiyorsanız:

Kullanabilirsiniz:

func checkWiFi() -> Bool {

    let networkStatus = Reachability().connectionStatus()
    switch networkStatus {
    case .Unknown, .Offline:
        return false
    case .Online(.WWAN):
        print("Connected via WWAN")
        return true
    case .Online(.WiFi):
        print("Connected via WiFi")
        return true
    }
}

Ağ türlerini birbirinden ayıran tüm Erişilebilirlik Sınıfı:

import Foundation
import SystemConfiguration

import UIKit
import SystemConfiguration.CaptiveNetwork

public let ReachabilityStatusChangedNotification = "ReachabilityStatusChangedNotification"

public enum ReachabilityType: CustomStringConvertible {
    case WWAN
    case WiFi

    public var description: String {
        switch self {
        case .WWAN: return "WWAN"
        case .WiFi: return "WiFi"
        }
    }
}

public enum ReachabilityStatus: CustomStringConvertible  {
    case Offline
    case Online(ReachabilityType)
    case Unknown

    public var description: String {
        switch self {
        case .Offline: return "Offline"
        case .Online(let type): return "Online (\(type))"
        case .Unknown: return "Unknown"
        }
    }
}

public class Reachability {

    func connectionStatus() -> ReachabilityStatus {
        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) { zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }) else {
           return .Unknown
        }

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

        return ReachabilityStatus(reachabilityFlags: flags)
    }

    func monitorReachabilityChanges() {
        let host = "google.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: NSNotification.Name(rawValue: ReachabilityStatusChangedNotification), object: nil, userInfo: ["Status": status.description])}, &context)

        SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), CFRunLoopMode.commonModes.rawValue)
    }
}

extension ReachabilityStatus {

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

3 Aralık 2016, iOS 10 ve hızlı 3.1 gibi iyi çalışıyor, teşekkürler!
joey

Merhaba, Wifi / 3G / Mobil-Veri / 4G bağlantısını farklılaştırmak istersek bunun için nasıl tanımlayabiliriz.

6

SendSynchronousRequest kullanımdan kaldırıldığından, bunu denedim ancak yanıt tamamlanmadan önce 'dönüş Durumu' çağrıldı.

Bu cevap yine de iyi çalışıyor, Swift ile internet bağlantısını kontrol edin

İşte yine de denediğim şey:

import Foundation

public class Reachability {

    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
        let session = NSURLSession.sharedSession()

        session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
            print("data \(data)")
            print("response \(response)")
            print("error \(error)")

            if let httpResponse = response as? NSHTTPURLResponse {
                print("httpResponse.statusCode \(httpResponse.statusCode)")
                if httpResponse.statusCode == 200 {
                    Status = true
                }
            }

        }).resume()


        return Status
    }
}

Senin çözümünü beğendim ve kullandım. Ama bunu şu cevapla birleştirdim: stackoverflow.com/a/34591379 aka. bir semafor ekledim .. Bu yüzden görevin bitmesini bekliyorum.
Bjqn

6

SWIFT 3: Wifi ve internet bağlantısını kontrol eder :

import Foundation
import SystemConfiguration

public class Reachability {
    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)
    }
}

KULLANIM:

if Reachability.isConnectedToNetwork() == true {
    print("Connected to the internet")
    //  Do something
} else {
    print("No internet connection")
    //  Do something
}

2
public func isConnectedToNetwork() {...}class func isConnectedToNetwork{...}kullanım durumunuz için değiştirilmelidir .
keverly

4

Aşağıdaki cevabı da kullanabilirsiniz.

    func checkInternet(flag:Bool, completionHandler:(internet:Bool) -> Void)
    {
      UIApplication.sharedApplication().networkActivityIndicatorVisible = true

      let url = NSURL(string: "http://www.google.com/")
      let request = NSMutableURLRequest(URL: url!)

      request.HTTPMethod = "HEAD"
      request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
      request.timeoutInterval = 10.0

      NSURLConnection.sendAsynchronousRequest(request, queue:NSOperationQueue.mainQueue(), completionHandler:
      {(response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in

        UIApplication.sharedApplication().networkActivityIndicatorVisible = false

        let rsp = response as NSHTTPURLResponse?

        completionHandler(internet:rsp?.statusCode == 200)
    })
    }

     func yourMethod()
    {
    self.checkInternet(false, completionHandler:
    {(internet:Bool) -> Void in

        if (internet)
        {
            // "Internet" mean Google
        }
        else
        {
            // No "Internet" no Google
        }
    })
   }

Teşekkürler! Yanıttan NSHTTPURLResponse olarak otomatik düzeltme aldım? olarak yanıt vermek için! NSHTTPURLResponse? Swift 1.2'de.
Francis Jervis

1

SWIFT 3: 3G ve Wi-Fi bağlantısını kontrol edin

DispatchQueue.main.async {
        let url = URL(string: "https://www.google.com")!
        let request = URLRequest(url: url)

        let task = URLSession.shared.dataTask(with: request) {data, response, error in

            if error != nil {
                // do something here...
                print("Internet Connection not Available!")
            }
            else if let httpResponse = response as? HTTPURLResponse {
                if httpResponse.statusCode == 200 {
                    // do something here...
                    print("Internet Connection OK")
                }
                print("statusCode: \(httpResponse.statusCode)")
            }

        }
        task.resume()
}

Bu tercih edilen bir yol değil. Ya ileride bir noktada sağlanan web bağlantısı yanıt vermeyi keserse veya devre dışı kalırsa. Bunun için Apple SystemConfiguration çerçevesini kullanmanızı tavsiye ederim. Yukarıdaki cevaba bakın.
Abdul Yasin

1

Swift 5 için:

import Network
let monitor = NWPathMonitor()

func checkInterwebs() -> Bool {
    var status = false
    monitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            status = true  // online
        }
    }
    return status
}

1

Swift 4

if isInternetAvailable() {
    print("if called Internet Connectivity success \(isInternetAvailable())");
} else {
    print("else called Internet Connectivity success \(isInternetAvailable())");
}

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)
   //   print(isReachable && !needsConnection)
   return (isReachable && !needsConnection)
}

0

Tüm yanıtların en iyisini buldum ve bu her seferinde İnternet bağlantı durumunu kontrol etmeye devam ediyor.

Başlamak için önce Ağ çerçevesi için bir içe aktarma ekleyin:

import Network

Ardından, NWPathMonitor örneğini oluşturun

let monitor = NWPathMonitor()

Bunu denemek için

 monitor.pathUpdateHandler = { path in
    if path.status == .satisfied {
      print("We're connected!")
    } else {
      print("No connection.")
    }
    print(path.isExpensive)
 }

Unutmayın, bağlantı durumu her değiştiğinde kapanış çağrılır.

 let queue = DispatchQueue(label: "Monitor")
 monitor.start(queue: queue)

Bunu View denetleyicimde nasıl kullandım,

class testViewController: UIViewController {

@IBOutlet weak var status: UILabel!
let monitor = NWPathMonitor()

override func viewDidLoad() {
    super.viewDidLoad()
    
    let queue = DispatchQueue(label: "Monitor")
    monitor.start(queue: queue)
    _ = NWPathMonitor(requiredInterfaceType: .cellular)
    
    monitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            print("We're connected!")
            DispatchQueue.main.async {
                self.status.text = "We're connected!"
            }
            
        } else {
            print("No connection.")
            DispatchQueue.main.async {
                self.status.text = "No connection."
            }  
        }
    }
 }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.