Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isReachable returning NO on second call despite connection #146

Open
robertturrall opened this issue Oct 27, 2016 · 3 comments
Open

isReachable returning NO on second call despite connection #146

robertturrall opened this issue Oct 27, 2016 · 3 comments

Comments

@robertturrall
Copy link

robertturrall commented Oct 27, 2016

I've just starting using this class and like the blocks approach so I added the following to the init() method of my APIManager singleton class:

__weak typeof(self) weakSelf = self;

            self.reach = [Reachability reachabilityWithHostname:LTAPIHost];
            self.reach.unreachableBlock = ^(Reachability *reach) {
                [weakSelf showReachability:NO];
            };
            self.reach.reachableBlock = ^(Reachability*reach) {
                [weakSelf showReachability:YES];
            };
[self.reach startNotifier];

Running in the simulator, all seems to work fine - although I do get the issue that it sometimes fires the unreachableblock even though the network is reachable after reconnecting to wifi.

The bigger problem, however, is this:

I check reachability at certain points on the class, before sending requests:

if (!self.reach.isReachable) {.......}

Running the app in the simulator this runs through fine on a first check (returns YES). On the second time I call if (!self.reach.isReachable) {.......} it returns NO, although there is still a connection.

If I comment out the [self.reach startNotifier]; in the init() method all calls to check self.reach. isReachable return YES but I lose the benefit of the reachability blocks.

How can I use the notifier to be able to use the blocks AND check for reachability whenever needed?

I had thought of simply maintaining a local BOOL that's set on/off by the reachability blocks but given the fact that they reachableblock seems to not always be correctly fired when a connection is reestablished, I'd rather be able to check directly.

Thanks in advance!

@daemedeor
Copy link

@robertturrall From what I recall of Apple's docs and presentation on network connection view here, they said to not rely on reachability to determine whether or not the connection is available and only use it to present a good interface to the user (like in facebook when it says "internet is not available" on the top). In good practice, you should use it to not stop a request and just fire a user request anyway. If it fails, you can either use reachability to tell the user exactly what happend (this is less of a good practice) or use it to refire another request when reachability does report "connection good"

@robertturrall
Copy link
Author

@daemedeor I agree with the guidelines but find it wasteful to even send a network request if the server is not reachable. I am testing for reachability prior to sending to simply return and skip trying in this case. Then when the server is reachable I can send any "missed" transactions, as you suggest. What concerns me is that using the reachability blocks and reach.isReachable seem to be mutually exclusive - meaning I should only really use the blocks and set a local reachable BOOL instead - AND that the firing of the blocks is unreliable - meaning that the local BOOL may be set wrong. That was the point of my question, to understand if this is an issue or if I should be using the class differently.

In the meantime, I've built a solution around this and am deciding whether it's acceptable or if I should return to using Apple's solution instead. Thanks for your comment however!

@daemedeor
Copy link

@robertturrall the reachability blocks is basically to restart the NSOperations that you've hung up, while the connection has been suspended... Probably what you can do, is have a NSOperations that is "paused" when you are in a go state/never added to. Then when the connection is reported bad, then you pause it from running, then add NSOperations to it. Then when the connection changes to good, set it to run in order. This would allow you to use the blocks to the fullest but allow for any other network requests to at least attempt once... unless you need specific order in which case just keep adding to that NSOperation block. reach.isReachable in this case, would best be used if you were to show the icon. Flip it from green and red between good and bad states based on that bool. You can also refresh the place where the icon is shown (or pop a message up) on the main thread once you get the new status as well. The firing of the blocks is "relatively" unreliable. it's only as reliable as the library allows. But if you use reach.isReachable and stop your UI from responding at all (say stop an attempt to go to the server) then you risk your Users being frustrated in the edge cases that the library doesn't work...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants