Adding NSNotification observers to view controllers on a storyboard - objective-c

I am putting a test app together to demonstrate how users can be notified when something happens in the app (using NSNotifications). The user should be notified by an unobtrusive banner at the top of the screen regardless of what view controller is displayed at the time. I have the code already to draw the banner, but i am having problems setting up the NSNotification observers.
I have a storyboard with two viewcontrollers. How do I reference their init methods so i can add observers in for the NSNotification posts?

View controllers in a storyboard will be init'ed using initWithCoder:. You would usually have a separate set up method that is called from this, and from initWithNibName:bundle: just to cover you for all use cases.
Or, start observing in viewDidLoad and stop in viewDidUnload.

Related

Should we call ads in viewDidLoad or viewDidAppear?

We have a tab-heavy app, which has 5 tabs to use back and forth. We have iAds and admobs(as backup for countries without iAd), and we 'call' the ads in viewDidLoad. Would it make a difference to call them in viewDidAppear instead? And then remove them in viewDidDisappear or shomething not to screw up the frames etc? Would this give more impressions etc?
viewDidLoad:
viewDidLoad
Called after the controller’s view is loaded into memory.
- (void)viewDidLoad
Discussion
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.
viewDidAppear:
viewDidAppear:
Notifies the view controller that its view was added to a view hierarchy.
- (void)viewDidAppear:(BOOL)animated
Parameters
animated
If YES, the view was added to the window using an animation.
Discussion
You can override this method to perform additional tasks associated with presenting the view. If you override this method, you must call super at some point in your implementation.
Answering
So viewDidLoad is called slightly earlier than viewDidAppear: , the only difference is that when viewDidAppear: the view have been already drawn, instead in viewDidLoad the view has still to be drawn.
So answering to your questions:
Would it make a difference to call them in viewDidAppear instead?
If calling the ads is a slow operation, then you would see first the view appearing in it's color, and the ads after a few interval of time.However this has to be too slow to make a real difference.
And then remove them in viewDidDisappear or shomething not to screw up the frames etc?
It doesn't "screw up frames", that for sure.
you just need call it in viewDidLoad
Putting your ad code in viewDidAppear: (and removing it in viewDidDisappear:) will certainly give you more impressions, but unless you're a whitelisted pub, you're probably getting paid on a cost per click basis anyway (AdMob Help Center article).
In this case, instead of having the overhead of creating and destroying GADBannerView objects on tab changes, you might as well create a singleton GADBannerView that you use throughout your TabbedController (look at an example here).

NSNotification, addObserver and removeObserver - removeObserver both in ViewDidUnload and dealloc?

I want to add a view controller as observer of a notification.
When the selector method is called, I'll alert the user. I would that this alert appears only when this view controller is the top view controller.
I thought to add it as observer in the viewDidLoad method. But where is the better remove the view controller as observer?
Could it be a problem if I remove it both in viewDidUnload and dealloc?
No. According to the documentation:
Removes all the entries specifying a given observer from the receiver’s dispatch table.
If there are no such entries, there is nothing to remove, so it's not a problem.
However, depending on how you're using this, adding it as an observer in viewDidLoad doesn't mean that it will only be used when that view controller is "the top view controller" (for instance, if you have several tabs and move from one to the other, unless you get memory warnings the other (non-visible) tabs' views won't be unloaded when you move away from them).
Depending on your goal, it might be better to add the observer on viewDidAppear (and if so, remove on viewWillDisappear).

Cocoa Touch Subclass UIScrollView and Custom Delegate Still Receive Parent Delegate Messages

I have subclassed UIScrollView and added my own custom delegate (currently called delegate). I want to add functionality such as notifying a user when an image is tapped and perform loading like the table view.
However, If I define my own custom delegate, I can not set the parent delegate for responding to events such as scrollViewDidScroll (I want the subclass to receive these events). Should I rename the delegate in my subclass? Should I be using super.delegate in some form? Does a standard exist for doing this? Thanks!
Does your custom delegate just extend the methods of UIScrollViewDelegate? If it does, just override the methods -scrollViewDidScroll etc and forward the messages onto your own delegate.
Maybe I've misunderstood your question, so I apologize if I have.

