简体   繁体   中英

If I add a control programmatically in viewDidLoad, how do I access it from other methods?

In my viewDidLoad method of my main View Controller I programatically create a segmented control and then add it to the titleView of my Navigation Control.

NSArray *seggieItems = [[NSArray alloc] initWithObjects:@"See Entire List",@"See Near Me", nil];
UISegmentedControl *seggie = [[UISegmentedControl alloc]initWithItems:seggieItems];
[seggie setSegmentedControlStyle:UISegmentedControlStyleBar];
[seggie setTintColor:[UIColor redColor]];
[seggie addTarget:self
           action:@selector(seggieChanged:)
 forControlEvents:UIControlEventValueChanged];


self.navigationItem.titleView = seggie;

However when I want to access this Segmented Control from another method, such as viewWillAppear, I can't - it's an undeclared identifier.

    - (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [seggie setSelectedSegmentIndex:0]; //this should always be 0 for this view controller viewDidLoad method

}

If I was using a XIB this would be no problem since I'd have an IBOutlet I could use from anywhere. I tried creating a property for my Segmented control, but then the instance variable hides the local variable, so this must be the wrong approach.

What's the best way to go about this? I apologize if this is a stupid question - I'm fairly new to iOS, currently about halfway through a couple of books. I couldn't find an answer on Google or searching StackOverflow. I would appreciate any help, and I'm sorry if this is something really simple that I'm missing. Thanks

Making it a property is the correct approach. If you do that, and get the mask warnings you describe, you are probably still declaring the seggie variable in your viewDidLoad method. Remove that declaration and always refer to self.seggie instead of seggie and you'll be fine.

By declaration I mean this line:

UISegmentedControl *seggie = [[UISegmentedControl alloc]initWithItems:seggieItems];    

It should be

self.seggie = [[UISegmentedControl alloc]initWithItems:seggieItems];

There are 2 ways you can do this:-

1>Either declare the object for UISegmentedControl in the .h file (global) adn no property is needed for same class unless you want to access from some other class.

2>You can iterate through subviews of the parentview and get the UISegmentedControl and typecast it to perfrom OPerations , such as:-

NSArray *subviewss=[self.view subviews];
for(int i=0;i<[subviewss ;i++])
{
if([[subviews objectAtIndex:i] isKindOfClass:[UISegmentedControl class]])
{
UISegmentedControl *segmentControl= (UISegmentedControl *) [subviewss objectAtIndex:i];
[segmentControl setSelectedSegmentIndex:0];

}
}

but the above looped code will wrk only if you have only one segmented control as subview in your viewcontroller else it will bump into anything that is of class type UISegmentedControl.

Put this UISegmentedControl *seggie; line of code in your .h(header) file, or make it Global !

You can't use a local created object in other method. Local and Instant Variable .It's for java but i hope you will understand the main idea.

Above suggestion options are good, either create a property or class wide/global variable. One more approach, if you don't want to define property or class wide/global variable-

access control like -

for (int index = 0; index < [self.view.subviews count]; index++) {
    if([[self.view.subviews objectAtIndex:index] isKindOfClass:[UISegmentedControl class]]) {
        UISegmentedControl *seggie = (UISegmentedControl *) [self.view.subviews objectAtIndex:index];
        [seggie setSelectedSegmentIndex:0];
    }
}

Not really a comment but some general advice

Yes this would indeed be the most inefficient way of getting a view.

For a start if you use fast enumeration you can at least get rid of the repeated use of the

[self.view.subviews objectAtIndex:index]

call, which is really

[[[self view] subviews] objectAtIndex:index]

method dispatch is fast but that doesn't mean you should not think about what your code is actually doing.

Your code does not account for multiple controls as they are all treated the same (eg set to 0).

There is also no early exit from this loop once you have found the object you are after. If you insisted on cycling through the views at least do it nicely -

for (UISegmentedControl *seggie in [self.views.subviews]) { 
    if ([seggie isKindOfClass:[UISegmentedControl class]]) { 
        seggie.selectedSegmentIndex = 0; 
        break; 
    } 
}

You gotta either make a property of

UISegmentedControll *seggie

in your header file, or make the array global.

If that's no option for you, I would try accessing it using

UISegmentedControl * temp = self.navigationController.titleView;
[temp setSelectedSegmentIndex:0];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM