2010-02-05 3 views
1

Без использования конструкторов интерфейса или xib-файлов, каков правильный способ создания экземпляров двух классов, которые наследуют UIView, чтобы они могли переключаться между собой с помощью UIButtons, расположенных на самих представлениях?Как создавать и вызывать подклассы UIView без использования Nib

Я думаю, что это включает в себя создание UIViewController из приложения делегата и добавив два экземпляра моих классов, которые реализуют UIView в контроллер (возможно, внутри контроллера?)

Я также не знаю, как поднять события из UIButtons в пользовательских UIViews для переключения представлений. Я подозреваю, что мне нужно будет добавить метод к контроллеру представления, но я не уверен, как получить ссылку на контроллер вида из области моего UIView.

Кроме того, мне интересно, если использование UIViewController необходимо, должен ли метод switch находиться в области основного делегата приложения?

Некоторые примеры кода были бы замечательными!

ответ

4

Если вы хотите сделать это в коде, вот пример, который я просто использовал, используя ленивые элементы пользовательского интерфейса. Я делаю только одну кнопку и меняю ее между тем, какой вид активен. Это немного неудобно, но это уменьшает количество кода, необходимого для демонстрации этого.

Я создал два UIViews для представления ваших пользовательских классов, один с синим фоном и один с красным. Кнопка меняет местами между ними. Если у вас есть уникальная кнопка уже в каждом из ваших пользовательских представлений, вам просто нужно либо выставить эти кнопки в качестве свойств ваших подклассов UIView, чтобы ваш контроллер просмотра мог получить к ним доступ, либо добавить контроллер вида в качестве цели для действия кнопки изнутри ваш код загрузки UIView.

Я тестировал этот код в своем симуляторе, и, похоже, он работает нормально, но вы действительно должны попытаться понять, что здесь происходит, чтобы вы могли реализовать его самостоятельно.

ToggleViewController.h:

#import <UIKit/UIKit.h> 
@interface ToggleViewController : UIViewController { 
    UIView *firstView; 
    UIView *secondView; 
    UIButton *button; 
} 
- (void)addButton; 
- (void)toggleViews; 
@property (nonatomic, readonly) UIView* firstView; 
@property (nonatomic, readonly) UIView* secondView; 
@property (nonatomic, readonly) UIButton* button; 
@end 

ToggleViewController.m:

#import "ToggleViewController.h" 
@implementation ToggleViewController 

// assign view to view controller 
- (void)loadView { 
    self.view = self.firstView; 
} 

// make sure button is added when view is shown 
- (void)viewWillAppear:(BOOL)animated { 
    [self addButton]; 

} 

// add the button to the center of the view 
- (void)addButton { 
    [self.view addSubview:self.button]; 
    button.frame = CGRectMake(0,0,150,44); 
    button.center = self.view.center; 
} 

// to toggle views, remove button from old view, swap views, then add button again 
- (void)toggleViews { 
    [self.button removeFromSuperview]; 
    self.view = (self.view == self.firstView) ? self.secondView : self.firstView; 
    [self addButton]; 
} 

// generate first view on access 
- (UIView *)firstView { 
    if (firstView == nil) { 
     firstView = [[UIView alloc] initWithFrame:CGRectZero]; 
     firstView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
     firstView.backgroundColor = [UIColor redColor]; 
    } 
    return firstView; 
} 

// generate second view on access 
- (UIView *)secondView { 
    if (secondView == nil) { 
     secondView = [[UIView alloc] initWithFrame:CGRectZero]; 
     secondView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
     secondView.backgroundColor = [UIColor blueColor]; 
    } 
    return secondView; 
} 

// generate button on access 
- (UIButton *)button { 
    if (button == nil) { 

     // create button 
     button = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain]; 

     // set title 
     [button setTitle:@"Toggle Views" 
       forState:UIControlStateNormal]; 

     // set self as a target for the "touch up inside" event of the button 
     [button addTarget:self 
        action:@selector(toggleViews) 
     forControlEvents:UIControlEventTouchUpInside]; 
    } 
    return button; 
} 