Strategy for two mutually exclusive UIViews

I have been doing spring cleaning in my app. I noticed something strange, that, when I tried to correct it, completely crashes my app.
There are two "paths" in my app; either you are in the "A" part of it or you are in the "B" part. From the "A" part you can go to the "B" part and the other way around.
I designed it so that the app delegate class has two methods; switchToAView and switchToBView
So being in the middle of the BView and calling the switchToAView method on the app delegate should completely release everything related to the BView and send the user to the AView.
I found out when switching to the AView the BView view was still retained.
Each view is held by a property.
interface;
#property(nonatomic, retain) UIView *viewA
#property(nonatomic, retain) UIView *viewB
implementation;
#synthesize viewA, viewB
in the appDelegate.
I put a breakpoint in the dealloc method of the two views. (viewA and viewB).
Now this happens;
When loading up viewA and from there switching to viewB, nothing is released(as expected). Then when I switch from viewB to viewA, viewA is first released (by the generated setter, as far as I can figure out).
and then viewA is initialized and displayed.
This works just fine but has the downside that both viewA and viewB is alive on the stack at the same time :/ this is not desirable as they are mutually exclusive. The viewA is only released when a new viewA comes along, however, viewA should be released when a viewB is added to the window
I then tried releasing the viewA in the switchToBView method.
This works fine when going from viewA to viewB. I checked with instruments and the retain count drops to 0 for the viewA. Now when switching back to the viewA, the app crashes, and I think it is because the:
self.viewA = newlyInstantiatedViewA;
setter, first sends a release message to the viewA, but I released viewA earlier, and this causes the crash.
I can't get my head around that using a setter this way, will cause a crash. ("message sent to deallocated instance" and breaking in the dealloc method of the last subview added to A when [super dealloc] is called)
Should I have chosen a different approach all together?
And how will I build something sturdy, that ensures only one view is kept alive at a time?
Sorry for the lengthy writing, I would have written less if I had more time:
Thanks you in advance for any solution or design suggestions:)
Should I have chosen a different
approach all together?
Quite definitely, you mixed view controller logic into your views and you have views mutually retaining each other in what appears to be a circular reference.
(1) The views should not have logic for loading other view. Loading and unloading views is the function of the view controller. A view should only be concerned with logic immediately relating to the display. It should not even store or manipulate any user data.
(2) View controllers should seldom call other view controllers. The view controller should be concerned with managing the view and reading and writing data from the view to the data modal.
(3) If you need to relate views, use a UINavigation controller. It's not just for strictly visually hierarchal view patterns. Plus you can hide the nav bar so the user never sees it. You need to have a view controller that pushes viewA and when you need viewB, call the nav to pop viewA and push viewB. To the user, it will look like the views are simply swapping our. See the utility flip view for a similar use.
Your app works temporarily because there is nothing in the language or API that prevents you from cramming almost the entire application logic into a view subclass. However, keeping such a design running and reliable is nearly impossible.

How return back info from a child to parent in a NavigationController

I wonder what is the proper way to get back some message from a child view.
I have a object that is edited in the child view. I wanna see in the TableView their modifications.
However, I don't know a clean way to do it (I don't like a singleton here).
Is possible get notified when the Child view dissapear and get some info on that?
You can use the UIViewController notifications viewWillDisappear: and viewDidDisappear: to be notified right before a certain UIView is about to disappear and right after it disappears respectively. Note that most of the various UIKit objects (including UITableView) are subclasses of UIView.
IMHO, the "correct" way would be to implement a custom protocol in the view's controller (probably navigation controller in your case) or the application delegate and have the child view communicate using it when it gets the viewWillDisappear and/or viewWillDisappear notifications (as mentioned in Adam's reply). Similarly, in the parent view you can refresh the necessary information in the viewWillAppear handler.
This way, the parent view is getting its data from the delegate and not directly from a specific child view, which maintains MVC in your design.
You could also issue a notification (using NSNotificationCenter) that the parent would be subscribed to listen for - that has the side benefit that other classes could be notified as well.
But if it's a pretty strict relationship where only the sub view and master table will care, you probably should set your table view controller as a delegate of the subview and have the subview call the delegate directly (a protocol as mentioned is a good idea for something like this).