Пользуясь видом для выбора даты, можно задавать минимальную и максимальную даты, которые он способен отображать. Для этого сначала нужно переключить вид выбора даты в режим UIDatePickerModeDate, а потом с помощью свойств maximumDate и minimumDate откорректировать этот диапазон:
 
   – (void)viewDidLoad{
   [super viewDidLoad];
   self.myDatePicker = [[UIDatePicker alloc] init];
   self.myDatePicker.center = self.view.center;
   self.myDatePicker.datePickerMode = UIDatePickerModeDate;
   [self.view addSubview: self.myDatePicker];
 
   NSTimeInterval oneYearTime = 365 * 24 * 60 * 60;
   NSDate *todayDate = [NSDate date];
 
   NSDate *oneYearFromToday = [todayDate
   dateByAddingTimeInterval: oneYearTime];
 
   NSDate *twoYearsFromToday = [todayDate
   dateByAddingTimeInterval:2 * oneYearTime];
 
   self.myDatePicker.minimumDate = oneYearFromToday;
   self.myDatePicker.maximumDate = twoYearsFromToday;
   }
 
   Применяя два этих свойства, можно ограничить доступный пользователю диапазон выбора даты конкретными пределами, как показано на рис. 1.15. В приведенном образце кода мы позволяем пользователю задавать даты в диапазоне от года до двух лет, отсчитывая с настоящего момента.
 
 
   Рис. 1.15. Минимальная и максимальная даты при работе с видом выбора даты
   Если вы хотите применять вид выбора даты в качестве таймера обратного отсчета, нужно задать для этого вида режим UIDatePickerModeCountDownTimer и использовать свойство countDownDuration вида выбора даты для указания длительности обратного отсчета, задаваемой по умолчанию. Например, если вы желаете предложить пользователю такой таймер и задать в качестве периода ведения обратного отсчета 2 минуты, нужно написать следующий код:
 
   – (void)viewDidLoad{
   [super viewDidLoad];
   self.view.backgroundColor = [UIColor whiteColor];
   self.myDatePicker = [[UIDatePicker alloc] init];
   self.myDatePicker.center = self.view.center;
   self.myDatePicker.datePickerMode = UIDatePickerModeCountDownTimer;
   [self.view addSubview: self.myDatePicker];
   NSTimeInterval twoMinutes = 2 * 60;
   [self.myDatePicker setCountDownDuration: twoMinutes];
   }
 
   Результат показан на рис. 1.16.
 
   Рис. 1.16. Таймер обратного отсчета в виде для выбора даты, где стандартная длительность обратного отсчета равна 2 минутам

1.6. Реализация инструмента для выбора временных рамок с помощью UISlider

Постановка задачи

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

Решение

   Используйте класс UISlider.

Обсуждение

   Вероятно, вы уже знаете, что такое слайдер. Пример слайдера показан на рис. 1.17.
 
   Рис. 1.17. В нижней части экрана находится слайдер, регулирующий уровень громкости
 
   Чтобы создать слайдер, нужно инстанцировать объект типа UISlider. Создадим слайдер и поместим его на вид нашего контроллера. Начнем с файла реализации нашего контроллера вида:
 
   #import "ViewController.h"
 
   @interface ViewController ()
   @property (nonatomic, strong) UISlider *slider;
   @end
 
   @implementation ViewController
 
   …
 
   Теперь рассмотрим метод viewDidLoad и создадим сам компонент-слайдер. В этом коде мы будем создавать слайдер, позволяющий выбирать значения в диапазоне от 0 до 100. По умолчанию ползунок слайдера будет установлен в среднем значении шкалы:
 
   – (void)viewDidLoad{
   [super viewDidLoad];
 
   self.slider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,
   0.0f,
   200.0f,
   23.0f)];
   self.slider.center = self.view.center;
   self.slider.minimumValue = 0.0f;
   self.slider.maximumValue = 100.0f;
   self.slider.value = self.slider.maximumValue / 2.0;
   [self.view addSubview: self.slider];
   }
   Диапазон слайдера совершенно не зависит от его внешнего вида. С помощью указателя диапазона мы приказываем слайдеру вычислить его (слайдера) значение, основываясь на относительной позиции в рамках диапазона. Например, если для слайдера задан диапазон от 0 до 100, то когда ползунок слайдера расположен у левого края шкалы, свойство слайдера value равно 0, а если ползунок стоит у правого края, оно равно 100.
   Как будут выглядеть результаты? Теперь вы можете запустить приложение в эмуляторе (рис. 1.18).
 
   Рис. 1.18. Обычный слайдер в центре экрана
 
   Для получения желаемых результатов мы использовали несколько свойств слайдера. Что это за свойства?
   • minimumValue – задает минимальное значение диапазона, поддерживаемого слайдером.
   • maximumValue – задает максимальное значение диапазона, поддерживаемого слайдером.
   • value – текущее значение слайдера. Это свойство доступно как для чтения, так и для изменения, то есть вы можете как считывать это значение, так и записывать в него информацию. Если вы хотите, чтобы при перемещении ползунка в это значение включалась анимация, то можно вызвать метод слайдера setValue: animated: и передать YES в качестве значения параметра animated.
   Ползунок слайдера называется также бегунком. Если вы хотите получать событие всякий раз, когда передвигается ползунок слайдера, нужно добавить ваш объект, которому требуется информация о таких событиях, в качестве цели слайдера с помощью относящегося к слайдеру метода addTarget: action: forControlEvents::
 
   – (void) sliderValueChanged:(UISlider *)paramSender{
 
   if ([paramSender isEqual: self.mySlider]){
   NSLog(@"New value = %f", paramSender.value);
   }
 
   }
   – (void)viewDidLoad{
   [super viewDidLoad];
   self.view.backgroundColor = [UIColor whiteColor];
   self.mySlider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,
   0.0f,
   200.0f,
   23.0f)];
   self.slider.center = self.view.center;
   self.slider.minimumValue = 0.0f;
   self.slider.maximumValue = 100.0f;
   self.slider.value = self.slider.maximumValue / 2.0;
   [self.view addSubview: self.slider];
 
   [self.slider addTarget: self
   action:@selector(sliderValueChanged:)
   forControlEvents: UIControlEventValueChanged];
   }
 
   Если сейчас запустить приложение в эмуляторе, вы увидите, что вызывается целевой метод sliderValueChanged: и это происходит всякий раз, как только перемещается ползунок слайдера. Возможно, именно этого вы и хотели. Но в некоторых случаях уведомление требуется лишь тогда, когда пользователь отпустил ползунок, установив его в новом значении. Если вы хотите дождаться такого уведомления, установите для свойства слайдера continuous значение NO. Если это свойство имеет значение YES (задаваемое по умолчанию), то на цели слайдера вызов будет идти непрерывно все то время, пока движется ползунок.
   В SDK iOS разработчик также может изменять внешний вид слайдера. Например, ползунок может иметь нестандартный вид. Чтобы изменить внешний вид ползунка, просто пользуйтесь методом setThumbImage: forState: и передавайте нужное изображение, а также второй параметр, который может принимать одно из двух значений:
   • UIControlStateNormal – обычное состояние ползунка, когда его не трогает пользователь;
   • UIControlStateHighlighted – изображение, которое должно быть на месте ползунка, когда пользователь начинает его двигать.
 
   Я подготовил два изображения: одно для стандартного состояния ползунка, а другое – для активного (затронутого) состояния. Добавим их к слайдеру:
 
   [self.slider setThumbImage: [UIImage imageNamed:@"ThumbNormal.png"]
   forState: UIControlStateNormal];
   [self.slider setThumbImage: [UIImage imageNamed:@"ThumbHighlighted.png"]
   forState: UIControlStateHighlighted];
 
   Теперь взглянем, как выглядит в эмуляторе неактивный слайдер (рис. 1.19).
 
   Рис. 1.19. Слайдер со специально оформленным ползунком

1.7. Оформление UISlider

Постановка задачи

   Вы используете компонент графического интерфейса UISlider, оформленный по умолчанию, и хотите на свой вкус изменить его внешний вид.

Решение

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

