Iphone UISegmentedControl最佳实践

Iphone UISegmentedControl最佳实践,iphone,subview,uisegmentedcontrol,Iphone,Subview,Uisegmentedcontrol,我正试图找出一种“最佳”方法,在iPhone应用程序中使用UISegmentedControl。我在这里读了一些关于stackoverflow的帖子,看到了一些人的想法,但我不太清楚最好的方法是什么。我指的是: 和 这些选择似乎是: 在IB中添加每个视图,并将它们放置在彼此的顶部,然后显示/隐藏它们 在IB中分别创建每个子视图,然后在主视图中创建一个容器以填充所需的子视图 设置一个非常高或非常宽的ui视图,并根据选定的线段设置左/右或上/下动画 使用UITabBarController交换

我正试图找出一种“最佳”方法,在iPhone应用程序中使用
UISegmentedControl
。我在这里读了一些关于stackoverflow的帖子,看到了一些人的想法,但我不太清楚最好的方法是什么。我指的是:

这些选择似乎是:

  • 在IB中添加每个视图,并将它们放置在彼此的顶部,然后显示/隐藏它们
  • 在IB中分别创建每个子视图,然后在主视图中创建一个容器以填充所需的子视图
  • 设置一个非常高或非常宽的
    ui视图
    ,并根据选定的线段设置左/右或上/下动画
  • 使用
    UITabBarController
    交换子视图-看起来很愚蠢
  • 对于表格,请重新加载表格并在
    cellforrowatinex
    中,根据所选的段选项从不同的数据源或部分填充表格(我的应用程序不是这样)
那么,对于子视图/非表方法,哪种方法最好?哪一个最容易实现?你能给我们分享一些示例代码吗


谢谢

我将使用您提到的第二个选项,在IB中创建子视图,并在主视图中交换它们。这将是一个使用
UIViewController
,非类化的好机会:在初始设置中,使用
-initWithNibName:bundle:
(其中第一个参数是包含单个子视图的NIB的名称,第二个参数是
nil
)并根据需要将其
视图添加为主视图的子视图。这将有助于降低内存占用:当收到内存警告时,
UIViewController
的默认行为是在没有superview时释放其视图。只要从视图层次结构中删除隐藏视图,就可以将控制器保留在内存中,而无需担心释放任何内容

(根据评论编辑:)

您不需要子类化
UIViewController
,但每个视图都需要单独的XIB。您也不需要向IB中的包含视图添加任何内容

实例变量,在处理所有这些的任何类的接口中:

 UIViewController *controllerOne;
 UIViewController *controllerTwo;

 UIViewController *currentController;

 IBOutlet UIView *theContainerView;
在您的设置中(
-applicationdFinishLaunching:
或其他任何内容)

要切换到控制器,请执行以下操作:

 - (void)switchToController:(UIViewController *)newCtl
 {
      if(newCtl == currentController)
           return;
      if([currentController isViewLoaded])
           [currentController.view removeFromSuperview];

      if(newCtl != nil)
           [theContainerView addSubview:newCtl.view];

      currentController = newCtl;
 }
那就用,例如

 [self switchToController:controllerOne];

我在iPad应用程序中也遇到过这个要求

我找到的解决方案是为对象创建专门的视图控制器 处理与这些视图相关的业务逻辑的每种视图样式 (即,与每一段相关),并根据需要以编程方式添加/删除它们 响应所选段的“管理”控制器的子视图 索引更改

为此,必须创建一个额外的UIViewController子类来管理 UISegmentedControl更改,并添加/删除子视图

下面的代码完成了所有这一切,同时还考虑了一些注意事项/额外事项:

  • ViewWillAspect/ViewWillEnglishe/etc不在子视图上调用 自动,并需要通过“管理”控制器告知
  • viewwillappease/viewwilldiscover/etc,在“管理”时不调用 控制器,当它位于导航控制器内时 导航控制器委托
  • 如果您想从导航堆栈中推送到导航堆栈上 在段的子视图中,您需要调用“管理”视图 这样做,因为子视图是在 导航层次结构,并且没有对导航的引用 控制器
  • 如果在导航控制器场景中使用,则返回按钮为 自动设置为段的名称
接口:

@interface SegmentManagingViewController : UIViewController <UINavigationControllerDelegate> {
    UISegmentedControl    * segmentedControl;
    UIViewController      * activeViewController;
    NSArray               * segmentedViewControllers;
}

@property (nonatomic, retain) IBOutlet UISegmentedControl * segmentedControl;
@property (nonatomic, retain) UIViewController            * activeViewController;
@property (nonatomic, retain) NSArray                     * segmentedViewControllers;

@end

