Get UINavController from subview of UIView? - objective-c

I added a custom subview to a UIViewController's content view. From that subview, how can I get a reference to the superview's controller?
Thanks

The correct answer is "You're Doing It Wrong™" ;-)
You shouldn't need to reference to a view controller from a view, and you certainly should never retain a view controller in one of your views -- or you'll end up with a retain loop and leak memory.
Cocoa provides multiple patterns to solve this problem:
Use a delegate: Define a protocol called DemoViewDelegate and add a delegate property to DemoView. Then have your view controller implement this protocol. Important: delegates should never be retained! Any delegate property you create should be set to assign. See Apple's Delegation docs or just google "delegation pattern".
Use the responder chain: Call UIApplication's sendAction:to:from:forEvent: and leave to: set to nil to have your action message automatically routed up the responder chain to your view controller. See Apple's Responder docs and the more detailed Action Messages docs.
Use a notification: Less common in this particular scenario, but you could also have your view controller listen for a notification, which the view sends.

Related

Send data back to rootviewcontroller before a popToRootViewController method call?

What is the best way to send data back to the root view controller before calling the popToRootViewControllerAnimated method? I am trying to signal to the rootviewcontroller that the current viewcontroller no longer exists and keep a record of what viewcontroller has been pushed thru segue.
You mustn't wait until the current view controller "no longer exists". While the current view controller does exist, the root view controller is the current view controller's navigationController.viewControllers[0]. So you have the reference you need to send a message from this one to that one. Just cast to the root view controller's class and now you can call any public method in the root view controller, e.g.
MyRootViewController* rvc = (MyRootViewController*)(self.navigationController.viewControllers[0]);
rvc.coolData = myCoolData;
There are two basic ways to do this: 1) with an NSNotification message or 2) with a delegate call. There are plenty of tutorials on how to code both. I wrote a small delegate tutorial as an answer to this question: Back button in iphone app and you can find a great NSNotification tutorial here: Send and receive messages through NSNotificationCenter in Objective-C?
You can subclass UINavigationController and override the necessary methods to track your array. I would recommend keeping a uniqued set of titles for each view controller popped off the stack. As for signaling to the current view controller that the previous view controller doesn't exist, that's what -viewWillAppear is for. If you need finer-grain control, create a protocol for your View Controller instances to conform to that the navigation controller calls out to when it pops one or more of them off the stack.

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.

Calling another view from within a view class

i may be making more out of this because of the late hour. i am confused. i have multiple views i call from a viewcontroller class. typically they are called with a uibutton object. say i have two views. main and child view. here is how i would call the child while the main view is visible.
[self presentModalViewController:childViewController animated:YES];
now because i want to use touch events to call the child view i believe i am forced to initiate the events from with the main view's class.
so how do i call the child view from within the main view class as i would when i am in the view controller class.
thanks for any help!!
If I understand you correctly, you're wondering if you need to handle touches in the main view itself, rather than in the main view controller. If that is correct, the answer is no, you don't have to.
The way events work in Cocoa is that they propagate up through a chain of objects called the responder chain. The last/lowest object in the chain is given a chance to respond to the events first. In this case, that object is your "main view". If the object can not respond to the event, the event goes to the next object in the chain, what's called the object's next responder. This progresses up the chain until an object responds to the event.
The reason you don't have to worry about this is that a UIView's next responder is its view controller. This means that if you don't handle the event in your view, it propagates up to the view's controller (and, if you don't handle it there either, it continues up the responder chain). So, if you implement the -touchesBegan:withEvent:, -touchesMoved:withEvent, and the other event-based methods in your view controller and not in your view, you'll be fine.
For further reading on event handling in Cocoa, see this section of the iPhone Application Programming Guide.

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