Обсуждение

   Apple проделала огромную работу, предоставив нам в iOS SDK методы для оформления компонентов пользовательского интерфейса. В частности, оформление может быть связано с изменением оттенков различных частей компонента в интерфейсе. Схема, демонстрирующая компонентный состав пользовательского интерфейса, приведена на рис. 1.20.
 
   Рис. 1.20. Различные компоненты UISlider
 
   Для каждого из этих компонентов UISlider существуют метод и свойство, позволяющие изменять внешний вид слайдера. Простейшими из этих свойств являются те, которые позволяют изменять оттенок соответствующего компонента:
   • minimumTrackTintColor – это свойство задает оттенок для области минимальных значений;
   • thumbTintColor – это свойство, как понятно из его названия, задает цвет ползунка;
   • maximumTrackTintColor – это свойство задает оттенок для области максимальных значений.
   Все эти свойства относятся к типу UIColor.
   В следующем образце кода мы инстанцируем UISlider и помещаем его в центре вида, расположенного в нашем контроллере. Кроме того, здесь мы задаем цвет для области минимальных значений (красный), цвет ползунка (черный) и цвет области максимальных значений (зеленый):
 
   – (void)viewDidLoad{
   [super viewDidLoad];
 
   /* Создаем слайдер */
   self.slider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,
   0.0f,
   118.0f,
   23.0f)];
   self.slider.value = 0.5;
   self.slider.minimumValue = 0.0f;
   self.slider.maximumValue = 1.0f;
   self.slider.center = self.view.center;
   [self.view addSubview: self.slider];
 
   /* Задаем оттенок для области минимальных значений */
   self.slider.minimumTrackTintColor = [UIColor redColor];
 
   /* Задаем оттенок для ползунка */
   self.slider.maximumTrackTintColor = [UIColor greenColor];
 
   /* Задаем цвет для области максимальных значений */
   self.slider.thumbTintColor = [UIColor blackColor];
   }
 
   Если вы теперь запустите получившееся приложение, то увидите примерно такую картину, как на рис. 1.21.
 
   Рис. 1.21. Оттенки всех составных частей слайдера изменены
 
   Иногда вам может потребоваться более полный контроль над тем, как слайдер будет выглядеть на экране. При этом одних только оттенков может быть недостаточно. Именно поэтому Apple предлагает и другие способы изменения внешнего вида слайдера, позволяя вам задавать изображения для различных его компонентов. Речь идет о следующих изображениях.
   • Изображение для минимального значения. Это изображение, которое будет находиться за пределами слайдера у его левого края. По умолчанию такое изображение не предоставляется, поэтому вы его и не увидите, если просто создадите в виде новый слайдер. Вы можете задать такое изображение, чтобы подсказывать пользователю, как трактуется минимальное значение в контексте данного слайдера. Например, в приложении, с помощью которого пользователь может увеличивать или уменьшать яркость экрана, минимальному значению может соответствовать картинка в виде потухшей лампочки. Она показывает, что чем дальше пользователь будет перемещать ползунок в сторону минимального значения (влево), тем более тусклым будет становиться экран. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMinimumValueImage:. Это изображение должно иметь по 23 точки в высоту и в ширину. При работе с сетчатым дисплеем используйте такое же изображение, только вдвое крупнее.
   • Изображение для области минимальных значений. Это изображение, которое будет соответствовать колее слайдера левее от ползунка. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMinimumTrackImage: forState:. Это изображение должно иметь 11 точек в ширину и 9 точек в высоту и допускать изменение размера (подробнее о таких изображениях см. в разделе 17.5).
   • Изображение для ползунка. Изображение ползунка – это единственный движущийся элемент слайдера. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setThumbImage: forState:. Это изображение должно иметь 23 точки в высоту и 23 точки в ширину.
   • Изображение для области максимальных значений. Это изображение будет соответствовать той части колеи слайдера, которая находится справа от ползунка. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMaximumTrackImage: forState:. Это изображение должно иметь 11 точек в ширину и 9 точек в высоту и допускать изменение размера (подробнее о таких изображениях см. в разделе 17.5).
   • Изображение для максимального значения. Это изображение, которое будет находиться у правого края слайдера. Оно должно напоминать изображение, соответствующее минимальному значению, но, разумеется, трактуется противоположным образом. Вернувшись к примеру с яркостью лампочки, допустим, что справа от колеи с ползунком у нас изображена яркая лампочка, испускающая лучи. Так пользователю будет понятно, что чем дальше вправо он передвигает ползунок, тем ярче становится экран. Чтобы изменить это изображение, воспользуйтесь относящимся к слайдеру методом экземпляра setMaximumValueImage:. Это изображение должно иметь 23 точки в высоту и столько же в ширину.
   Изображения, предоставляемые вами для областей максимальных и минимальных значений, должны при необходимости изменять размер. Подробнее о таких изображениях рассказано в разделе 17.5.
   Для этого упражнения я создал пять уникальных изображений – по одному для каждого компонента слайдера. Убедился, что изображения для областей с максимальными и минимальными значениями поддерживают изменение размера. Оформляя этот слайдер по своему усмотрению, я стремлюсь создать у пользователя впечатление, что он меняет температуру в комнате: при перемещении ползунка влево становится прохладнее, вправо – теплее. Далее приведен код, создающий слайдер и оформляющий различные его компоненты:
 
   #import "ViewController.h"
 
   @interface ViewController ()
   @property (nonatomic, strong) UISlider *slider;
   @end
 
   @implementation ViewController
 
   /*
   Этот метод возвращает изображение переменного размера для области слайдера, содержащей минимальные значения
   */
   – (UIImage *) minimumTrackImage{
   UIImage *result = [UIImage imageNamed:@"MinimumTrack"];
   UIEdgeInsets edgeInsets;
   edgeInsets.left = 4.0f;
   edgeInsets.top = 0.0f;
   edgeInsets.right = 0.0f;
   edgeInsets.bottom = 0.0f;
   result = [result resizableImageWithCapInsets: edgeInsets];
   return result;
   }
 
   /*
   Аналогично предыдущему методу этот возвращает изображение переменного размера для области слайдера, содержащей максимальные значения
   */
   – (UIImage *) maximumTrackImage{
   UIImage *result = [UIImage imageNamed:@"MaximumTrack"];
   UIEdgeInsets edgeInsets;
   edgeInsets.left = 0.0f;
   edgeInsets.top = 0.0f;
   edgeInsets.right = 3.0f;
   edgeInsets.bottom = 0.0f;
   result = [result resizableImageWithCapInsets: edgeInsets];
   return result;
   }
 
   – (void)viewDidLoad{
   [super viewDidLoad];
 
   /* Создаем слайдер */
   self.slider = [[UISlider alloc] initWithFrame: CGRectMake(0.0f,
   0.0f,
   218.0f,
   23.0f)];
   self.slider.value = 0.5;
   self.slider.minimumValue = 0.0f;
   self.slider.maximumValue = 1.0f;
   self.slider.center = self.view.center;
   [self.view addSubview: self.slider];
 
   /* Изменяем изображение для минимального значения */
   [self.slider setMinimumValueImage: [UIImage imageNamed:@"MinimumValue"]];
 
   /* Изменяем изображение для области минимальных значений */
   [self.slider setMinimumTrackImage: [self minimumTrackImage]
   forState: UIControlStateNormal];
 
   /* Изменяем изображение ползунка для обоих возможных состояний ползунка: когда
   пользователь его касается и когда не касается */
   [self.slider setThumbImage: [UIImage imageNamed:@"Thumb"]
   forState: UIControlStateNormal];
   [self.slider setThumbImage: [UIImage imageNamed:@"Thumb"]
   forState: UIControlStateHighlighted];
 
   /* Изменяем изображение для области максимальных значений */
   [self.slider setMaximumTrackImage: [self maximumTrackImage]
   forState: UIControlStateNormal];
 
   /* Изменяем изображение, соответствующее максимальному значению */
   [self.slider setMaximumValueImage: [UIImage imageNamed:@"MaximumValue"]];
   }
   Ползунок в iOS 7 выглядит совершенно иначе, нежели в более ранних версиях. Как вы догадываетесь, этот элемент стал очень прямолинейным и тонким на вид. Высота максимальной и минимальной отметок на шкале в iOS 7 составляет всего 1 точку, поэтому задавать для этих элементов специальные изображения абсолютно бесполезно – скорее всего, получится некрасиво. Поэтому для оформления этих элементов UISlider в iOS 7 рекомендуется оперировать лишь оттенками, но не присваивать элементу никаких изображений.

