1

I have implemented a subclass of ECSlidingViewController.

InitialViewController.h
@interface InitialViewController : ECSlidingViewController

@property (nonatomic, strong) WebViewController *webVC;
@property (nonatomic, strong) MenuViewController *menuVC;

@end

I need access to the .webVC from the .menuVC, but am unable to access them from self.parentViewController.webVC getting the error:

 "UIViewController does not have a member named webVC"

but when I check in the debugger

po self: <MenuViewController>
po self.parentViewController: <InitialViewController>
po self.parentViewController.webVC: error: property 'webVC' not found on object of type 'UIViewController *'

However, when I navigate the object tree of self in the local variable window, I can go

-self <MenuViewController> 0x0000001
  -UITableViewController
    -UIViewController
      -_parentViewController <InitialViewController>
        -webVC <WebViewController
        -menuVC <MenuViewController> 0x0000001

Where self and self.parentViewController.menuVC have the same memory address

When I navigate down and right-click->print Description, I get

    Printing description of self->_parentViewController->menuVC:
<MenuViewController: 0x8e8c720>

Those '->' and the '_' make me think I'm seriously missing something involving pointers and ivars.

I'm also interested if there is a better way to implement this functionality. This kind of smells like I'm breaking MVC with a child Controller knowing about itself and its parent. However, selections on the menu directly manipulate the webView I have loaded.

Liftoff
  • 24,717
  • 13
  • 66
  • 119
oflannabhra
  • 661
  • 5
  • 18
  • See [this post][1] about HttpPostedFileBase. [1]: http://stackoverflow.com/questions/8475023/request-files-is-empty-in-mvc-file-upload – NovaJoe Mar 27 '14 at 21:32

1 Answers1

3

Answer:

UIViewController does not have this property built in so you need to cast it:

[(InitialViewController*)self.parentViewController webVC]

Explanation:

This is a question of Classes and SubClasses. Say I have a class MyView which is a subclass of UIView. This class has a couple methods on it, -(void)method1; and -(void)method2;. The .h would look something like this:

@interface MyView : UIView

- (void)method1;
- (void)method2;

@end

I then create a MyView* named thisView and assign it to my ViewController's view property:

#import "MyView.h"

- (void)viewDidLoad
{
    MyView* thisView = [[MyView alloc] init];
    [self setView: thisView];
}

The UIViewController class's property, view is declared like this:

@property (...) UIView* view;

Pay extra special attention to the UIView* there.

Because view is declared as a UIView*, it will accept values that are subclasses of UIView*, but when I access it later, it will give me a MyView in a box labeled UIView.

In other words, consider this code:

- (void)viewDidLoad
{
    MyView* thisView = [[MyView alloc] init];
    [self setView: thisView];

    UIView* returnedView = thisView; //This is perfectly fine
}

UIViewController will return something along the lines of returnedView, which is a MyView in a UIView container.

When your program goes to access the view, all it knows is that has received something in a box labeled "UIView", so it only knows that it can run methods on it that are present in the UIView class. We have to explicitly tell it "No, this is a MyView," and we do that with casting:

[self.view method1]; //This will break
[(MyView*)self.view method1]; //This will work

Back to your problem

When you access self.parentViewController, you are given a InitialViewController in a UIViewController box, so you have to explicitly tell your program that it is an InitialViewController. You do that by casting:

InitialViewController* parentVC = (InitialViewController*)self.parentViewController;
[parentVC.webVC doSomething];

Warning:

Your VC that is accessing webVC must have a declaration of (InitialViewController*), so you'll need to watch out for forward declaration errors.

If you are unfamiliar with this, it is when Class A imports Class B, but Class B also imports Class A:

A
--->Import B

B
--->Import A

Which results in

A
--->Import B
------->Import A
----------->Import B
and so on.

A class cannot import itself.

Liftoff
  • 24,717
  • 13
  • 66
  • 119