I need to model following in RAC.
I have a tabBarController which will subscribe to a notification signal. Say push notification. Also say currently active view controller may also be want to subscribe to the same signal. But if any view controller subscribed to it tabBarController doesn't want to handle it. Otherwise it will handle it. Also when current visible view controller changes. It needs to delegate back the responsibility to tabController.
Currently without RAC I maintain array of observers at tabController. If any observer present for particular kind of notification. It will delegate to viewController otherwise tabController will take care of it.
Any better way to model this using RAC?
Related
I have two controller in my screen and want to reload one method when push notification receive.
Now question is that listener successfully call when visible specific controller via NSNotificationCenter. But when i am on another controller then listener method not call.
Can i handle it via NSNotificationCenter? If no then what is the best approach for this? Thanks.
I have a navigation controller with 4 view controllers on the stack. I need to access a function in ViewController1 from ViewController4. What is the proper way to do this?
Do I pass the reference to ViewController1 through ViewController2 & 3 then access the function using a protocol delegate?
Do I store a reference to ViewController1 in a struct then access it from there?
Number 2 is what I am currently doing. I set the reference when I leave ViewController1 then set that reference back to nil when I'm done with it.
Why I need to do this:
VC1 has a tableview with a bunch of items. The data in these items is edited in VC4. Once editing is done in VC4 I want to save, pop to root, and reload the tableview with the new data.
Your plan is all wrong. What you should be doing is have a data model that can post notifications about changes in its data. There should be no link whatsoever between the view controllers. VC1 should be prepared to listen for notifications from the data model. When VC4 updates the data model, the data model will tell anyone that is listening that it has been updated.
With this setup, any number of view controller can all be listening to the same instance of the data model being passed around. Any part of your app can respond as needed to these notifications. The best part of this design is that no class has any knowledge of any other specific class except everyone knows about the data model.
The data model has no knowledge of any controllers or views.
No controllers have any direct link to other controllers except for one that needs to present another.
I think you can use notification. Make VC1 to subscribe the notification. When need, in VC4, send the notification.
I am a new iOS developer so please bear with me if I seem a little ignorant.
I am trying to make an app for a gallery. I want to use iBeacons in each category of the gallery. I know how to make this all happen if I am only using one view controller. I can make it range for the beacon and once in a certain range send a pop up stating "You have entered the "XXXX" area. Would you like to view these exhibits?"
If the user presses yes, it will take them to it. However, the problem I am running into is that I need to have quite a few view controllers. So How can I get the ranging to happen in the background of all of them? Should I create a separate Swift file and do all the ranging there and then call that class in each view? Or should (or even could) I do all the beacon code in the app delegate.
The next problem that I have is how to segue to the "category" view controller when a user is in a view controller that doesn't have the actual segue? Say VC 1 has a segue to VC 2 with identifier #3. Can I call the segue with ID #3 from VC 5, for an example? Or is it better to instantiate the views?
Will appreciate any tips.
This kind of centralized logic fits well into the AppDelegate as it is designed to handle global app logic. It is easy and a common practice to set up beacon monitoring and ranging in the didFinishLaunching callback.
To launch specific view controllers, it is easiest to instantiate and present them programmatically (rather than using a segue) when a change is needed based on beacon detection in a callback in the AppDelegate.
Good morning.
I have been working through a lot of tutorials the past year, and have seen several methods of passing reference back up the View Hierarchy with Storyboards. I was wondering what some best practices are, and more importantly any pitfalls using the following methods:
Protocol - the child view implements a protocol, that the parent view sets itself as the delegate to and responds to messages. This can be used to pass back information to the delegate. The Child does not need to know anything about the reason it was called, it does it's job, and sends back whatever information it was asked for.
Public property of the Child ViewController that has the model reference. On the segue you retrieve the reference to the destination view Controller. This view controller has the model property exposed publically. You pass in your reference to the model. I personally like this method - can't see any real pitpalls with it. then when the child makes changes the model is changed directly. at the point [self.navigationController dismissViewControllerAnimated:YES] gets called to or however you navigate off/dismiss the view controller you have the information in the model you want.
ANYTHING ELSE? - someone else has a good idea, i'd love to hear it.
Thanks for anyone's input on this. I know there are always more than 1 way to skin a cat, I just want to skin the cat cleanly and quickly. (-Sorry cat)
Steve
For the sake of completeness, in addition to the two options you enumerate, there are a couple of other options:
Use unwind segue (iOS 6 and later), and you can pass data to the "destination" (the controller you're unwinding to) via prepareForSegue;
Use singleton for your master model object;
Use Core Data (or SQLite) for persistent storage; or
Use notifications or key value observation (though this is much better for communicating data updates to multiple objects).
Personally, I'll generally use a protocol when it's just a matter of a presented view controller wanting to inform the presenting view controller of some information, but each of these techniques have their respective uses.
Depending on your need there is another option and no segue is required.
The child view controller could create its own object or obtain a known shared reference of any object. Creating its own object would be good for adding a new item to a table. Obtaining a known shared reference would be good for something like a settings object.
When the child view controller is ready to be dismissed it posts a notification.
[[NSNotificationCenter defaultCenter] postName:MyAppDidCreateNewItem object:self.item];
or
[[NSNotificationCenter defaultCenter] postName:MyAppDidUpdateSettings object:self.settings];
The parent view controller registers as an observer to the notification. When the notification happens, the parent view controller can use notification.object to get the reference and update itself.
I'm wondering if there's any way -viewWillAppear: would be called without a matching -viewDidAppear:. Ditto for -viewWillDisappear and -viewDidDisappear.
The root of my question is where to register and unregister for KVO and / or NSNotifications of an object who's change notifications will cause the view controller to update views.
For example, I have a model object that is being processed asynchronously and it's string properties could change. I'd like the view controller to KVO those properties and have any changes reflected by swapping out the text of a label managed by said view controller.
Where do you register and unregister for notifications and why?
EDIT:
A gotcha I've come across is what to do in cases of application state change (e.g. -applicationWillResignActive, -...didEnterBackground, etc). These changes don't seem to trigger view controller lifecycle methods. Any best practices here?
With the standard container view controllers, you will always get will/did messages in pairs. If you have written your own view controller container, you may not, but that would be a bug in the container implementation.
Most of the time, you'll want to set things up and tear things down in the 'will' messages. This gives your view controller the earliest shot at anything it needs to do before it becomes "active" and also shuts down things as early as possible when you no longer need them.
When pushing a view controller in nav stack, it is entirely possible that a notification will occur during the push animation. If you set up the observers in viewDidAppear, you would miss that notification. You want to be listening as soon as possible.
Likewise, I would reckon that viewDidDisappear is too late to remove callbacks. For example, a location manager could be stopped in viewDidDisappear, but another location update could be delivered during the disappearing animation. That probably doesn't hurt much, but depending on the application, something weird could happen like an alert view appearing after you've already left a view controller - which looks like a flicker to the user.
Anything non-view related, as indicated above, occur in the 'will' methods. The choice about will vs did, then, is really about what the user sees. Animations should start in viewDidAppear, otherwise, the user won't see the frames that occur during will/did appear. Data should be moved to views in viewWillAppear, otherwise, a blank view will transition in and the data will only appear after the transition animation completes. Also, it possible that a view frames could be adjusted in between viewWillAppear/viewDidAppear, like in the case of a previous view controller in the stack hiding/showing the navigation bar.
And on a side note, not something I will get into great detail here with, but I'd advocate against KVO for controller interactions that move data from model to view objects. Difficult to test and difficult to trace.
You can subclass your UILabel and in your subclass override the setText method:
-(void)setText:(NSString *)newText {
//do your KVO updates here
[super setText:newText];
}
hope this helps