См. также

   Раздел 1.6.

1.8. Группирование компактных параметров с помощью UISegmentedControl

Постановка задачи

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

Решение

   Используйте класс UISegmentedControl. Пример работы с этим классом показан на рис. 1.22.
 
   Рис. 1.22. Сегментированный элемент управления, в котором отображаются четыре параметра

Обсуждение

   Сегментированный элемент управления – это сущность, позволяющая отображать в компактном пользовательском интерфейсе наборы параметров, из которых пользователь может выбирать нужный. Чтобы отобразить сегментированный элемент управления, создайте экземпляр класса UISegmentedControl. Начинаем работу с файла реализации (.m) нашего контроллера вида:
 
   #import "ViewController.h"
 
   @interface ViewController ()
   @property (nonatomic, strong) UISegmentedControl *mySegmentedControl;
   @end
 
   @implementation ViewController
 
   …
   Создаем сегментированный элемент управления в методе viewDidLoad контроллера нашего вида:
   – (void)viewDidLoad{
   [super viewDidLoad];
   NSArray *segments = [[NSArray alloc] initWithObjects:
   @"iPhone",
   @"iPad",
   @"iPod",
   @"iMac", nil];
 
   self.mySegmentedControl = [[UISegmentedControl alloc]
   initWithItems: segments];
   self.mySegmentedControl.center = self.view.center;
   [self.view addSubview: self.mySegmentedControl];
 
   }
 
   Чтобы представить разные параметры, которые будут предлагаться на выбор в нашем сегментированном элементе управления, мы используем обычный массив строк. Такой элемент управления инициализируется с помощью метода initWithObjects:. Потом передаем сегментированному элементу управления массив строк и изображений. Результат будет как на рис. 1.22.
   Теперь пользователь может выбрать в сегментированном элементе управления один из параметров. Допустим, он выбирает iPad. Тогда пользовательский интерфейс сегментированного элемента управления изменится и покажет пользователю, какой параметр будет выбран. Получится такое изображение, как на рис. 1.23.
 
   Рис. 1.23. Пользователь выбрал один из вариантов в сегментированном элементе управления
 
   Возникает вопрос: как узнать, что пользователь выбрал в сегментированном элементе управления новый параметр? Ответ прост. Как и при работе с UISwitch или UISlider, применяется метод addTarget: action: forControlEvents: сегментированного элемента управления, к которому добавляется цель. Для параметра forControlEvents нужно задать значение UIControlEventValueChanged, так как именно это событие запускается, когда пользователь выбирает в сегментированном элементе управления новый параметр:
 
   – (void) segmentChanged:(UISegmentedControl *)paramSender{
   if ([paramSender isEqual: self.mySegmentedControl]){
   NSInteger selectedSegmentIndex = [paramSender selectedSegmentIndex];
 
   NSString *selectedSegmentText =
   [paramSender titleForSegmentAtIndex: selectedSegmentIndex];
   NSLog(@"Segment %ld with %@ text is selected",
   (long)selectedSegmentIndex,
   selectedSegmentText);
   }
   }
 
   – (void)viewDidLoad{
   [super viewDidLoad];
   NSArray *segments = [[NSArray alloc] initWithObjects:
   @"iPhone",
   @"iPad",
   @"iPod",
   @"iMac", nil];
 
   self.mySegmentedControl = [[UISegmentedControl alloc]
   initWithItems: segments];
   self.mySegmentedControl.center = self.view.center;
   [self.view addSubview: self.mySegmentedControl];
 
   [self.mySegmentedControl addTarget: self
   action:@selector(segmentChanged:)
   forControlEvents: UIControlEventValueChanged];
   }
 
   Если пользователь начинает выбирать слева и выбирает каждый параметр (см. рис. 1.22) до правого края, на консоль будет выведен следующий текст:
 
   Segment 0 with iPhone text is selected
   Segment 1 with iPad text is selected
   Segment 2 with iPod text is selected
   Segment 3 with iMac text is selected
 
   Как видите, мы использовали метод selectedSegmentIndex сегментированного элемента управления, чтобы найти индекс варианта, выбранного в настоящий момент. Если ни один из элементов не выбран, метод возвращает значение –1. Кроме того, мы использовали метод titleForSegmentAtIndex:. Просто передаем этому методу индекс параметра, выбранного в сегментированном элементе управления, а сегментированный элемент управления возвратит текст, соответствующий этому параметру. Ведь просто, правда?
   Как вы, вероятно, заметили, как только пользователь отмечает один из параметров в сегментированном элементе управления, этот параметр выбирается и остается выбранным, как показано на рис. 1.23. Если вы хотите, чтобы пользователь выбрал параметр, но кнопка этого параметра не оставалась нажатой, а возвращалась к исходной форме (так сказать, «отщелкивалась обратно», как и обычная кнопка), то нужно задать для свойства momentary сегментированного элемента управления значение YES:
 
   self.mySegmentedControl.momentary = YES;
 
   Одна из самых приятных особенностей сегментированных элементов управления заключается в том, что они могут содержать не только текст, но и изображения. Для этого нужно просто использовать метод-инициализатор initWithObjects: класса UISegmentedControl и передать с этим методом те строки и изображения, которые будут применяться при реализации соответствующего пользовательского интерфейса:
 
   – (void)viewDidLoad{
   [super viewDidLoad];
   NSArray *segments = [[NSArray alloc] initWithObjects:
   @"iPhone",
   [UIImage imageNamed:@"iPad"],
   @"iPod",
   @"iMac",
   ];
 
   self.mySegmentedControl = [[UISegmentedControl alloc]
   initWithItems: segments];
 
   CGRect segmentedFrame = self.mySegmentedControl.frame;
   segmentedFrame.size.height = 128.0f;
   segmentedFrame.size.width = 300.0f;
   self.mySegmentedControl.frame = segmentedFrame;
   self.mySegmentedControl.center = self.view.center;
 
   [self.view addSubview: self.mySegmentedControl];
   }
   В данном примере файл iPad.png – это просто миниатюрное изображение «айпада», добавленное в наш проект.
   В iOS 7 Apple отказалась от использования свойства segmentedControlStyle класса UISegmentedControl, поэтому теперь сегментированные элементы управления имеют всего один стиль, задаваемый по умолчанию. Мы больше не можем изменять этот стиль.

