Integrating Reachability with ReactiveCocoa? - ios

I'm working on the development of an app using ReactiveCocoa and the time has came to integrate Reachability to handle Network Events.
I'm not sure about the work I've done as some of RAC design guidelines advice against it. But from what I've been researching I couldn't find a proper way to manage this (or more likely, I dind't understand how).
Our idea is to have a unique signal that sends events upon Reachability's notifications. Each of our viewcontrollers would subscribe to that signal and react each one in its specific way (ie alertview, do nothing, etc).
The thing is that we only need our visible viewcontroller to react, so we are using RACDisposable. This way, when a viewcontroller appears it subscribes to the signal, and when it dissapears we dispose it.
From the Design Guidelines of RAC the use of RACDisposable should be avoided, but I can't manage to handle this subscribe/unsubscribe cycle in any other way.
Is this approach correct for this kind of "infinite" signals?
An alternative we though of is using a signal that removes its previous subscribers when a new one joins. Does such a thing exist?
Thanks in advance for any light you can point in my direction.
From this SO post I got to trying takeUntil:[self rac_willDeallocSignal]which seems useful in theory but doesn't really work for me. As this behaviour is encapsulated within a Manager, and it's not supposed to be deallocated, I don't know how this can work in my favour.
An option that crossed my mind is takeUntila new signal fires whenever a method to stop is called; but it seems pretty much just so we don't use RACDisposable.

From this SO post I got to trying takeUntil:[self rac_willDeallocSignal]which seems useful in theory but doesn't really work for me. As this behaviour is encapsulated within a Manager, and it's not supposed to be deallocated, I don't know how this can work in my favour.
Your view controller can do something like this:
- (void)viewWillAppear
{
RACSignal *disappear = [self rac_signalForSelector:#selector(viewWillDisappear)];
[[self.manager.reachabilitySignal takeUntil:disappear] subscribeNext:^(id status) {
// do whatever needs doing with reachability status here
}];
}
and your Manager's reachabilitySignal can be implemented to register/de-register for reachability status changes as needed depending on whether there are any subscribers.

Related

Notifying ViewController from model(networkClient) in swift

I have some complex networking in my app( I don't use any third party dependencies, because of project requirements). For instance, I send three network requests in parallel after first two requests provide results. All my networking is done in separate models, known as networkClients(following MVC-S pattern) and are called directly from repository, not from ViewControllers. However, I need the last request to notify my viewController after I get response from network. How should I do that? I don't think notification center would be right solution because it can cause memory leaks and I have not found correct approach to complex problem like this. Please provide some prominent solutions. It should conform to good design pattern like MVVM or MVC and should not be some workaround or hack. Maybe delegates would work? I know that rxSwift would solve my issue, because I could start observing for results after initializing viewController and after data would be updated from repository my viewController would also be notified...
The right design doesn't have VCs observing the network clients directly. Those network operations should be assembling parts of a model, which is what the VC really cares about. Have the VC observe that singular model.
It can do this observing using one of the well known patterns for loosely coupled communication between objects. The OP correctly mentions delegates. Notification center and KVO are others. There's plenty of discussion on SO about which to use and how to implement. (I'd go with NSNotificationCenter as an easy and rational start).
So the order of operation is like this:
allocate the model
launch the network requests and setup those request completions (completion blocks, probably) to update that model with their responses. (the model can launch the requests, which is a reasonable practice).
create the view controller(s) that setup model observation when they initialize (probably, in viewWillAppear or later)
What about the fact that >1 requests are in flight simultaneously? A commenter above points out correctly that GCD offers a way to group those async operations into a single one. But you can do this yourself straight-forwardly: the model decides when it's completely built. The completion code for each request will change some condition in the model to the "ready" state. Each request completion can check to see whether all of the ready conditions are met, and only then post a "ready" notification for observers to see.
Another niggling issue: what if those requests all run very, very fast? Maybe there's some cached response that's ready early, making the model "ready" before the VC has had a chance to setup observation? Handle this straight-forwardly in the VC: before observing the model, check to see if it's ready already and run the same update code that runs on the notification.

Apple notifications reliability

Okay so it's pretty obvious that push notifications aren't always reliable, as stated in the docs.
Correct me if I'm wrong, it's simply because someone might not have internet for an extended period of time and the notification could for example, expire, or get replaced, or even get lost for some cosmic reason.
I'm okay with that.
But as a junior programmer I used a lot of local notifications, not for display, but simply to call different methods when some processes where done.
Here is a simple example, when the app starts, I have a data-update process of, say, messages and stuff. When that update is done (about 3 seconds later), I send a notification that all my controllers listen to so they update their UI accordingly. If I'm on the home screen I'll show those little red badges, if I'm in a conversation I'll add the messages in the tableview, and so on.
And, as a junior developer, I had the chance to work with a senior developer who frowned upon this style. He says that it's just not reliable and I should use delegate callbacks and completion handlers. Which I find very hard to do considering the way the app is built. My system is literally a one-liner and never failed, whereas his system requires a lot of implementation of different methods in each separate class. It seems both redundant and messy.
I'm finally getting where I wanted : are notifications reliable locally, I'm talking about this :
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_SOMETHING_SOMETHING object:self];
with its addObserver: counterpart obviously.
Am I really wrong about chosing this work style ? What should I have done? Or is that okay? Or is that even awesome?
Sadly enough this is a quite opinion-based question because it's about standards and good practices, but I feel like it's not broad enough to be against the rules because I really really feel like someone is gonna bring a technical reason why this or that should/shouldn't be done, or clarify what should be used where and when.
Anyway, please ask me to clarify anything if need be, I'm genuinly interested in all the responses to come, and I'm looking forward to it.
There are different kinds of notifications in the iOS world, each really have different purposes and shouldn't be confused with each other.
push notifications:
these are the only ones not being reliable in the sense that they depend on a network connection and apple's push system...
UILocalNotification:
these are ways to notify your users upon certain events (you could compare it to a push notification only that it's not sent from a server but triggered locally by your own app)
NSNotification:
these are purely technical and basically they provide a broadcast mechanism that can be used to enable communication between certain parts of your app. i understand that on first sight it might seem handy to use NSNotification often in your code, because it's a simple and straightforward way to let 2 (or more) classes communicate with each other. however, you senior dev was right in that he advised you not to overuse this mechanism. mainly because it leads to a messy coding structure and doesn't scale well when your project becomes bigger. another huge issue is that it makes debugging very difficult. when using delegates or completion blocks on the other hand, you have a chance to structure your code in a reasonable way that ensures that you encapsulate functionality as you should, makes the code more readable and is way more appropriate to be used at scale.
Don't confuse NSNotificationCenter notifications with local (or remote) push notifications. They are completely different.
Notifications from NSNotificationCenter are reliable. No Internet is used for these. They are simple method calls made within your running app. They are just as safe as using other forms such as delegation.
Using NSNotificationCenter is great when you simply want to broadcast to the app that something has happened and you don't care who knows or how many listeners there are for the event.
The typical delegation pattern generally only works when there is at most one listener for the events.

How to make UIAlertView pause thread and wait user response, iOS dev

Please read through all my question and see if it is duplicate with this question
Sometimes I believe iOS is the best OS and xCode is the most elegant IDE too, but sometimes I think they're both the stupidest thing in the world and maybe the whole universe!
What I need SEEMS easy, code logic like this
//code BEFORE asking user's decision
//with a lot of variables, this is important
//call UIAlertView to ask user Yes/No question, now the thread should be paused and waiting for user's tap on button
//code AFTER get user tap a button, selected YES/NO
//MANY variables before asking should be continuely used here
answerIsYES = //response from UIAlertView
if (answerIsYES)
{
//code response to YES
}else{
//code response to NO
}
If you noticed "MANY variables" before and after UIAlertView show, you will not suggest me to use UIAlertViewDelegate. If that, I have to make all the variables at class-level and what if I have to ask user's decision in FOR loop? That cannot jump to SelectedButtonAtIndex method and come back! Am I right? I want to make my code integrated but the UIAlertView and its delegate seems keeping split them.
Put it simple, what I want is just a MessageBox from .NET, it can wait for user's click. So is there any code that can ahieve this on iOS? Is there a code in iOS can just simple "pause" a thread and then triggerd by some event and "resume" it??
I have searched a lot and cannot find a satisfied answer, the answers involved "NSCondition", "NSThread", "loop", but none really works well. But I did found one in the link at first, respond by #Joseph Gagliardo, I don't know if that's the best solution.
Any suggestion will be greatly appreciated.
UIAlertView, like most other aspects of UIKit, is event driven. You don't want the main thread blocked while an alert is being displayed. Many times other things need to keep going while the alert is in view. But there is a good solution to your issue. Blocks.
UIKit classes that have been added more recently are starting to make use of blocks. This makes writing event driven code easier. It eliminates the need for separate delegate methods just to handle the completion of some event.
Do a Google search on "UIAlertView blocks". You will find several 3rd party versions of UIAlertView that make use of blocks. The use of this type of alert view will allow you to keep all of your code in the one method. These solutions don't pause the main thread or anything. It just makes it much easier for the completion block to access all of the variables you have setup just prior to displaying the alert view.

handleTurnEventForMatch:didBecomeActive: callbacks only arriving some of the time

This is a follow-up to this question. If you are not receiving any callbacks to handleTurnEventForMatch:didBecomeActive:, try the answer there.
In my game, I am only receiving turn event notifications some of the time. But if I go back to the matchMakerViewController and re-load the match, the state is always correct.
My game uploads the turn state multiple times during each turn. Anecdotally, it seems that if the other device receives one notification for an opponent's turn, it is less likely to receive further notifications for that same turn. However, this is not 100%.
In general, my internet connection seems to work pretty well.
Any ideas what might be causing this?
I finally figured out the problem.
Alright, if you use the GKTurnBasedMatchmakerViewController, then it steals the delegation from your current delegate.
It has probably got something like:
[GKTurnBasedEventHandler sharedTurnBasedEventHandler].delegate = self;
This makes perfect sense as the viewcontroller needs to update when changes occur from gamecenter, so it becomes the delegate for the GKTurnBasedEventHandler.
If you want to return the delegation to your own object though you should put this line:
[GKTurnBasedEventHandler sharedTurnBasedEventHandler].delegate = self;
At the very top of all function in the GKTurnBasedMatchmakerViewControllerDelegate protocol.

Which observer pattern should I use for remote app?

I am building a remote app which is receiving different states of its accessory. It is receiving things like: power state on/off, volume state 5, equalizer setting jazz, etc. and has nothing more to do than map theses states into the UI with selected or unselected states and send changes done back to the accessory.
About the app architecture:
The app is connected with it's accessory as illustrated in Apples EADemo project using the external accessory framework.
The UI is build within non-repeating customized UITableViewCell full of UIButtons. When starting the app a data model class will receive all current states from the examples EADSessionController and has to communicate theses states to the UI (the cells directly rather than the UITableViewController) with one of the mentioned patterns. This will be a stand alone, one-page app looking like a real remote.
Thinking of NSNotification, delegates and KVO (key-value-observing) I am trying to figure out which of these patterns I should use for this special approach?
Any answer on why choosing one of them and a brief description on how to implement would be appreciated. If your answer will be KVO please give some more insights since I never used this pattern so far.
It really depends.
The most loosely coupled one is to use NSNotification and NSNotificationCenter, as the instance which post the notification does not necessarily have knowledge about the observer, and there can be more than one observer.
The delegate pattern is a little more rigid, and there could usually be only one delegate object that receives a message. If the UITableViewController in your project is the only instance that handles a message(, or it would properly propagate the message to other components), it is still OK.
The KVO pattern requires more precisely designed observation relationship. You will have and have to look after exactly how the KVO is implemented. And KVO also allows one-to-many observation. The down side of KVO is if the observing relationship is dynamic and transient, you must take much more care about how these objects were torn down, or you could get a lot of crashes like sending updates to a dealloc'ed instance, etc.
If you are working on a library which would be delivered to a 3rd party to use, perhaps NSNotification would be the first choice.

Resources