这个问题让我疯狂。当用户更改分段控件的选定“选项卡”时,我试图更改viewController
。我花了几个小时的时间进行研究,一直未能找到可以通过故事板完成的答案。分段控制改变时更改视图控制器
它真的很麻烦,因为设置选项卡应用程序非常简单,但试图使用像Tab应用程序一样的分段控件只是不起作用。我已经知道如何检测在分段控制中选择哪个索引。我怎样才能做到这一点?
非常感谢。
这个问题让我疯狂。当用户更改分段控件的选定“选项卡”时,我试图更改viewController
。我花了几个小时的时间进行研究,一直未能找到可以通过故事板完成的答案。分段控制改变时更改视图控制器
它真的很麻烦,因为设置选项卡应用程序非常简单,但试图使用像Tab应用程序一样的分段控件只是不起作用。我已经知道如何检测在分段控制中选择哪个索引。我怎样才能做到这一点?
非常感谢。
我会说这是多少卡如果要在UIViewController
内更改子视图,则可以在故事板中设置子视图,并在控制器中将它们与IBOulets
挂钩,您可以将视图的hidden
属性设置为YES或NO,具体取决于所单击的控件。
现在,如果您使用@Robotic Cat的方法,这也是一个很好的解决方案,您可以在应用程序的工作方式上有更多的模块化,考虑到您必须使用我提供的解决方案将所有逻辑放在一个控制器中。
我喜欢你的建议只是在Xcode上试用过,看起来不错并且易于实现。我唯一担心的是将背景隐藏在背景中效率低下吗? – 2012-07-10 23:02:10
我还没有读过te开发人员文档中任何与此相反的内容,尽管您必须考虑如果添加了大量视觉元素,它会占用内存,因此明智地做。为了避免这种情况,您可以动态地灌输所需的一切,尽管我相信已经设置好所有元素的开销很小。例如,我只有4个子视图,每个子视图都有1或2个文本框。 – 8vius 2012-07-10 23:47:49
在我的一个iPad应用程序中,我有一个视图控制器,它有7个子视图可以显示或隐藏,每个子视图都有自己的一组控件。总共有大约60个视图和子视图(标签,按钮等)。我没有注意到任何缓慢或犹豫,并且Profier不会在内存或CPU中发现任何巨大的峰值。显然,你应该彻底测试你自己的解决方案,但我怀疑你会遇到问题。 – 2012-07-11 00:04:23
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
}
注:这是从内存中写入未经测试的代码 - 请相应参考文档。
注:答案与iOS视图控制器遏制码5+包括@接口部分
更新在我的应用程序,我有在导航栏段控制,并单击视图控制器“标签”切换视图控制器。基本思想是有一个视图控制器的数组,并使用段索引切换它们(以及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];
}
}
真的很好的解决方案。感谢分享这个。 – Mike 2013-03-13 06:23:35
@Robotic Cat:我有点困惑,为什么你将子视图控制器的框架设置为与父视图控制器相同。这个父视图控制器不包含UISegmentedControl吗?如果是这样,孩子视图控制器不会掩盖它吗? – Marplesoft 2013-08-10 22:32:06
@Marplesoft:通常“UISegmentedControl”位于导航栏中。显然,如果你的'UISegmentedControl'在你的视图控制器中,你应该将你的自动布局约束或框架设置为你的应用的正确值。 – 2013-08-10 23:39:08
查看此窗格:https://github.com/xmartlabs/XLMailBoxContainer。它使视图控制器之间的UI动画。这些视图控制器可以扩展UITableViewController或任何其他视图控制器。
我希望这对你有所帮助!
您是否想换出_view_或_view controller_?他们是两回事。如果是后者,我建议将所有东西都放到一个视图控制器中,并根据需要显示或隐藏子视图。 – 2012-07-10 22:29:36
嗯,我真的是iOS新手,我想到的最简单的事情就是改变viewController就像选项卡式应用程序一样。您是否建议制作各种视图并使用相同的视图控制器来管理它们?如果是这样,我该怎么做?非常感谢 – 2012-07-10 22:33:56