分段控制更改时更改视图控制器

时间:2012-07-10 22:16:06

标签: ios storyboard

这个问题让我抓狂。我在用户更改所选的"标签"时尝试更改viewController。分段控制。我花了几个小时进行研究,并且无法通过故事板找到有效的答案。

由于设置标签应用程序非常简单,所以真的很烦我,但尝试使用像标签应用程序这样的分段控件却无法正常工作。我已经知道如何检测分段控件中选择的索引。我怎样才能做到这一点?

非常感谢。

4 个答案:

答案 0 :(得分:42)

注意:使用适用于iOS 5+的视图控制器包含代码更新了答案,包括@interface部分

在我的应用程序中,我在导航栏中有一个带有Segment Control的视图控制器,然后单击“tabs”切换视图控制器。基本思想是拥有一个视图控制器数组,并使用Segment Index(和indexDidChangeForSegmentedControl IBAction)在它们之间切换。

我的应用程序中的示例代码(iOS 5或更高版本)(这适用于2个视图控制器,但它可以简单地扩展到多个视图控制器);代码比iOS 4略长,但会保持对象图完好无损。此外,它使用ARC:

@interface MyViewController ()
// Segmented control to switch view controllers
@property (weak, nonatomic) IBOutlet UISegmentedControl *switchViewControllers;

// Array of view controllers to switch between
@property (nonatomic, copy) NSArray *allViewControllers;

// Currently selected view controller
@property (nonatomic, strong) UIViewController *currentViewController;
@end

@implementation UpdateScoreViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the score view controller
    ViewControllerA *vcA = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerA"];

    // Create the penalty view controller
    ViewControllerB *vcB = [self.storyboard instantiateViewControllerWithIdentifier:@"ViewControllerB"];

    // Add A and B view controllers to the array
    self.allViewControllers = [[NSArray alloc] initWithObjects:vcA, vcB, nil];

    // Ensure a view controller is loaded
    self.switchViewControllers.selectedSegmentIndex = 0;
    [self cycleFromViewController:self.currentViewController toViewController:[self.allViewControllers objectAtIndex:self.switchViewControllers.selectedSegmentIndex]];
}

#pragma mark - View controller switching and saving

- (void)cycleFromViewController:(UIViewController*)oldVC toViewController:(UIViewController*)newVC {

    // Do nothing if we are attempting to swap to the same view controller
    if (newVC == oldVC) return;

    // Check the newVC is non-nil otherwise expect a crash: NSInvalidArgumentException
    if (newVC) {

        // Set the new view controller frame (in this case to be the size of the available screen bounds)
        // Calulate any other frame animations here (e.g. for the oldVC)
        newVC.view.frame = CGRectMake(CGRectGetMinX(self.view.bounds), CGRectGetMinY(self.view.bounds), CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));

        // Check the oldVC is non-nil otherwise expect a crash: NSInvalidArgumentException
        if (oldVC) {

            // Start both the view controller transitions
            [oldVC willMoveToParentViewController:nil];
            [self addChildViewController:newVC];

            // Swap the view controllers
            // No frame animations in this code but these would go in the animations block
            [self transitionFromViewController:oldVC
                              toViewController:newVC
                                      duration:0.25
                                       options:UIViewAnimationOptionLayoutSubviews
                                    animations:^{}
                                    completion:^(BOOL finished) {
                                        // Finish both the view controller transitions
                                        [oldVC removeFromParentViewController];
                                        [newVC didMoveToParentViewController:self];
                                        // Store a reference to the current controller
                                        self.currentViewController = newVC;
                                    }];

        } else {

            // Otherwise we are adding a view controller for the first time
            // Start the view controller transition
            [self addChildViewController:newVC];

            // Add the new view controller view to the ciew hierarchy
            [self.view addSubview:newVC.view];

            // End the view controller transition
            [newVC didMoveToParentViewController:self];

            // Store a reference to the current controller
            self.currentViewController = newVC;
        }
    }
}

- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl *)sender {

    NSUInteger index = sender.selectedSegmentIndex;

    if (UISegmentedControlNoSegment != index) {
        UIViewController *incomingViewController = [self.allViewControllers objectAtIndex:index];
        [self cycleFromViewController:self.currentViewController toViewController:incomingViewController];
    }

}
@end

原始示例(iOS 4或之前版本):

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    // Create the score view controller
    AddHandScoreViewController *score = [self.storyboard instantiateViewControllerWithIdentifier:@"AddHandScore"];

    // Create the penalty view controller
    AddHandPenaltyViewController *penalty = [self.storyboard instantiateViewControllerWithIdentifier:@"AddHandPenalty"];

    // Add Score and Penalty view controllers to the array
    self.allViewControllers = [[NSArray alloc] initWithObjects:score, penalty, nil];

    // Ensure the Score controller is loaded
    self.switchViewControllers.selectedSegmentIndex = 0;
    [self switchToController:[self.allViewControllers objectAtIndex:self.switchViewControllers.selectedSegmentIndex]];
}

#pragma mark - View controller switching and saving

- (void)switchToController:(UIViewController *)newVC
{
    if (newVC) {
        // Do nothing if we are in the same controller
        if (newVC == self.currentViewController) return;

        // Remove the current controller if we are loaded and shown
        if([self.currentViewController isViewLoaded]) [self.currentViewController.view removeFromSuperview];

        // Resize the new view controller
        newVC.view.frame = CGRectMake(CGRectGetMinX(self.view.bounds), CGRectGetMinY(self.view.bounds), CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));

        // Add the new controller
        [self.view addSubview:newVC.view];

        // Store a reference to the current controller
        self.currentViewController = newVC;
    }
}

- (IBAction)indexDidChangeForSegmentedControl:(UISegmentedControl *)sender {

    NSUInteger index = sender.selectedSegmentIndex;

    if (UISegmentedControlNoSegment != index) {
        UIViewController *incomingViewController = [self.allViewControllers objectAtIndex:index];
        [self switchToController:incomingViewController];
    }

}

答案 1 :(得分:4)

我说更改UIViewController中的子视图要简单得多,您可以在故事板中设置子视图,并在控制器中用IBOulets连接它们,您可以设置{{1}根据所单击的控件,您的视图属性为YES或NO。

现在,如果您使用@Robotic Cat的方法,这也是一个很好的解决方案,您可以在应用程序的工作方式上更加模块化,考虑到您必须使用我提供的解决方案将所有逻辑放在一个控制器中。

答案 2 :(得分:0)

UISegmentedControl有点不同,因为它没有委托协议,你必须使用“添加目标”样式。在您的情况下,您要做的是添加一个目标,以便在UISegmentedControl更改时通知(可能是父视图控制器),然后该目标可以处理选项卡切换。

例如:

[self.mainSegmentedControl addTarget:self action:@selector(changedSegmentedControl:) forControlEvents:UIControlEventValueChanged];

在此示例中,从某个视图/控制器调用代码,该视图/控制器可以访问分段控件的变量。我们添加自己来获取调用的changedSegmentedControl:方法。

然后你会有另外一种方法:

- (void)changedSegmentedControl:(id)sender
{
   UISegmentedControl *ctl = sender;
   NSLog(@"Changed value of segmented control to %d", ctl.selectedSegmentIndex);
   // Code to change View Controller goes here
}

注意:这是从内存中编写的未经测试的代码 - 请相应地查阅文档。

答案 3 :(得分:0)

看看这个广告:https://github.com/xmartlabs/XLMailBoxContainer。它在视图控制器中创建UI动画。这些视图控制器可以扩展UITableViewController或任何其他视图控制器。

我希望这能帮到你!