reachabilityWithHostname return YES only once
It is a well known bug of simulators in xCode 6.
Try the same on your device in debug mode. It should work correctly as in case of mine.
Also I recommend to use the original version of Reachability from Apple.
Reachability reachable and unreachableBlock are called multiple times?
This is just what i have in mind, this should be a comment but it's too long.
Please let me explain what is happening in your code...
I'm not really sure about this one but i think iOS 9.0.1 and iOS 9.1 is keeping the variable because of this [reach startNotifier];
..
When you call the method -(void)checkServerConnection
you are creating a new Reachability* reach
and so on..
IF you will call the method again, it will create a new
Reachability* reach
and there is an existing one..
Possible solution is to create a global variable (Reachability* reach) that will be reused everytime the method is called.
Probably something like this:
Reachability* reachVar;
// i've changed your variable name hope that's okay, just for example.
-(void)checkServerConnection{
NSLog(@"Check Server Connection");
if (reachVar == nil)
{
reachVar = [Reachability reachabilityWithHostname:@"www.google.com"];
[reachVar startNotifier];
}
reachVar.reachableBlock = ^(Reachability*reach)
{
NSLog(@"Reachability reachable block");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"REACHABLE!");
});
};
reachVar.unreachableBlock = ^(Reachability*reach)
{
NSLog(@"UNREACHABLE!");
}
}
reachability bug in Xcode 8 e Swift 3
You need to fix your method selector. Try like this.
AppDelegate
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
reachability = Reachability.forInternetConnection()
reachability.startNotifier()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
}
}
View Controller
import UIKit
import SystemConfiguration
var reachability = Reachability()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityStatusChanged(_:)), name: .reachabilityChanged, object: nil)
}
func updateInterfaceWithCurrent(networkStatus: NetworkStatus) {
switch networkStatus {
case NotReachable:
view.backgroundColor = .red
print("No Internet")
case ReachableViaWiFi:
view.backgroundColor = .green
print("Reachable Internet")
case ReachableViaWWAN:
view.backgroundColor = .yellow
print("Reachable Cellular")
default:
return
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//
updateInterfaceWithCurrent(networkStatus: reachability.currentReachabilityStatus())
}
func reachabilityStatusChanged(_ sender: NSNotification) {
guard let networkStatus = (sender.object as? Reachability)?.currentReachabilityStatus() else { return }
updateInterfaceWithCurrent(networkStatus: networkStatus)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: .reachabilityChanged, object: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Reachability change notification should be called only once
You can add a flags to prevent the code from being executed unless the state has changed like this:
var connectionState = "Connected"
let connectedState = "Connected"
let notConnectedState = "notConnected"
func checkForReachability(notification:NSNotification)
{
let networkReachability = notification.object as! Reachability;
var remoteHostStatus = networkReachability.currentReachabilityStatus()
if remoteHostStatus.value == NotReachable.value && connectedState == connectedState {
connectionState = notConnectedState
println("State Changed Not Connected")
} else if remoteHostStatus.value == ReachableViaWiFi.value && connectedState == notConnectedState {
connectionState = connectedState
println("State Changed Connected")
}
}
What is the issue with ReachabilitySwift?
I needed a strong reference to Reachability instance! So I should have declared it at a class level.
Check internet connection in iOS app only once
I solved this issue by creating an own HomeViewController.h/HomeViewController.m file for the ViewController where my homepage is integrated. There I added the alert-if-no-internet-connection code.
Checking network status in Swift, observer does not get called
The Reachability
object returned is an autoreleased object , so it has deallocated hence notification is not triggering . You can fix by keeping a strong reference to it.
create a property to hold Reachability
object
var reachability:Reachability?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
// Override point for customization after application launch.
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged:", name:kReachabilityChangedNotification, object: nil)
reachability = Reachability(hostName: "www.apple.com");
reachability?.startNotifier();
return true
}
This will fix your problem.
The observer's name is changed from ReachabilityChangedNotification to kReachabilityChangedNotification. Notice the "k"
How to check network connectivity changes for internet connection at run time with Reachability?
Faced the same issue before, to resolve it you need to declare
let reachability = Reachability()!
outside viewWillAppear
function and your code will look like:
let reachability = Reachability()!
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(reachabilityChanged(note:)), name: .reachabilityChanged, object: reachability)
do{
try reachability.startNotifier()
}catch{
print("could not start reachability notifier")
}
getUserDetail()
}
Related Topics
Swift iOS Record Video and Audio with Avfoundation
Admob Interstitial Alway Returns False
Swiftui Present View Modally via Tabview
How to Access Property or Method from a Variable
How to Reuse Struct on Swift? or Is There Any Other Way
How to Set Response Data into Todayextenstion Widget
How to Download and View Images from the New Firebase Storage
iOS - Setobject VS. Synchronize
Extending a Delegate from a Base Class
Error "Call Can Throw, But Is Not Marked with 'Try' and the Error Is Not Handled"
Modifing One Variable from Another View Controller Swift
Swift3 - How to Protect Secret Key
Displaying Strings in iOS Randomly Without Repeating Them
Swift Custom Uitableviewcell Not Displaying Data
Passing Data Between Interface Controllers in Watchkit
Passing Data Between View Controllers in Swift (From Tableview to Detailviewcontroller)