views:

7303

answers:

4

Hi,

I am surely doing something completely stupid here, hopefully someone can tell me what! In summary I would like to programmatically toggle a subview when a button (I'll use a segmented button) is clicked. It need not animate. Ideally I'd load the contents of these views from a nib.

I am pushing a UIViewController subclass, initialised from a nib, on to a navigationController. This view controller & it's "default" view display ok. This nib contains:

File's Owner [Class=my view controller subclass]
First Responder
View
--Bar Segmented Control
--View //this is the 'subview' whose content I want to toggle

Perhaps I've made a mistake with my IB outlets? They are hooked up as follows:

switchableView <--> View
view <--> View

And where switchableView is declared:

IBOutlet UIView *switchableView;
...
@property (nonatomic, retain)   UIView *switchableView;

I am stuck at replacing the contents of this UIView. First off, I just want to set it to a default when the view first comes to life. Once I've got that, swapping it to something else should be easy as I can already capture the event generated by the segmented button. Can someone please tell me what I am doing wrong?

- (void)loadView {
NSLog(@"loadView invoked");
[super loadView];
UIView *view = [[UIView alloc] init];
UILabel *label = [[UILabel alloc] init];
label.text = @"Segment1";
[view addSubview:label];
[switchableView addSubview:view]; //this is what I can't work out
[view release];
[label release];    
}

That method is invoked (as is viewDidLoad), but neither help. I guess that I am doing [switchableView addSubview:view] wrong. I've also tried switchableView = view, but a long time in the safety of Java and Perl makes me not 100% sure whether that is right to try or not!

Here's hoping someone can set me straight. Thanks in advance,

Paul

A: 

Here are some snippets to help you. The first is simply the initialization for a navigation controller

// In AppDelegate.m
-(void)applicationDidFinishLaunching:(UIApplication *)application
{
  // Create and configure the main view controller.
  UIViewController *firstViewController = [[UIViewController alloc] init];

  // Add create and configure the navigation controller.
  UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:firstViewController];
  self.navController = navigationController;
  [navigationController release];

  // Configure and display the window.
  [window addSubview:navController.view];
  [window makeKeyAndVisible];
}

Then, when you're ready for a new view, just push one on there.

// Wherever you need to get your new view on there
UIViewController *secondViewController = [[UIViewController alloc] init];
[[self navigationController] pushViewController:secondViewController animated:YES];
[secondViewController release];

You should really be going through about 5 Apple Sample Projects a day in order to really become fluent in the iPhone world. Check out this one for starters: TableSearch.

TahoeWolverine
Cheers, but this isn't what I am after. I already have a view controller, and it's already displaying my view - I don't want to push a new view controller on the stack. What I want to do is utilise that view controller to swap out a subview that's embedded in my view.
Paul J
A: 

The most likely issue is that you are not setting the frame on your views, which means that while they are being successfully attached, they are 0x0 in size.

Try something like:

- (void)loadView {
  NSLog(@"loadView invoked");
  [super loadView];

  CGRect labelFrame = CGRectZero;
  labelFrame.size.height = switchableView.size.height;
  labelFrame.size.width = switchableView.size.width;

  UILabel *label = [[UILabel alloc] initWithFrame:labelFrame];
  label.text = @"Segment1";
  [switchableView addSubview:label]; //this is what I can't work out
  [label release];    
}

Also removed view because it was gratuitous (a UILabel is a UIView, you were stacking three view, 2 of which have nothing but a single subview which covers its full frame.) and it elided the UIViewController view property (in general it is bad to make local variables with the same name as instance variables or properties, there are compiler warnings you can turn on to avoid that).

Louis Gerbarg
A: 

If I understand your question correctly, you are trying to swap one view with another. One way to accomplish this is as follows:

Add an UIView to the root view named switchView. Either in code or in Interface Builder create a new UIView named subView1 and add it as a subclass of switchView when the root view loads:

[switchView addSubview:subView1];

When the user toggles the segmented control in the root view, create a new UIView in a similar fashion named subView2 and switch it with the current subview of switchView:

[subView1 removeFromSuperview];
[switchView addSubview:subView2];
titaniumdecoy
+1  A: 

Solved this in the end after inspecting the UICatalog sample code (with thanks to you both for giving me some pointers). The following works:

- (void)loadView {
    [super loadView];

    //define what will go in the seg1 view
    UILabel *mylabel = [[UILabel alloc] initWithFrame:switchableView.frame];
    mylabel.text=@"finally";
    self.seg1view = [[[UIView alloc] initWithFrame:switchableView.frame] autorelease];
    [self.seg1view addSubview:mylabel];
    [mylabel release];

    //define what will go in the seg2 view
    UILabel *mylabel2 = [[UILabel alloc] initWithFrame:switchableView.frame];
    mylabel2.text=@"it works!";
    self.seg2view = [[[UIView alloc] initWithFrame:switchableView.frame] autorelease];
    [self.seg2view addSubview:mylabel2];
    [mylabel2 release]; 

    //default the switchable view to seg1view
    [switchableView addSubview:self.seg1view];
}

-(void)doTheSwitch {
    if (segmentedButton.selectedSegmentIndex == 0) {
     [seg2view removeFromSuperview];
     [switchableView addSubview:seg1view];
    }
    if (segmentedButton.selectedSegmentIndex == 1) { 
     [seg1view removeFromSuperview];
     [switchableView addSubview:seg2view];
    } 
}

where the following are also defined as properties (retain, nonatomic)

IBOutlet UIView *switchableView;
UIView  *seg1view;
UIView  *seg2view;
Paul J