希望这有帮助。

这里有一个很好的教程,可以进一步解释这个概念:


github的位置:

只是为了澄清。。。您的意思是要在IB中为每个子视图创建一个单独的UIViewController.h、.m和.xib文件,在“包含”视图的ViewDiLoad中实例化其中一个,在IB中向包含视图添加一个UIView,然后执行“向上投票”操作!在-didChangeSegmentedControl:方法中存在一个小内存泄漏。最后一条语句应该是:self.navigationItem.backBarButtonItem=[[[UIBarButtonItem alloc]initWithTitle:segmentTitle样式:UIBarbuttoneMStylePlain目标:nil操作:nil]autorelease];viewDidLoad中也存在类似的内存泄漏:self.navigationItem.titleView=self.segmentedControl=[[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@“Seg 1”、@“Seg 2”、@“Seg 3”、nil]]autorelease];添加一个链接,指向我发布的关于此模式的进一步更新-使用UINavigationController而不是“容器”视图控制器。由于某种原因,当我在iPad上使用此功能时,细节部分的大小无法正确调整,就好像视图是在完整的iPad肖像中绘制的。@Convolution您是否设法解决了此问题。在iPhone上实现这一点时,我遇到了类似的问题。第一个选定的段视图的大小调整正确,其他所有的都没有。@bencallis抱歉,这件事发生在很久以前,我完全忘记了我是如何解决这个问题的
@interface SegmentManagingViewController : UIViewController <UINavigationControllerDelegate> {
    UISegmentedControl    * segmentedControl;
    UIViewController      * activeViewController;
    NSArray               * segmentedViewControllers;
}

@property (nonatomic, retain) IBOutlet UISegmentedControl * segmentedControl;
@property (nonatomic, retain) UIViewController            * activeViewController;
@property (nonatomic, retain) NSArray                     * segmentedViewControllers;

@end
@interface SegmentManagingViewController ()
- (void)didChangeSegmentControl:(UISegmentedControl *)control;
@end

@implementation SegmentManagingViewController

@synthesize segmentedControl, activeViewController, segmentedViewControllers;

- (void)viewDidLoad {
    [super viewDidLoad];

    UIViewController * controller1 = [[MyViewController1 alloc] initWithParentViewController:self];
    UIViewController * controller2 = [[MyViewController2 alloc] initWithParentViewController:self];
    UIViewController * controller3 = [[MyViewController3 alloc] initWithParentViewController:self];

    self.segmentedViewControllers = [NSArray arrayWithObjects:controller1, controller2, controller3, nil];
    [controller1 release];
    [controller2 release];
    [controller3 release];

    self.navigationItem.titleView = self.segmentedControl =
    [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Seg 1", @"Seg 2", @"Seg 3", nil]];
    self.segmentedControl.selectedSegmentIndex = 0;
    self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;

    [self.segmentedControl addTarget:self action:@selector(didChangeSegmentControl:) forControlEvents:UIControlEventValueChanged];

    [self didChangeSegmentControl:self.segmentedControl]; // kick everything off
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.activeViewController viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self.activeViewController viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.activeViewController viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self.activeViewController viewDidDisappear:animated];
}

#pragma mark -
#pragma mark UINavigationControllerDelegate control

// Required to ensure we call viewDidAppear/viewWillAppear on ourselves (and the active view controller)
// inside of a navigation stack, since viewDidAppear/willAppear insn't invoked automatically. Without this
// selected table views don't know when to de-highlight the selected row.

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewDidAppear:animated];
}

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewWillAppear:animated];
}

#pragma mark -
#pragma mark Segment control

- (void)didChangeSegmentControl:(UISegmentedControl *)control {
    if (self.activeViewController) {
        [self.activeViewController viewWillDisappear:NO];
        [self.activeViewController.view removeFromSuperview];
        [self.activeViewController viewDidDisappear:NO];
    }

    self.activeViewController = [self.segmentedViewControllers objectAtIndex:control.selectedSegmentIndex];

    [self.activeViewController viewWillAppear:NO];
    [self.view addSubview:self.activeViewController.view];
    [self.activeViewController viewDidAppear:NO];

    NSString * segmentTitle = [control titleForSegmentAtIndex:control.selectedSegmentIndex];
    self.navigationItem.backBarButtonItem  = [[UIBarButtonItem alloc] initWithTitle:segmentTitle style:UIBarButtonItemStylePlain target:nil action:nil];
}

#pragma mark -
#pragma mark Memory management

- (void)dealloc {
    self.segmentedControl = nil;
    self.segmentedViewControllers = nil;
    self.activeViewController = nil;
    [super dealloc];
}

@end