Видео урок 36 посвящен описанию класса UIPopoverController.
Popover представляет собой всплывающее модальное окно со стрелочкой - якорем указывающим на элемент к которому относится Popover.
В новой версии xCode класс UIPopoverController уже deprecated (в IOS 9.0).
Поэтому подробно описывать урок смысла нет (т.к. UIPopoverController использовать уже не нельзя).
В сообщении об ошибке говорится, что теперь popover включен в презентации UIViewController. Используйте модальный стиль презентаций UIModalPresentationPopover и UIPopoverPresentationController.
Попробую домашнее задание реализовать с учетом нововведений в Xcode.
Нашел вот такой пример создания Popover в коде:
Домашнее задание
Ученик
1. Создайте универсальное приложение (айпад / айфон)
2. Первый контроллер должен быть статической таблицей с навигейшн баром
3. В правом углу на навигейшине должна быть кнопка инфо, если на нее нажать, то вылазит поповер с объяснением, что это такое за приложение :)
Студент
4. В таблице создайте классические ячейки:
имя + текстфилд
фамилия + текстфилд
пол + сегментед контрол (мужской/женский)
Дата рождения + текстфилд
Образование + текстфилд
5. с первыми тремя ячейками все понятно, а вот дальше самое интересное
Мастер
6. При нажатии на текст филд с датой рождения текст филду должно быть запрещено входить в режим редактирования, а вместо этого из него должен появиться поповер с UIDatePicker. При изменении даты, содержимое текст филда должно меняться (то есть мы не мучаем юзера форматами ввода, мы просто даем ему барабан с датами и предлагаем выбрать самому)
7. Подсказка. Вам надо сделать контроллер с дейт пикером, а дейт пикер это наследник от UIControl, то есть у него есть акшин valueChanged или типо того. У контроллера нужно создать проперти делегат, по которому мы будем отправлять данные, полученные с барабана. То есть по простому: контроллер следит за барабаном и отправляет изменения своему делегату. Не забудьте установить делегат перед создания поповера.
Супермен
8. Тоже самое сделать с образованием. Образование это список типа, неполное среднее, среднее, неполное высшее, высшее и тд, то есть если делать в сегментед контролах, то не поместится.
9. Когда нажимаем на образование, появляется поповер с контроллером и таблицей. Причем, выбранное образование должно быть отмечено чекбоксом. (кстати выбранная дата рождения в мастере тоже должна стоять по умолчанию в новом поповере)
10. У этого контроллера тоже должен быть делегат. По нажатию на ячейку вы должны изменить текущий выбор на новый (поменять чекбокс) и передать сообщение делегату, после чего тот должен изменить содержимое текст филда
Выполнены все задания к уроку 36 Popover
Исходник проекта
Popover представляет собой всплывающее модальное окно со стрелочкой - якорем указывающим на элемент к которому относится Popover.
В новой версии xCode класс UIPopoverController уже deprecated (в IOS 9.0).
Поэтому подробно описывать урок смысла нет (т.к. UIPopoverController использовать уже не нельзя).
В сообщении об ошибке говорится, что теперь popover включен в презентации UIViewController. Используйте модальный стиль презентаций UIModalPresentationPopover и UIPopoverPresentationController.
Попробую домашнее задание реализовать с учетом нововведений в Xcode.
Нашел вот такой пример создания Popover в коде:
Declare a property of
UIPopoverPresentationController
:@property(nonatomic,retain)UIPopoverPresentationController *dateTimePopover8;
Use the following method to present the popover from UIButton:- (IBAction)btnSelectDatePressed:(id)sender
{
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(280,200);
destNav.modalPresentationStyle = UIModalPresentationPopover;
_dateTimePopover8 = destNav.popoverPresentationController;
_dateTimePopover8.delegate = self;
_dateTimePopover8.sourceView = self.view;
_dateTimePopover8.sourceRect = sender.frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
}
Use the following method to present the popover from UIBarButtonItem:
- (IBAction)btnSelectDatePressed:(id)sender
{
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(280,200);
destNav.modalPresentationStyle = UIModalPresentationPopover;
_dateTimePopover8 = destNav.popoverPresentationController;
_dateTimePopover8.delegate = self;
_dateTimePopover8.sourceView = self.view;
CGRect frame = [[sender valueForKey:@"view"] frame];
frame.origin.y = frame.origin.y+20;
_dateTimePopover8.sourceRect = frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
}
Implement this delegate method too in your view controller:
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}
To dismiss this popover, simply dismiss the view controller. Below is the code to dismiss the view controller:
-(void)hideIOS8PopOver
{
[self dismissViewControllerAnimated:YES completion:nil];
}
В процессе выполнения домашнего задания разобрался с разными моментами создания Popover (т.к. методы указанные в уроке уже устарели).
Popover легко можно создать в StoryBoard. Создаем UIButton или UIBarButtonItem, контроллер который будет отображаться как Popover.
От кнопки тянем к новому контроллеру Segue и выбираем PopoverPresentation.
В принципе на Ipad уже будет все работать.
Чтобы и на айфоне нормально выводился поповер, необходимо добавить код:
-(void) prepareForSegue:(nonnull UIStoryboardSegue *)segue sender:(nullable id)sender{
if ([segue.identifier isEqualToString:@"showView"]) {
UINavigationController * nvc = segue.destinationViewController;
UIPresentationController * pc = nvc.presentationController;
pc.delegate=self;
}
}
Так же обязательно присутствие метода для всех типов создания поперев (из кода или storyboard)
- (UIModalPresentationStyle) adaptivePresentationStyleForPresentationController: (UIPresentationController * ) controller {
return UIModalPresentationNone;
}
Если segue начинается не с кнопки, а просто связывает два контроллера, то можно в action кнопки указать использовать нужный segue:
- (IBAction)actionButton:(UIButton *)sender {
[self performSegueWithIdentifier:@"showView" sender:self];
}
Так же нужно прописать, что наш класс поддерживает протокол
@interface ViewController ()<UIPopoverPresentationControllerDelegate>
Для создания Popover из кода:
Создаем property
@property(nonatomic,retain)UIPopoverPresentationController *popoverPresentation;
В обработчик кнопки добавляем код
TAPopoverController *dateVC=[[TAPopoverController alloc]init];
// это контроллер который будут отображен в Popover окне
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:dateVC];/*Here dateVC is controller you want to show in popover*/
dateVC.preferredContentSize = CGSizeMake(150,150);
destNav.modalPresentationStyle = UIModalPresentationPopover;
self.popoverPresentation = destNav.popoverPresentationController;
self.popoverPresentation.delegate = self;
self.popoverPresentation.sourceView = self.view;
CGRect frame = [[sender valueForKey:@"view"] frame];
frame.origin.y = frame.origin.y+20;
self.popoverPresentation.sourceRect = frame;
destNav.navigationBarHidden = YES;
[self presentViewController:destNav animated:YES completion:nil];
Для передачи данных между контроллерами, используется делегат (для возвращения данных в родительский контроллер) и переменная класса при создании контроллера (класс связанный с контроллером).
Объявляем протокол:
@protocol DataPopoverDelegate <NSObject>
-(void) dataFromPopover:(NSDate*) date;
-(void) currentEducationSelected:(NSInteger) currentEducation;
@end
Родительский контроллер поддерживает этот протокол и реализует методы этого протокола
@interface ViewController : UITableViewController <UIAdaptivePresentationControllerDelegate,DataPopoverDelegate>
В дочернем контроллере объявляем член класса - делегат
@interface TADatePickerController : UIViewController
@property (weak, nonatomic) IBOutlet UIDatePicker *birthdayDataPicker;
@property (strong,nonatomic) NSDate *dateBirthday;
@property(weak,nonatomic) id<DataPopoverDelegate> delegate;
@end
Реализация метедов протокола в родительском классе
-(void) dataFromPopover:(NSDate*) date{
self.dateBirthday=date;
[self displayBirthday];
}
-(void) currentEducationSelected:(NSInteger) currentEducation{
self.educationTextField.text=educationArray[currentEducation];
self.currentEducationSelected=currentEducation;
}
При изменении данных в дочернем классе вызываем метод делегата
- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath {
self.currentSelection=indexPath.row;
[tableView reloadData];
[self.delegate currentEducationSelected:self.currentSelection];
}
Так же в этом домашнем задании реализовано сохранения и загрузка данных через NSUserDefaults
- (IBAction)actionSaveData:(UIBarButtonItem *)sender {
NSUserDefaults *userDefault=[NSUserDefaults standardUserDefaults];
[userDefault setObject:self.firstNameTextField.text forKey:kSettingsFirstName];
[userDefault setObject:self.lastNameTextField.text forKey:kSettingsLastName];
[userDefault setInteger:self.sexSegmentControl.selectedSegmentIndex forKey:kSettingsSex];
[userDefault setObject:self.dateBirthday forKey:kSettingsBirthDay];
[userDefault setInteger:self.currentEducationSelected forKey:kSettingsEducation];
[userDefault synchronize];
}
- (IBAction)actionLoadData:(id)sender {
NSUserDefaults *userDefault=[NSUserDefaults standardUserDefaults];
self.firstNameTextField.text=[userDefault objectForKey:kSettingsFirstName];
self.lastNameTextField.text=[userDefault objectForKey:kSettingsLastName];
self.sexSegmentControl.selectedSegmentIndex=[userDefault integerForKey:kSettingsSex];
self.dateBirthday=[userDefault objectForKey:kSettingsBirthDay];
[self displayBirthday];
self.currentEducationSelected=[userDefault integerForKey:kSettingsEducation];
self.educationTextField.text=educationArray[self.currentEducationSelected];
}
Подробное описание модального диалога Alert - UIAlertcontroller
Ученик
1. Создайте универсальное приложение (айпад / айфон)
2. Первый контроллер должен быть статической таблицей с навигейшн баром
3. В правом углу на навигейшине должна быть кнопка инфо, если на нее нажать, то вылазит поповер с объяснением, что это такое за приложение :)
Студент
4. В таблице создайте классические ячейки:
имя + текстфилд
фамилия + текстфилд
пол + сегментед контрол (мужской/женский)
Дата рождения + текстфилд
Образование + текстфилд
5. с первыми тремя ячейками все понятно, а вот дальше самое интересное
Мастер
6. При нажатии на текст филд с датой рождения текст филду должно быть запрещено входить в режим редактирования, а вместо этого из него должен появиться поповер с UIDatePicker. При изменении даты, содержимое текст филда должно меняться (то есть мы не мучаем юзера форматами ввода, мы просто даем ему барабан с датами и предлагаем выбрать самому)
7. Подсказка. Вам надо сделать контроллер с дейт пикером, а дейт пикер это наследник от UIControl, то есть у него есть акшин valueChanged или типо того. У контроллера нужно создать проперти делегат, по которому мы будем отправлять данные, полученные с барабана. То есть по простому: контроллер следит за барабаном и отправляет изменения своему делегату. Не забудьте установить делегат перед создания поповера.
Супермен
8. Тоже самое сделать с образованием. Образование это список типа, неполное среднее, среднее, неполное высшее, высшее и тд, то есть если делать в сегментед контролах, то не поместится.
9. Когда нажимаем на образование, появляется поповер с контроллером и таблицей. Причем, выбранное образование должно быть отмечено чекбоксом. (кстати выбранная дата рождения в мастере тоже должна стоять по умолчанию в новом поповере)
10. У этого контроллера тоже должен быть делегат. По нажатию на ячейку вы должны изменить текущий выбор на новый (поменять чекбокс) и передать сообщение делегату, после чего тот должен изменить содержимое текст филда
Выполнены все задания к уроку 36 Popover
Исходник проекта