When To Observe/Unobserve Events - objective-c

I am currently using a UINavigationController based flow:
Events +-> Event Input
|
+-> People -> People Input
The model underlying Events and People fires notifications when the collection changes. I'm hooking up the observers in viewWillAppear:animated: and unhooking them in viewWillDisappear. This all seems fine, but what I really want is for the observer for people to be hooked up when I transition from Events to People and stay hooked up until I transition back to Events. That way, even when People Input hides People, the notification will be handled so I can update my list.
Note: I am not using segues.
Where are the best places to hook up the observers and unhook them?

Then you can enlarge the time scope from viewDidLoad for observing to dealloc for unobserving. Then you can update your content at the sole condition that the view actually exists.

The way I chose to fix this was to compare the current controller to the navigationController collection of viewControllers. If it is not contained in this collection, then I know the view was popped and I can unobserve events. I make this test in viewDidDisappear.

Related

How to get currently active UIEvent?

Background
I have a custom UIWindow implementation that posts a notification in the sendEvent method. Then I have a custom view that, once added to the window hierarchy, removes itself from superview as soon as the mentioned notification is posted (i.e. tapping anywhere, in this view or not, removes the view). Finally, I have a button that causes this custom view to be added to the view hierarchy. Now the problem is that when I tap this button, the view gets added to the view hierarchy, BUT, the event that was caused by this tap reaches my custom UIWindow sendEvent method AFTER the custom view is added, thus resulting in the custom view being removed immediately after it has been added.
Question
I want to somehow access whatever UIEvent is currently active. Is this possible to do, and if yes, then how?
I solved this by listening for the notification in order to track the most recent UIEvent (I provided the UIEvent in the userInfo). Then, when receiving the notification again, I made sure that it is not the same event as the one that occured just before the custom view appeared (if it is, I skip the removal of the custom view).
While this is an answer to my question, the solution to the underlaying problem that #matt proposed in an answer to the following SO question turned out to be much better: How can I know when any of the objects on screen were tapped?

Is there a way to disable sounds (such as "beeps") in my mac app?

I know I need to dig the reason why my app is beeping in the code, etc.
But I was wondering, is there a global setting to disable sounds all over my app screens?
this is very little information to go on, but usually your application is beeping when the responder chain comes up with no object that can respond to an event on the screen or keyboard.
For instance, if you type text in an active view and the view doesn't allow for text editing, the view sends the key down event to its super view. For a view this can end by the NSPanel or NSWindow or BSWindow controller. The last responder in the chain invokes the noResponderFor: method, which, when not implemented, will give a beep. If you don't want it to beep, override this method to do something else.
Based on your information I can't give you any other information.

Main Menu in different nibs

I have a Cocoa app with a ManMenu.xib, in which the main menu is stored and different other subviews in several xibs handling different tasks of my app. So how do I make my sub-xibs or rather their NSViewControllerController receive actions from the menu?
i have an idea but I don't know if it's the right way: I subclass NSViewController and add some actions like - (IBAction)undo or - (IBAction)redo use instances of it as the files owner. Further I add a pointer to my app delegate pointing at the actual view or rather its controller and the menu sends the action to that pointer.
Wise solution?
You should hook up your menu items to the First Responder. Their action messages will then travel along the responder chain until they reach something that responds to them.
You'll need to make sure your view controller is in the responder chain by setting it as the next responder of something else in the responder chain. I would suggest the window controller.
Speaking of the window controller, you probably should be handling undo there rather than in a view controller—it would be confusing for different views in the same window to have different undo lists. The only exception I can think of would be if the controlled views correspond to document tabs, like in Photoshop or Xcode.

Best way to wire up NSMenuItems from Interface Builder?

So I've spent some time checking out CocoaDev, reading the Cocoa docs on NSMenuItems, and doing some tests in Interface Builder.
In my application I have an application menu ([NSApp mainMenu]) designed in Interface Builder. I see three potential paths:
Put my action responders in the NSApplicationDelegate. This seems strange to me, partially because it's so far up the food chain, partially because it seems bolted on.
Create a sub-view(s) that would listen for the various NSMenuItem action messages. This would seem useful but it looks like in order for it to be in the responder chain there might be some magic I couldn't figure out.
Create an NSObject that listens for the specific application menu stuff, put it in the xib, and wire it up. This seems to me the best solution at the moment, because I can isolate stuff, and not depend upon the responder chain to reach a specific object. BUT I wonder if, when I get my app to a sufficient level of complexity, this may be a problem because it usurps the responder chain, which is there for perhaps a reason beyond just ease of use.
Sorry for the long question. Is there a preferred approach?
Thanks!
It really depends on the architecture of your application. As a general rule, implement actions wherever they make sense. The responder chain for action messages helps you in that regard.
If your application isn’t document-based, the responder chain for action messages goes like this:
Whichever responder is the first responder
View hierarchy
Window
Window controller
Window delegate
NSApp
Application delegate
I only use actions in the application delegate if they’re truly global for the entire application. Otherwise, I put them in the window controller (which is normally the window delegate as well) if they make sense for a specific window, or a view controller if they make sense for a specific view.
It’s worth mentioning that view controllers (subclasses of NSViewController) aren’t automatically inserted in the responder chain. I do that manually after adding the corresponding view to a superview. For instance, in an NSViewController subclass:
NSResponder *nextResponder = [[self view] nextResponder];
[[self view] setNextResponder:self];
[self setNextResponder:nextResponder];
This inserts self (an instance of a subclass of NSViewController) in the responder chain between the view and the original view’s next responder.
Note that there’s nothing inherently wrong with your third approach, namely having a specific target for (a subset of) action messages. The responder chain exists to give a chance for different objects to handle action messages because some actions can be context-dependent. For example, the actions under the File menu are normally applied to the window that’s currently the main window, so it makes sense to not have a specific target and use the responder chain instead. On the other hand, the actions under the ApplicationName menu are truly global—they don’t need to go through the responder chain, so you can hook them up to a specific target.
I usually just expose IBActions in the app controller (NSApp delegate), and wire the menu items up to those actions. This is a pretty standard way of doing things. If you have a lot of menu items, you can also break the functionality up into one or more controllers that are connected to the app controller, and wire the menu items up to them.

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).