Reputation: 311
I am making an app which requires API requests. If there's no internet connection in any way (mobile connection, wifi, etc), there's no usage in my app. So I'm trying to populate activity indicator view whenever there's no internet connection in my app.
I found really good Stack Overflow post which let me check the connection status of my device (Check for internet connection with Swift).
However, here is one thing I'm not sure. If I put a method to check iOS device's network connectivity in AppDelegate didFinishLaunchingWithOptions method, then it will be only checked when the app is launched, right? I want to show the activity indicator view whenever there is no connection. In order to facilitate this feature, I would like to know which place makes the most sense to put the method in the app.
Upvotes: 0
Views: 1764
Reputation: 1754
Create below 2 class files Singleton Class
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)
}
}
Reach Class
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
}
}
}
Access it using
if(Constants.sharedInstance.checkNetwork(vc: self)){
// Call api here
}
Upvotes: 1
Reputation: 2212
Swift 3: You can use the following class to check network reachability:
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)
}
}
Usage:
guard Reachability.isConnectedToNetwork() else {
completion({ throw Errors.Network.noInternet(message: "No internet connection") })
return
}
Upvotes: 0
Reputation: 832
- (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;
}
}
}
Use apple's Reachability class
if you want to check manually then
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)
}
Upvotes: 0
Reputation: 2149
There is a great library not for using this.It's only tiny part of this library. use alamofire
How?
you can check reachibility by using this code only.
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()
}
You may using this code as a singleton. Remember to hold on to the reachability manager reference.
Upvotes: 3
Reputation: 586
For 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)
}
then check :
if isConnectedToNetwork()
{
// connected
}else
{
// not connected
}
Upvotes: 1