ios-05_1-uikit
DESCRIPTION
Noveo iOS school. Lecture 5.TRANSCRIPT
iOS Internship 2014UIKit (part I)
UIKitframework
лекция 5
UIApplication, UIWindow UIView, UILabel, UIButton
UIViewControllerUINavigationController
Interface Builderautolayouts
interface orientationsview animations
UIKit Framework
● Всё что видит пользователь:○ текст○ кнопки○ картинки○ списки○ …
● Обработка действий пользователя:○ нажатия○ жесты○ набор текста○ сворачивание/разворачивание приложения○ …
● Абстракции для работы с перечисленным○ цвет, шрифт, …○ устройство, экран, окно○ NIB, layouts, …○ …
UIKit
UIKit Framework
● Объект-синглтон [UIApplication sharedApplication]
● Владеет окном
● Управляет статус-баром
● Управляет работой приложения в background-режиме
● Рассылает уведомления о смене состояния приложения
● Осуществляет переход в другие приложение (открывает URL)
● Имеет делегата
UIApplication
UIKit Framework
UIApplication *app = [UIApplication sharedApplication];
//...
[app setStatusBarHidden:YES withAnimation:UIStatusBarAnimationFade];
//...
NSURL *url = [NSURL URLWithString:@"http://google.com"];if ([app canOpenURL:url]) {
[app openURL:url];}
UIApplication
UIKit Framework
● Фактически в каждом приложении есть класс отвечающий этому протоколу
● Фактически это место, с которого начинается исполнение прикладного кода
● Обрабатывает события жизненного цикла приложения:
○ запуск
○ сворачивание/разворачивание
○ переход в активное/неактивное состояние (например звонок)
○ переход в background-режим (приложение свёрнуто, но наш код выполняется)
○ завершение работы приложения
● Получает локальные и push-уведомления
UIApplicationDelegate
UIKit Framework
UIApplicationDelegate@interface AppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *window;@end @implementation AppDelegate- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
CGRect windowFrame = [UIScreen mainScreen].bounds;self.window = [[UIWindow alloc] initWithFrame:windowFrame];
ViewController *viewController = [[ViewController alloc] init];self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];return YES;
}@end
UIKit Framework
Один экран*:[UIScreen mainScreen]
Одно окно*:[[UIApplication sharedApplication].delegate window]
* на самом деле — не совсем…
UIScreen, UIWindow
UIKit Framework
● Базовый класс для всего, что видит пользователь
● Сама по себе UIView — просто прямоугольник
● Умеет отрисовывать себя и перехватывать события внутри прямоугольника
● Объекты UIView (и классов-наследников) выстраиваются в дерево:
○ UIView содержит 0 или несколько вложенных объектов — subview
○ UIView имеет 0 или 1 объект-контейнер — superview
● UIView верхнего уровня лежит в окне (UIWindow)
UIView
UIKit Framework
UIViewUIView *greenView = [[UIView alloc] init];
greenView.frame = (CGRect) {200, 100, 60, 40};
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
UIView *redView = [[UIView alloc] init];
redView.frame = self.view.bounds;
redView.backgroundColor = [UIColor redColor];
[self.view insertSubview:redView atIndex:0];
UIKit Framework
UIView *greenView = [[UIView alloc] init];
greenView.frame = (CGRect) {200, 100, 60, 40};
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
UIView *redView = [[UIView alloc] init];
redView.frame = self.view.bounds;
redView.backgroundColor = [UIColor redColor];
[self.view insertSubview:redView atIndex:0];
UIViewx
y
0, 0
60x40200
100
UIKit Framework
UIView *greenView = [[UIView alloc] init];
greenView.frame = (CGRect) {200, 100, 60, 40};
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
UIView *redView = [[UIView alloc] init];
redView.frame = self.view.bounds;
redView.backgroundColor = [UIColor redColor];
[self.view insertSubview:redView atIndex:0];
UIViewx
y
0, 0
60x40200
100
UIKit Framework
?
UIView *greenView = [[UIView alloc] init];
greenView.frame = (CGRect) {200, 100, 60, 40};
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
UIView *redView = [[UIView alloc] init];
redView.frame = greenView.bounds;
redView.backgroundColor = [UIColor redColor];
[self.view insertSubview:redView atIndex:0];
UIViewx
y
0, 0
60x40200
100
UIKit Framework
UIView *greenView = [[UIView alloc] init];
greenView.frame = (CGRect) {200, 100, 60, 40};
greenView.backgroundColor = [UIColor greenColor];
[self.view addSubview:greenView];
UIView *redView = [[UIView alloc] init];
redView.frame = greenView.bounds; //{0, 0, 60, 40}
redView.backgroundColor = [UIColor redColor];
[self.view insertSubview:redView atIndex:0];
UIViewx
y
0, 0
60x40200
10060x40
UIKit Framework
UIView *view = [[UIView alloc] initWithFrame:self.view.bounds];view.hidden = NO;view.alpha = 0.8;view.backgroundColor = [UIColor redColor];view.userInteractionEnabled = YES;view.tag = 42;
//...
for (UIView *subview in view.subviews) {//...
}UIView *superview = view.superview;
UIView
UIKit Framework
UILabel *label = [[UILabel alloc] init];label.frame = (CGRect) {0, 0, self.view.bounds.size.width, 30};label.font = [UIFont systemFontOfSize:20];label.backgroundColor = [UIColor clearColor];label.textColor = [UIColor blackColor];label.textAlignment = NSTextAlignmentLeft;label.numberOfLines = 1;label.adjustsFontSizeToFitWidth = YES;label.minimumScaleFactor = 0.8;[self.view addSubview:label];
label.text = @"Hello, world!";
UILabel
UIKit Framework
UIImage — картинка в памяти● загружается из файла / ресурсов / бинарных данных в памяти● сохраняется в JPG и PNG● поддерживает растягивание фонов / рамок (аналог 9-patch)● можно получить размер, ориентацию● автоматически выбирает retina / non-retina версию ресурса (@2x)UIImageView — картинка на экране● показывает UIImage● масштабирует до нужного размера (кадрирует / добавляет поля /
растягивает / сжимает)● поддерживает циклическую анимацию
UIImage, UIImageView
UIKit Framework
UIImage *image = [UIImage imageNamed:@"my_image.png"];UIImageView *imageView = [[UIImageView alloc] initWithImage:image];imageView.frame = self.view.bounds;imageView.contentMode = UIViewContentModeScaleAspectFit;[self.view addSubview:imageView];
//...
UIImage *image_2 = [UIImage imageNamed:@"my_image_2.png"];imageView.image = image_2;
UIImage, UIImageView
UIKit Framework
UIImage *buttonBGImageN = [UIImage imageNamed:@"button.png"];UIImage *buttonBGImageS = [UIImage imageNamed:@"button_pressed.png"];
UIButton *button = [[UIButton alloc] init];button.frame = (CGRect) {0, 0, 120, 40};button.backgroundColor = [UIColor lightGrayColor];[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];[button setTitle:@"Tap me!" forState:UIControlStateNormal];[button setBackgroundImage:buttonBGImageN forState:UIControlStateNormal];[button setBackgroundImage:buttonBGImageS forState:UIControlStateSelected];
[self.view addSubview:button];
UIButton как UIView
UIKit Framework
{UIButton *button = /*...*/;//...[button addTarget:self
action:@selector(buttonTap:) forControlEvents:UIControlEventTouchUpInside];} - (void)buttonTap:(UIButton *)sender{
//...}
UIButton как UIControl
UIKit Framework
[x addTarget:target action:action forControlEvents:events];
UIButton *x
[
<target, action, events>,
<target, action, events>,
<target, action, events>,
...
]
UIControl
UIKit Framework
self.label = [[UILabel alloc] initWithFrame:labelFrame];[self.view addSubview:self.label];
self.input = [[UITextField alloc] initWithFrame:inputFrame];[self.view addSubview:self.input];[self.input addTarget:self action:@selector(textChanged:) forControlEvents:UIControlEventEditingChanged]; //...
- (void)textChanged:(UITextField *)sender{
self.label.text = sender.text;}
UITextField
UIKit Framework
UIView — логическая организация элементов, прямоугольники, полоски
UILabel — вывод текста
UITextField, UITextView — редактирование текста
UIWebView — показ HTML
UIImageView — показ картинок
UIButton — кнопка
UISwitch, UISlider, UIStepper — выключатель, регулятор, ступенчатый регулятор
UIToolbar, UITabBar, UINavigationBar — панели
UIActivityIndicatorView — спиннер
UITableView, UITableViewCell — список
UICollectionView, UICollectionViewCell — коллекция
UIScrollView — область прокрутки
UIPickerView — выбор варианта
UIView
UIKit Framework
Прозрачный: [UIColor clearColor]
RGB: [UIColor colorWithRed:r/255.0f
green:g/255.0f
blue:b/255.0f
alpha:a/255.0f]
HSV: [UIColor colorWithHue:h/255.0f
saturation:s/255.0f
brightness:v/255.0f
alpha:a/255.0f]
BW: [UIColor colorWithWhite:w/255.0f
alpha:a/255.0f]
UIColor
UIKit Framework
Список семейств шрифтов: [UIFont familyNames]
● Courier● Georgia● Helvetica● Helvetica Neue● Verdana● ...
Список вариантов начертаний: [UIFont fontNamesForFamilyName:@"Helvetica"]
● Helvetica-Oblique● Helvetica-Light● Helvetica-Bold● Helvetica● Helvetica-BoldOblique● Helvetica-LightOblique
Шрифт по имени: [UIFont fontWithName:@"Helvetica-Bold" size:20]
Стандартный шрифт: [UIFont systemFontOfSize:[UIFont systemFontSize]]
UIFont
UIKit Framework
MVC… WTF?
UIViewController
UIKit Framework
● Связывает модель с представлением.
● Управляет жизненным циклом View.
● Обрабатывает события (действия пользователя).
● Обеспечивает логическую организацию функционала(например разбивка по экранам).
● Свойство view — верхнеуровневая UIView конроллера.
● Основной способ использования UIViewController — наследование. Поведение задаём в переопределённых методах.
UIViewController
UIKit Framework
– initWithNibName:bundle:
– viewDidLoad
– viewWillAppear:
– viewDidAppear:
– viewWillDisappear:
– viewDidDisappear:
– viewWillLayoutSubviews
– viewDidLayoutSubviews
UIViewController– preferredStatusBarStyle
– prefersStatusBarHidden
– shouldAutorotate
– supportedInterfaceOrientations
...
UIKit Framework
– initWithNibName:bundle: — designated initializer
– viewDidLoad — self.view загружена
– viewWillAppear: — перед началом анимации перехода на контроллер
– viewDidAppear: — после завершения анимации перехода на контроллер
– viewWillDisappear: — перед началом анимации перехода с контроллера
– viewDidDisappear: — после завершения анимации перехода с контроллера
– viewDidLayoutSubviews — после (потенциального) изменения лейаута self.view
UIViewController
UIKit Framework
UIViewController
@interface DashboardVC()@property (strong, nonatomic) UILabel *speedLabel;@end @implementation DashboardVC- (void)viewDidLoad{
[super viewDidLoad];self.speedLabel = [[UILabel alloc] initWithFrame:self.view.bounds];[self.view addSubview:self.speedLabel];self.speedLabel.text = stringFromSpeedValue(self.speed);
} -(void)setSpeed:(float)speed{
_speed = speed;self.speedLabel.text = stringFromSpeedValue(self.speed);
}
@interface DashboardVC : UIViewController@property (assign, nonatomic) float speed;@end
DashboardVC.h
DashboardVC.m
UIKit Framework
UIViewController@interface AppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *window;@end @implementation AppDelegate
- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
DashboardVC *dashboardVC = [[DashboardVC alloc] init];
self.window.rootViewController = dashboardVC;[self.window makeKeyAndVisible];
return YES;}@end
UIKit Framework
UINavigationController"back" button
navigation bar
push
pop
VC 1 VC 2
UIKit Framework
UINavigationController@interface AppDelegate : UIResponder <UIApplicationDelegate>@property (strong, nonatomic) UIWindow *window;@end @implementation AppDelegate- (BOOL)application:(UIApplication *)applicationdidFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
DashboardVC *dashboardVC = [[DashboardVC alloc] init];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:dashboardVC];
self.window.rootViewController = nc;[self.window makeKeyAndVisible];
return YES;}@end
UIKit Framework
@interface DashboardVC()//...@property (strong, nonatomic) UIButton *settingsButton;@end @implementation DashboardVC- (void)viewDidLoad{
[super viewDidLoad];//...self.settingsButton = [[UIButton alloc] initWithFrame:(CGRect){40, 40, 40, 40}];self.settingsButton.backgroundColor = [UIColor blueColor];[self.view addSubview:self.settingsButton];[self.settingsButton addTarget:self action:@selector(settingsButtonTap:) forControlEvents:UIControlEventTouchUpInside];
} -(void)settingsButtonTap:(UIButton *)sender{
SettingsVC *settingsVC = [[SettingsVC alloc] init];[self.navigationController pushViewController:settingsVC animated:YES];
}@end
UINavigationController
UIKit Framework
@implementation DashboardVC //... - (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[UIView animateWithDuration:0.3 animations:^{self.settingsButton.alpha = 1;
}];} - (void)buttonTap:(UIButton *)sender{
[UIView animateWithDuration:0.3 animations:^{self.settingsButton.alpha = 0;
} completion:^(BOOL finished) {self.settingsButton.hidden = YES;self.settingsButton.userInteractionEnabled = NO;
}];} @end
UIView animation
UIKit Framework
Interface orientations@implementation DashboardVC//... - (BOOL)shouldAutorotate{
return YES;} - (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;} - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;} @end
UIKit Framework
● Autoresizing masks vs. Autolayouts
● Interface Builder
Далее
UIKit Framework
Layout● iPhone + iPad● portrait + landscape● динамический размер контента● ...
UIKit Framework
Layout● Springs & struts (using UIViewAutoresizing)
○ Легко освоить○ Удобно задавать и в IB и из кода○ Легко анимаировать○ Легко кастомизировать○ Не помогает при динамическом контенте
● Autolayout (using NSLayoutConstraint)○ Сложно освоить○ Неудобный редактор в IB и муторно задавать из кода○ Помогает при динамическом контенте○ Медленно работает
UIKit Framework
Manual layoutx
y
@property (nonatomic, strong) UILabel *myLabel; //... - (void)viewDidLoad{
[super viewDidLoad];self.myLabel = [[UILabel alloc] init];[self.view addSubview:self.myLabel];//...
} - (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];self.myLabel.frame = CGRectInset(self.view.bounds, 40, 40);
}
20.0, 20.0
280 x 440
UIKit Framework
Spring & strutsx
y
20.0, 20.0@property (nonatomic, strong) UILabel *myLabel; //... - (void)viewDidLoad{
[super viewDidLoad];
self.myLabel = [[UILabel alloc] init];[self.view addSubview:self.myLabel];self.myLabel.frame = CGRectInset(self.view.bounds, 40, 40);self.myLabel.autoresizingMask =
UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
}
UIKit Framework
- (void)viewDidLoad{
[super viewDidLoad];
self.myLabel = [[UILabel alloc] init];[self.view addSubview:self.myLabel];self.myLabel.translatesAutoresizingMaskIntoConstraints = NO;UIView *label = self.myLabel;UIView *superview = self.view;NSDictionary *views = NSDictionaryOfVariableBindings(superview, label);
[superview addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-20-[label]-20-|"options:0metrics:nilviews:views]];
[superview addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-20-[label]-20-|"options:0metrics:nilviews:views]];
}
Autolayoutx
y
20.0
20.0 20.0
20.0
UIKit Framework
● XIB○ визуальное описание иерархии и свойств view
● Storyboard○ XIB + ...
○ несколько экранов в одном файле
○ можно описать переходы между экранами
○ таблицу можно описать вместе с ячейками
Interface Builder
UIKit Framework
● XIBMyVC *myVC =
[[UIViewController alloc]initWithNibName:@"MyVC" bundle:[NSBundle mainBundle]];
● StoryboardUIStoryboard *myStoryboard =
[UIStoryboard toryboardWithName:@"MySB" bundle:[NSBundle mainBundle]];MyVC *myVC =
[myStoryboard instantiateViewControllerWithIdentifier:@"MyVC"];
Interface Builder
UIKit Framework
@interface MyVC ()@property (strong, nonatomic) IBOutlet UIButton *myButton;@property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *myLabels;@end
@implementation MyVC
- (IBAction)myButtonTap:(UIButton *)sender{
for (UILabel *label in self.myLabels) { label.text = nil;
}}
@end
Interface Builder