1.9. Представление видов и управление ими с помощью UIViewController

Постановка задачи

   Необходимо иметь возможность переключаться между видами в вашем приложении.

Решение

   Воспользуйтесь классом UIViewController.

Обсуждение

   Стратегия разработки для iOS, предложенная Apple, предполагает использование паттерна «модель – вид – контроллер» (MVC) и соответствующее разделение задач. Виды – это элементы, отображаемые для пользователя, а модель – это абстракция с данными, которыми управляет приложение. Контроллер – это перемычка, соединяющая модель и вид. Контроллер (в данном случае речь идет о контроллере вида) управляет отношениями между видом и моделью. Почему же этими отношениями не занимается вид? Ответ довольно прост: если бы мы возлагали эти задачи на вид, код вида становился бы очень запутанным. Кроме того, такой подход тесно связывал бы виды с моделью, что не очень хорошо.
   Контроллеры видов можно загружать из файлов XIB (для использования с конструктором интерфейсов) или просто создавать с помощью программирования. Сначала рассмотрим, как создать контроллер вида, не пользуясь файлом XIB.
   Контроллеры видов удобно создавать в Xcode. Теперь, когда вы уже создали шаблон приложения с помощью шаблона Empty Application (Пустое приложение), выполните следующие шаги, чтобы создать новый контроллер вида для вашего приложения.
   1. В Xcode перейдите в меню File (Файл) и там выберите New-New File (Новый– Новый файл).
   2. В диалоговом окне New File (Новый файл) убедитесь, что слева выбраны категория iOS и подкатегория Cocoa Touch. Когда сделаете это, выберите класс UIViewController в правой части диалогового окна, а затем нажмите Next (Далее) (рис. 1.24).
 
   Рис. 1.24. Подкласс нового контроллера вида
 
   3. На следующем экране убедитесь, что в текстовом поле Subclass (Подкласс) указано UIViewController, а также что сняты флажки Targeted for iPad (Разработка для iPad) и With XIB for user interface (Использовать файл XIB для пользовательского интерфейса). Именно такая ситуация показана на рис. 1.25. Нажмите Next (Далее).
 
   Рис. 1.25. Собственный контроллер вида, без использования класса XIB
 
   4. На следующем экране (Save as (Сохранить как)) назовите файл контроллера вида RootViewController и нажмите Save (Сохранить) (рис. 1.26).
 
   Рис. 1.26. Сохранение контроллера вида без использования файла XIB
 
   5. Теперь найдем файл реализации (.m) делегата приложения, который обычно называется AppDelegate.m. В этом файле объявим свойство типа ViewController:
 
   #import "AppDelegate.h"
   #import "ViewController.h"
 
   @interface AppDelegate ()
   @property (nonatomic, strong) ViewController *viewController;
   @end
 
   @implementation AppDelegate
 
   …
 
   6. Найдем в файле реализации метод application: didFinishLaunchingWithOptions:, относящийся к делегату приложения, инстанцируем контроллер вида и добавим его в наше окно как корневой контроллер вида:
 
   – (BOOL) application:(UIApplication *)application
   didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
 
   self.viewController = [[ViewController alloc] initWithNibName: nil
   bundle: nil];
 
   self.window = [[UIWindow alloc]
   initWithFrame: [[UIScreen mainScreen] bounds]];
 
   /* Делаем наш контроллер вида корневым контроллером вида */
   self.window.rootViewController = self.viewController;
 
   self.window.backgroundColor = [UIColor whiteColor];
   [self.window makeKeyAndVisible];
   return YES;
   }
 
   Теперь снова попробуем запустить приложение в эмуляторе. На экране увидим вид, имеющий ровный белый цвет. Поздравляю: вы только что создали контроллер вида, и теперь у вас есть доступ не только к контроллеру вида, но и к самому объекту этого вида.