Передовая практика UISegmentedControl
Я пытаюсь разработать "лучший" способ использовать UISegmentedControl
для приложения iPhone. Я прочитал несколько сообщений здесь, в stackoverflow, и увидел несколько идей, но я не могу найти лучший способ сделать это. Сообщения, на которые я имею в виду:
Изменение просмотров из UISegmentedControl
а также
Как использовать UISegmentedControl для переключения представлений?
Похоже, что варианты:
- Добавьте каждый вид в IB и выложите их поверх друг друга, затем покажите/скройте их.
- Создайте каждый из подзонов отдельно в IB, затем создайте контейнер в главном представлении, чтобы заполнить подзаголовок, который вам нужен.
- Настройте один действительно высокий или очень широкий
UIView
и оживите его влево/вправо или вверх/вниз в зависимости от выбранного сегмента
- Используйте
UITabBarController
для замены подзонов - кажется глупым
- Для таблиц перезагрузите таблицу и
cellForRowAtIndex
и заполните таблицу из разных источников или разделов данных на основе выбранной опции сегмента (не для моего приложения).
Итак, какой подход лучше всего подходит для подзонов/не-табличных подходов? Что проще всего реализовать? Не могли бы вы поделиться некоторым примером кода с подходом?
Спасибо!
Ответы
Ответ 1
Я бы воспользовался вторым вариантом, который вы упомянули, создав подпрограммы в IB и заменив их в главном представлении. Это была бы хорошая возможность использовать UIViewController
, unsubclassed: в вашей начальной настройке создайте контроллер с помощью -initWithNibName:bundle:
(где первым параметром является имя NIB, содержащее отдельный поднаблюдение, а второй параметр nil
) и добавьте его view
в качестве подсмотра вашего основного вида по мере необходимости. Это поможет снизить отставание в памяти: поведение по умолчанию UIViewController
при получении предупреждения о памяти заключается в том, чтобы выпустить его представление, если оно не имеет супервизора. Пока вы удаляете скрытые представления из иерархии представлений, вы можете держать контроллеры в памяти и не беспокоиться о том, чтобы отпустить что-либо.
(отредактирован в ответ на комментарий:)
Вам не нужно подклассом UIViewController
, но для каждого представления вам нужны отдельные XIB. Вам также не нужно добавлять что-либо к содержащему виду в IB.
Переменные экземпляра в интерфейсе любого класса обрабатывают все это:
UIViewController *controllerOne;
UIViewController *controllerTwo;
UIViewController *currentController;
IBOutlet UIView *theContainerView;
В вашей настройке (-applicationDidFinishLaunching:
или что-то еще)
controllerOne = [[UIViewController alloc] initWithNibName:@"MyFirstView" bundle:nil];
controllerTwo = [[UIViewController alloc] initWithNibName:@"MySecondView" bundle:nil];
Чтобы переключиться на контроллер:
- (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];
Ответ 2
Я столкнулся с этим требованием и в iPad-приложении.
Решением, к которому я пришел, было создание специализированных контроллеров представлений для
каждый стиль представления для обработки бизнес-логики, относящейся к этим представлениям
(т.е. относящихся к каждому сегменту) и программно добавлять/удалять их как
subviews для "управляющего" контроллера в ответ на выбранный сегмент
изменения индекса.
Для этого нужно создать дополнительный подкласс UIViewController, который управляет
UISegmentedControl изменяет и добавляет/удаляет subviews.
Приведенный ниже код делает это, также заботясь о нескольких предостережениях/дополнениях:
- viewWillAppear/viewWillDisappear/etc, не вызываются в подзаголовках
автоматически, и вам нужно сообщить через контроллер управления
- viewWillAppear/viewWillDisappear/и т.д. не вызываются при управлении,
контроллер, когда он находится в контроллере навигации,
делегат диспетчера навигации
- Если вы хотите нажать на стек навигации изнутри
сегментный просмотр, вам нужно вернуться к представлению "управление"
сделать это, поскольку подвью было создано вне
навигационной иерархии и не будет иметь ссылки на навигацию
контроллер.
- Если используется в сценарии контроллера навигации, кнопка "Назад"
автоматически устанавливается на имя сегмента.
Интерфейс:
@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
Надеюсь, что это поможет.
Ответ 3
Вот отличный учебник, который далее объясняет эту концепцию: http://redartisan.com/2010/5/26/uisegmented-control-view-switching
и местоположение github: https://github.com/crafterm/SegmentedControlExample.git