// clean up 
- (void)dealloc { 
    [button release]; 
    [secondView release]; 
    [firstView release]; 
    [super dealloc]; 
} 

@end 
+0

@ Victorb благодарит, что это замечательный материал. Кстати, мне пришлось использовать initWithFrame: [[UIScreen mainScreen] applicationFrame] мой метод firstView вместо CGRectZero, чтобы заставить его работать в симуляторе любые идеи, почему? – PeanutPower

+0

В моем тесте я добавлял VC к контроллеру панели таблеток, чтобы рамка уже была установлена. Я предполагаю, что любой контейнер, который вы использовали, не имел нужного набора кадров. Кадр CGRectZero должен быть изменен супервизором, когда он отображает свои подпункты, так как установлен параметр autoresizingMask. Но если у вас есть кадр, который будет работать, идите с ним. – VictorB

-2

Использование интерфейса Builder. Это по какой-то причине.

+4

Чтобы быть справедливым, есть много причин, чтобы избежать создания интерфейса. Я сам никогда не использую его, если могу помочь, и знаю других разработчиков, которые чувствуют то же самое. Есть кое-что, что можно сказать о том, что все поведение вашего приложения в коде как для разработки, так и для отладки. – VictorB

7

Ваша главная проблема заключается в том, что вы не концептуально понять роль UIViewControllers против UIViews. Большинство людей не делают, когда они впервые начинают.

Виды глупые и в идеале, они должны состоять из общих объектов. Они практически не содержат логики интерфейса. Они не знают и не заботятся о существовании других взглядов. Единственная логика, которую вы ставите в представлениях, - это логика, которая относится к непосредственному и универсальному функционированию самого представления, независимо от отображаемых данных или состояния других частей приложения. Вам редко приходится подклассифицировать UIView. Вот почему представления могут быть полностью сконфигурированы в построителе интерфейса без какого-либо кода.

ViewControllers содержат логику интерфейса и подключают интерфейс к данным (но они не содержат или не логически манипулируют данными). Они являются «интеллектуальными» и очень настраиваемыми. ViewControllers действительно понимают место просмотра в контексте приложения. ViewControllers загружают и настраивают представления либо из nib, либо программно. Контроллеры viewControllers управляют, когда представления отображаются или скрыты, и какой порядок. Контроллеры view определяют, какие действия предпринимаются в ответ на события и какие данные отображаются там, где.

Пример кода примера VictorB показывает, как все это делается прагматично. Важно отметить, что viewController и view являются полностью отдельными объектами из двух полностью отдельных классов. Не существует перекрытия и не требуется подкласс UIView. Все настройки находятся в контроллере.

Все это из-за шаблона проектирования MVC. Он отделяет интерфейс от модели данных, делая их как модульными, так и независимыми друг от друга. Это упрощает проектирование, отладку и повторное использование каждого независимого модуля.

+0

@TechZen это означает, что я не должен подклассифицировать UIView и реализовать собственный код для рисования ядра? Представьте себе, например, сценарий шахматной доски и другое представление для экрана меню. Используется ли код рисования платы в UIViewController? – PeanutPower

+0

На самом деле рисование вида является частью представления и должно быть реализовано там. Решение о том, что делать, сколько рисовать и т. Д. Должно быть функцией контроллера вида, передающего данные из модели данных. В случае с шахматной игрой у вас может быть собственный метод рисования в представлении, чтобы обрабатывать фактическую панель, но куски и их размещение будут зависеть от контроллера представления и модели данных. Представления должны быть как минимальными, так и минимальными. Например, если у вас есть представление, которое нарисовало доску для игры в шахматы, вы сможете использовать ее в игре с шашками. – TechZen

Смежные вопросы