I'm new to developing on iOS and in Objective-C.
According to this technical note (https://developer.apple.com/library/ios/qa/qa1693/_index.html),
It is recommended to check for Reachability using async APIs on app startup, in order to prevent the app from being killed by the Watchdog.
I have looked at the samples + documentation here: SCNetworkReachabilitySetCallback
This allows registering a callback that is asynchronously invoked when reachability state changes.
However, this does not solve the issue of detecting what the state is RIGHT NOW (the callback is only raised on changes to reachability state).
What is the preferred way of getting the reachability state flags ? is there an Async API for that ?
I would look at this tutorial which uses the Tony Million Reachability class.
Related
Is it safe to use 'com.apple.system.config.network_change' notification to detect network reachability changes? Or is it considered to be a private API? For now my code looks like this:
CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(),
nil,
callback,
"com.apple.system.config.network_change" as CFString,
nil,
.deliverImmediately);
And then in callback I respond to the notification.
The problem is Reachability in iOS not always detects Wi-Fi switching. For instance, if we are switching from one Wi-Fi AP to the other that system already knows (because we have used it in the past) then it happens so fast that there's no 'Disconnected' event and I cannot track the actual switching moment. Solution above works but I am sure whether my app won't be rejected for publishing in the App Store.
Thanks!
I can't exactly answer your question, but the way I handle Reachability changes is using this "lib", which is pretty accurate when listening to every single change. I think you could give it a try if it fits your needs of detecting this specific moment of switching between two Wi-Fis.
If you don't want to import it - it's a really small file -, you can just see how it works - basically using SCNetworkReachability.
That is considered to be a public API for now. For more details please see this thread:
https://forums.developer.apple.com/message/334035#334035
I've been reading through the documentation on the WatchKit connectivity framework to try and figure out if I can delegate all of the intensive processing needs over to my parent iOS app. All of the code already exists in the parent app for doing the required processing and it seems significantly more efficient for it to do so, rather than the Apple Watch app duplicating the code and attempting it itself.
My question is whether this is possible if the app on the iOS device isn't active at the time the watch kit app makes the request? Will it just queue up the request until it's next opened or can it be configured to process it immediately? I would want the watch to always get some form of response or have a timeout on the request.
UPDATE:
I found that my particular issue was related to calling the reply handler from a background thread after executing a separate request. When I was doing this I didn't get a response back from the iOS device to the apple watch. This initially made me think the iOS device was ignoring the requests until it was active.
The solution for me was to do the following so that the reply handler is always called from the main thread. This seems to be a critical piece of the communication that I must have missed out in the documentation (or maybe it was missing :o). Long story, short, after making the update shown below I successfully got responses back every time.
dispatch_async(dispatch_get_main_queue(), { () -> Void in
replyHandler(myResponse) // Always call from main thread!
})
WCSession's sendMessage APIs enable the WatchKit extension to wake the iOS app up in the background as long as reachable is true. Here is a nice step-by-step tutorial on using sendMessage.
I am having consistent issues with the Reachability class reporting incorrect state and losing notifications from Tony Millions reachability class. Although something similar has been reported here I would like to add more information that may or may not be useful in resolving my variation of the problem.
Firstly, I'm using the latest Xcode Version 6.3.2 (6D2105) and am working on a Macbook Pro connected via Wifi and have downloaded the latest Reachability class (as of today by post date 5 Aug 2015) which I have set up as an instance that I pass around my iPhone application (not a singleton pattern).
Secondly, and probably quite importantly I'm using the iOS simulator in order to get the application behaviour correct before deploying it to an iPhone.
I'm taking advantage of both the notification mechanism, and also the direct 'isReachable' method depending on my usage about the code - notifications for triggering sync'ing and status bar updates and the 'isReachable' for conditional method calls. The reachability class is instantiated in the app delegate using this style:
[Reachability reachabilityWithHostname:hostAddress]
And the reachability notification service is started using the
[reachability startNotifier]
method. Now, when the application starts, the reachability correctly indicates network access (be that up or down) and I also receive notifications as expected.
If I simulate the network failing by turning of Wifi (Turn off wifi from the computers perspective) I correctly receive the notification that the network is no longer reachable. But when I turn Wifi back on again I receive another notification which also tells me that the network is no longer reachable - even though it is. In addition, the 'isReachable' method also reports incorrectly.
Note that I call isReachable immediately after the result of a notification from NSNotificationCentre. I also ask for isReachable calls on different threads (does this matter)? Occasionally I simply don't get reachability updates at all, and eventually the notifier just seems to stop working.
Any one have any thoughts on what I'm doing wrong here? Thanks!
With iOS7, it is possible to have completionHandler for Remote Notifications. Is it possible to do the same for UILocalNotifications?
Basically, I want a webservice to post my some data at regular time intervals of 30 seconds, even if the app is in background. For this I considered 3 options but didn't get help from any :
Background Fetch : This will work in background, but I can't use it as it is not mandatory that iOS will always invoke this background fetch at my desired time intervals.
Remote Notifications : This works perfectly. But every 30 seconds I have to post a Remote PUSH Notification, which is not at all practical. Also it'll be great if I could handle it locally.
UILocalNotifications : There's no completion handler for this. User WILL HAVE TO open the app. So this ain't working as well!
Are there any other options? Or even with iOS7, it's still not possible to do something locally in background?
Please help. Thanks!
You covered all the options, and as you see, this isn't supported. For good reasons, mostly, as waking up the application in the background is a costly operation (in iOS7, a snapshot is taken after apps finish their background work), doing it every 30 seconds would be devastating to the battery life.
Seeing as you haven't mentioned what data you need to post, in most cases I would suggest you redesign your app to be friendly to your users' batteries. If you need location reporting, consider listening to significant location changes instead of recording every 30 seconds.
Abusing push notifications is possible (note, that silent remote notifications are rate-limited by Apple), but consider the experience your users will have.
If you feel that this feature should be there and is missing, you should open an enhancement request with Apple and post the radar number here so people can duplicate it.
Background fetch is a direct answer for your problem. Background fetch initiates your fetch handler whenever the iOS is free to execute a task periodically. All you need to do is initiate you NSURLSession request in
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
NSURLConnection is no longer a valid API for service calls or nor it supports background tasking. NSURLSession is clearly a replacement API for NSURLConnection with its advanced iOS 7 benefits. Adding below, documentation from Apple's iOS documentation
NSURLSession is a replacement API for NSURLConnection. It provides
options that affect the policy of, and various aspects of the
mechanism by which NSURLRequest objects are retrieved from the
network.
Background fetch interval can be set to define the repetition frequency for background fetch, but it also considers factors of the OS resources and pending operations
- (void)setMinimumBackgroundFetchInterval:(NSTimeInterval)minimumBackgroundFetchInterval;
iOS 7 clearly gives a better way to update content of the application, but it respects device resources & user priority as iOS generally does. Hope this answers your question.
Actually, all looks like you can't communicate with webservice at regular time intervals from background.
UILocalNotifications or Remote Notifications need user's action to wake up the app if it's backgrounded. EDITED: Starting from iOS 7.0 remote notification can wake up the app but it's not a flexible solution
iOS allows more activities in background for applications that use one of specified UIBackgroundModes, see please "Table 3-4 Background modes for apps":
Here is a link to related Apple docs
If your application isn't positioned for one of bg modes directly, I agree with Anil Kumar (post above) that background fetch is the most useful thing here. However it doesn't do completely what you need. [UIApplication setMinimumBackgroundFetchInterval:] it doesn't mean any strict time. It means minimum interval only (or desired time). Here is more info:
performFetchWithCompletionHandler never gets fired
Thanks
in my IOS application I have an in-app purchase in my app and I need to send receipt to my web service to assign premium content to a user account. I need this to be reliable even when the connection is lost right after the in-app purchase completes.
Are there any solid libraries out there that can take a request and execute it when connection is reestablished?
I would definitely recommend AFNetworking, a very well-made networking library which wraps NSURLConnection.
In order to use it for your purpose you need to take advantage of the reachability build-in features of AFHTTPClient as suggested in this other answer.
Basically you can execute and arbitrary block whenever the reachability status of the network changes using the setReachabilityStatusChangeBlock: method of AFHTTPClient.
Just remember to link and import the SystemConfiguration framework, otherwise it won't work.