There is no built-in way to do it. I did it by adding a IBOutlet on the UIView and connecting these in Interface Builder.
There is no built-in way to do it. I did it by adding a IBOutlet on the UIView and connecting these in Interface Builder. I think you should ask yourself why do you need this, and if the View Controller can't do the job instead.(This was my experience).
5 That's very bad advice. You shouldn't reference a view controller from a view – Philippe Leybaert Oct 5 '10 at 19:23 @Philippe Leybaert: Wouldn't setting property to "assign" resolve the circular reference and resolve the problems with this approach? – Ivan VuÄ?
Ica Feb 25 at 13:14 @Philippe Leybaert, so are you saying Apple's very own BubbleLevel Xcode example app is bad? LevelView has an assign property to its viewController. – MattDiPasquale Jun 20 at 18:46 @MattDiPasquale: yes, it's bad design.
– Philippe Leybaert Jun 21 at 17:50 @Phillipe Leybaert I'm curious to know your thoughts on the best design for a button click event which should invoke some action on the controller, without the view holding a reference to the controller. Thanks – Jonathon Horsman Aug 22 at 16:05.
Using the example posted by Brock, I modified it so that its a category of UIView instead UIViewController and made it recursive so that any subview can (hopefully) find the parent UIViewController. @interface UIView (FindUIViewController) - (UIViewController *) firstAvailableUIViewController; - (id) traverseResponderChainForUIViewController; @end @implementation UIView (FindUIViewController) - (UIViewController *) firstAvailableUIViewController { // convenience function for casting and to "mask" the recursive function return (UIViewController *)self traverseResponderChainForUIViewController; } - (id) traverseResponderChainForUIViewController { id nextResponder = self nextResponder; if (nextResponder isKindOfClass:UIViewController class) { return nextResponder; } else if (nextResponder isKindOfClass:UIView class) { return nextResponder traverseResponderChainForUIViewController; } else { return nil; } } @end To use this code, add it into an new class file (I named mine "UIKitCategories") and remove the class data... copy the @interface into the header, and the @implementation into the . M file.
Then in your project, #import "UIKitCategories. H" and use within the UIView code: // from a UIView subclass... returns nil if UIViewController not available UIViewController * myController = self firstAvailableUIViewController.
1 And one reason you need to allow the UIView to be aware of its UIViewController is when you have custom UIView subclasses that need to push a modal view/dialog. – Phil M Sep 17 '10 at 5:32 Awesome , I had to access my ViewController to display a custom popup which is created by a subview – aryaxt Aug 12 at 6:00.
UIView is a subclass of UIResponder. UIResponder lays out the method nextResponder with an implementation that returns nil. UIView overrides this method, as documented in UIResponder (for some reason instead of in UIView) as follows: if the view has a view controller, it is returned by nextResponder.
If there is no view controller, the method will return the superview. Add this to your project and you're ready to roll. @interface UIView (FixedApi) - (UIViewController *)viewController; @end @implementation UIView (FixedApi) - (UIViewController *)viewController; { id nextResponder = self nextResponder; if (nextResponder isKindOfClass:UIViewController class) { return nextResponder; } else { return nil; } } @end Now UIView has a working method for returning the view controller.
– Lukasz Mar 31 at 10:16 Yes. I've updated the code. – Answerbot Sep 22 at 18:12.
Even though this can technically be solved as pgb recommends, IMHO, this is a design flaw. The view should not need to be aware of the controller.
I'm just not sure how the viewController can be told that one of its view's is going away and it needs to call one of its viewXXXAppear/viewXXXDisappear methods. – mahboudz Sep 3 '09 at 18:40 This is the idea behind the Observer pattern. The Observed (the View in this case) should not be aware of its Observers directly.
The Observer should only receive the callbacks that they're interested in. – Ushox Sep 4 '09 at 9:32.
Don't forget that you can get access to the root view controller for the window that the view is a subview of. From there, if you are e.g. Using a navigation view controller and want to push a new view onto it: self window rootViewController navigationController pushViewController:newController animated:YES; You will need to set up the rootViewController property of the window properly first, however.Do this when you first create the controller e.g. In your app delegate: -(void) applicationDidFinishLaunching:(UIApplication *)application { window = UIWindow alloc initWithFrame:UIScreen mainScreen bounds; RootViewController *controller = YourRootViewController alloc init; window setRootViewController: controller; navigationController = UINavigationController alloc initWithRootViewController:rootViewController; controller release; window addSubview:self navigationController view; window makeKeyAndVisible; }.
It seems to me that in accordance with Apple docs since self navigationController view is the "main" (sub)view of the window, the rootViewController property of the window has to be set to navigationController which controls the "main" view immediately. – adubr May 14 at 18:03.
My solution would probably be considered kind of bogus but I had a similar situation as mayoneez (I wanted to switch views in response to a gesture in an EAGLView), and I got the EAGL's view controller this way: EAGLViewController *vc = ((EAGLAppDelegate*)UIApplication sharedApplication delegate).viewController.
1 Please rewrite your code as follows: EAGLViewController *vc = (EAGLAppDelegate *)UIApplication sharedApplication. Delegate viewController;. – Jonathan Sterling Aug 21 '10 at 5:21 1 The problem is not with the dot syntax, but with types.In Objective C to declare an object you write ClassName *object - with an asterisk.
– adubr May 14 at 18:09 Oops... that's actually what I had, but the StackOverflow HTML widget thingy looks like it thought the asterisk meant italics... I changed it to a code block, now it displays correctly. Thanks! – gulchrider Aug 7 at 19:44.
There is no way. What I do is pass the UIViewController pointer to the UIView (or an appropriate inheritance). I'm sorry I can't help with the IB approach to the problem because I don't believe in IB.To answer the first commenter: sometimes you do need to know who called you because it determines what you can do.
For example with a database you might have read access only or read/write ...
I've launched it, it certainly exists. – marcc Jan 2 '10 at 0:33 2 You need a better grasp of fun and abstraction, especially with regards to the English language.It means I don't like it. – John Smith Jan 4 '10 at 16:44.
While these answers are technically correct, including Ushox, I think the approved way is to implement a new protocol or re-use an existing one. A protocol insulates the observer from the observed, sort of like putting a mail slot in between them. In effect, that is what Gabriel does via the pushViewController method invocation; the view "knows" that it is proper protocol to politely ask your navigationController to push a view, since the viewController conforms to the navigationController protocol.
While you can create your own protocol, just using Gabriel's example and re-using the UINavigationController protocol is just fine.
I think there is a case when the observed needs to inform the observer. I see a similar problem where the UIView in a UIViewController is responding to a situation and it needs to first tell its parent view controller to hide the back button and then upon completion tell the parent view controller that it needs to pop itself off the stack. I have been trying this with delegates with no success.
I don't understand why this should be a bad idea?
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.