Видео урок находится здесь.
В этом уроке рассказывается как переделать проект файлового менеджера из прошлого урока с помощью StoryBoard.
Первым делом удаляем наш код создания контроллеров из функции didFinishLaunchingWithOptions класса AppDelegate.
Теперь это будет делаться из StoryBoard.
Если файла StoryBoard не существует, если существует переходим к следующему шагу.
Создаем в storyboard UINavigationController и UITableViewController.
Перетягиваем с одного на другой линию и устанавливаем root контроллер.
Для инициализации меняем сеттер и конструктор, т.к. вызывать конструктор со сторибоард не получиться.
Все работает как в предыдущем проекте за исключением кнопки возврата в Root контроллер.
Это происходит так как метод viewDidLoad в котором происходит создание кнопки вызывается еще до того, как контроллер создается.
Если перенести код создания кнопки в функцию viewWillAppear, то все работает нормально.
Кстати xCode выдает ворнинг на такой способ добавления, т.е. им лучше не пользоваться
Push segues are deprecated since iOS 8.0
Ссылке Segue даем идентификатор navigateDeep.
Так же добавляем новое property
Заменяем предыдущий абзац кода на
-(void) prepareForSegue:(nonnull UIStoryboardSegue *)segue sender:(nullable id)sender{
Если определить метод
Для того, чтобы изменить высоту строки в таблице нужно определить метод
Определяем 3 Label вставляем фотографию и кнопку.
Определяем идентификатор FileCell.
Создаем новый файл-класс тоже же типа.
Создаем оутлеты, которые соответствуют Label
В этом уроке рассказывается как переделать проект файлового менеджера из прошлого урока с помощью StoryBoard.
Первым делом удаляем наш код создания контроллеров из функции didFinishLaunchingWithOptions класса AppDelegate.
Теперь это будет делаться из StoryBoard.
Если файла StoryBoard не существует, если существует переходим к следующему шагу.
Создаем в storyboard UINavigationController и UITableViewController.
Перетягиваем с одного на другой линию и устанавливаем root контроллер.
Для инициализации меняем сеттер и конструктор, т.к. вызывать конструктор со сторибоард не получиться.
-(void) setPath:(NSString *)path{
_path=path;
NSError *error=nil;
self.contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
if (error){
NSLog(@"%@",[error localizedDescription]);
}
[self.tableView reloadData];
self.navigationItem.title=[self.path lastPathComponent];
}
-(id) initWithFolder: (NSString *)path{
self = [super initWithStyle:UITableViewStyleGrouped];
if(self){
self.path=path;
}
return self;
}Все работает как в предыдущем проекте за исключением кнопки возврата в Root контроллер.
Это происходит так как метод viewDidLoad в котором происходит создание кнопки вызывается еще до того, как контроллер создается.
Если перенести код создания кнопки в функцию viewWillAppear, то все работает нормально.
-(void) viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
self.navigationItem.title=[self.path lastPathComponent];
if ([self.navigationController.viewControllers count]>1) {
UIBarButtonItem *item=[[UIBarButtonItem alloc]initWithTitle:@"Root"
style:UIBarButtonItemStylePlain
target:self action:@selector(actionRoot:)];
self.navigationItem.rightBarButtonItem=item;
}
}
Для того, чтобы загрузить контроллер из сторибоард, а не создать с помощью конструктора, мы в функции
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
обрабатывающей нажатие на строку заменим
// TADirectoryViewController *controller=[[TADirectoryViewController alloc] initWithFolder:filePath];
// [[self navigationController] pushViewController:controller animated:YES];
на
TADirectoryViewController* vc=[storyboard instantiateViewControllerWithIdentifier:@"TADirectoryViewController"];
vc.path=filePath;
[self.navigationController pushViewController:vc animated:YES];
Еще один вариант сделать вызов контроллера из самого контроллера с помощью сторибоард
Нужно поместить кнопку uibarbutton не на сам контроллер, а на панель над контроллером и связать эту кнопку с самим контроллером.Кстати xCode выдает ворнинг на такой способ добавления, т.е. им лучше не пользоваться
Push segues are deprecated since iOS 8.0
Ссылке Segue даем идентификатор navigateDeep.
Так же добавляем новое property
@property (strong,nonatomic) NSString * selectedPath;
Заменяем предыдущий абзац кода на
// UIStoryboard *storyboard=self.storyboard;
// TADirectoryViewController* vc=[storyboard instantiateViewControllerWithIdentifier:@"TADirectoryViewController"];
// vc.path=filePath;
// [self.navigationController pushViewController:vc animated:YES];
self.selectedPath=filePath;
[self performSegueWithIdentifier:@"navigateDeep" sender:nil ];
Определяем метод, который вызывается перед переходом по Segue
NSLog(@"prepareForSegue %@",segue.identifier);
if([segue.identifier isEqualToString:@"navigateDeep"]){
TADirectoryViewController *destinationController=segue.destinationViewController;
TADirectoryViewController *sourceController=segue.sourceViewController;
destinationController.path=sourceController.selectedPath;
}
}
Если определить метод
-(bool) shouldPerformSegueWithIdentifier:(nonnull NSString *)identifier sender:(nullable id)sender{
NSLog(@"shouldPerformSegueWithIdentifier identifier:%@",identifier);
return YES;
}
Можно контролировать по каким связям запускать, а по каким нет и что-то можно делать перед запускам в зависимости от типа связи.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if ([self isDirectoryAtIndexPath:indexPath]) {
return 40.f;
}else{
return 80.f;
}
}
Для настройки ячеек таблицы из storyboard UITableController настраиваем единственно созданную с контроллером ячейку.
Определяем фотографию папки и идентификатор FolderCell
Затем добавляем новую ячейку на контроллер типа UITableViewCell . Определяем 3 Label вставляем фотографию и кнопку.
Определяем идентификатор FileCell.
Создаем новый файл-класс тоже же типа.
Создаем оутлеты, которые соответствуют Label
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *sizeLabel;
@property (weak, nonatomic) IBOutlet UILabel *dateLabel;
Заменяем старый код функции на новый, с учетом того, что ячейки загружаются из сторибоард
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *fileIdentifier=@"FileCell";
static NSString *folderIdentifier=@"FolderCell";
NSString *fileName=[self.contents objectAtIndex:indexPath.row];
if ([self isDirectoryAtIndexPath:indexPath]) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:folderIdentifier];
cell.textLabel.text=fileName;
return cell;
}else{
NSString *filePath=[self.path stringByAppendingPathComponent:fileName];
NSDictionary * attributes=[[NSFileManager defaultManager]attributesOfItemAtPath:filePath error:nil];
TAFileCell* cell = [tableView dequeueReusableCellWithIdentifier:fileIdentifier];
cell.nameLabel.text=fileName;
cell.sizeLabel.text=[self fileSizeFromValue:[attributes fileSize]];
static NSDateFormatter *dateFormatter=nil;
if (!dateFormatter){
dateFormatter=[[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:@"MM/dd/yyyy hh:mm a"];
}
cell.dateLabel.text=[dateFormatter stringFromDate:[attributes fileModificationDate]] ;
return cell;
}
Для вывода размера файла создана специальная функция показывающая размер в байтах, кб, мегабайтах и т.д.
-(NSString*) fileSizeFromValue:(unsigned long long) size{
int index=0;
double fileSize =(double) size;
while (fileSize>1024&&index<unitsCount) {
fileSize/=1024;
index++;
}
return [NSString stringWithFormat:@"%.2f %@",fileSize,unit[index]];
}
Для определения ячейки на которой была нажата кнопка создаем дополнительную категорию к классу UIView
@implementation UIView (UITableViewCell)
-(UITableViewCell*) superCell{
if(!self.superview) {
return nil;
}
return [self.superview superCell]; ;
}
static NSString *unit[]={@"B",@"KB",@"Mb",@"Gb",@"TB"};
static int unitsCount=5;int index=0;
while (fileSize>1024&&index<unitsCount) {
fileSize/=1024;
index++;
}
return [NSString stringWithFormat:@"%.2f %@",fileSize,unit[index]];
}
Для определения ячейки на которой была нажата кнопка создаем дополнительную категорию к классу UIView
#import "UIView+UITableViewCell.h"
return nil;
}
if ([self.superview isKindOfClass:[UITableViewCell class]]) {
return (UITableViewCell*)self.superview;
}}
@end
И обработчик нажатия на кнопку с выводом секции и ряда нажатия
- (IBAction)actionInfo:(UIButton *)sender {
NSLog(@"ActionInfo");
UITableViewCell *cell=[sender superCell];
if (cell) {
NSIndexPath*indexPath=[self.tableView indexPathForCell:cell];
NSLog(@"action %@ %@",@(indexPath.section),@(indexPath.row));
}
Домашнее задание к уроку 33-34
Я рекомендую вам немного задержаться на этом уроке и снова попрактиковать таблицы. Также будет довольно таки неплох о если вы углубитесь в NSFileManager
Ученик.
1. Добавьте возможность создавать директории
2. Добавьте возможность удалять файлы и папки
Студент
3. Сортируйте файлы и папки, сверху должны быть папки, снизу файлы, сортировка по имени
4. Не показывайте скрытые файлы
Мастер
5. В detailedTextField каждой ячейки файла, выводите размер файла.
Супермен
6. Тем же способом выводите размер папки (размер папки придется считать рекурсивно :) )
Комментариев нет:
Отправить комментарий