hfossli
hfossli

Reputation: 22962

Setting a subview in UIViewController

EDIT: This question is due to a big lack of understanding how Interface Builder and properties in classes works.

Why can't i just set self.mySubView = anoterhView; like one can set self.view = anotherView; ?

## .h
@interface TestController : UIViewController {
    IBOutlet UIView *mySubView;
}

@property (nonatomic, retain) IBOutlet UIView *mySubView;

##.m

@implements TestController

@synthesize mySubView;

- (void)viewDidLoad { 

    AnotherController *anotherController = [[AnotherController alloc] initWithNibName:nil bundle:nil];
    anotherView = anotherController.view;

    // if i do
    self.view = anotherView;
    // result: replaces whole view with anotherView

    // if i instead do
    self.mySubView = anotherView;
    // result: no change at all

    // or if i instead do:
    [self.mySubView addSubview:anotherView];
    // result: mySubView is now displaying anotherView

}

NOTE: I'm using interfacebuilder. I'm sure everything is hooked up allright because self.view, and self.mySubView addSubview: is working allright..

Upvotes: 1

Views: 3198

Answers (4)

Deepak Danduprolu
Deepak Danduprolu

Reputation: 44633

mySubview is a property which is a reference to an UIView object. So when you assign an UIView object to it, you are merely changing what mySubview is referring to and no more as in this case,

self.mySubview = anotherView;

The original UIView object that mySubview was referring to is still referred to within view's subviews property. Nothing changes.

But when you add anotherView as a subview of mySubview, anotherView belongs to the view hierarchy and is displayed on screen. So this works.

view (parent of) mySubview (parent of) anotherView

However when you assign anotherView directly to the view, You not only change the UIView object view was referring to but it also adds itself to the parentView. This is handled by UIViewController.

self.view = anotherView;



Your setCurrentView should be more or so like this,

- (void) replaceSubview:(UIView *)newView {
  CGRect frame = mySubview.frame;

  [mySubview removeFromSuperview];
  self.mySubview = newView;

  [self.view addSubview:newView];
  newView.frame = frame;
}



Upvotes: 1

hfossli
hfossli

Reputation: 22962

As a response to what @beefon said. This works kind of as expected, but background-color is transparent. It doesen't respond either... buttons do not get pressed etc..

- (void)setCurrentView:(UIView *)newView {
    /*      1. save current view.frame: CGRect mySubViewFrame = [mySubView frame]; 
            2. remove and put new subview - I have wrote how to do it 
            3. set new frame for new view: [mySubView setFrame:mySubViewFrame];      */ 
    CGRect currentViewFrame = [currentView frame];
    [currentView removeFromSuperview];
    [currentView autorelease];
    currentView = [newView retain];
    [self.view addSubview:currentView];
    [currentView setFrame:currentViewFrame]; 
}

Upvotes: 0

Jab
Jab

Reputation: 27485

Your instance variable needs to be a property in order to use the dot. syntax, use:

@Property (nonatomic, retain) IBOutlet UIView* subview;

in the header, and use:

@synthesize subview;

in the main file.

In order to set a UIView using the dot. syntax you need to make it a property. This also allows you to set the subview's properties outside the class.

Upvotes: -1

beefon
beefon

Reputation: 3192

To make it automatically appear on your self.view you need to overwrite your setter method, e.g.:

- (void)setMySubView:(UIView *)view {
    [mySubView removeFromSuperview];  // removing previous view from self.view
    [mySubView autorelease];
    mySubView = [view retain];
    [self.view addSubview: mySubView]; // adding new view to self.view
}

Upvotes: 2

Related Questions