воскресенье, 18 октября 2015 г.

33. UINavigationController, UITableViewController


Видео урок 33 расположен здесь.
В этом уроке продолжаем создавать приложения "в коде" без использования сторибоард. 
Сегодня тема урока - более подробное рассмотрение контроллера навигации UINavigationController  и использование готового контроллера таблиц UITableViewController.
Тестовое приложение для изучение этих контроллеров - файловый менеджер.

Проект создается на базе EmptyApplication. В новом xCode отсутствует, поэтому удаляем ненужные файлы.

Создается класс наследник UITableViewController.
Создается проперти   

@property(strong,nonatomic) NSString *path;
@property(strong,nonatomic) NSArray *contents;

Заменяется конструктор  - (instancetype)initWithStyle:(UITableViewStyle)style  на

-(id) initWithFolder: (NSString *)path{
    self = [super initWithStyle:UITableViewStyleGrouped];
    if(self){
        NSError *error=nil;
        self.contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error];
        if (error){
            NSLog(@"%@",[error localizedDescription]);
        }
        self.path=path;
    }
    return self;

}

Стандартно определяем методы из UITableDataSource

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.contents.count;
}

Для удобства определим функцию определяющую на файл или директорию указывает indexPath:
-(BOOL) isDirectoryAtIndexPath: (NSIndexPath*) indexPath{
    NSString *fileName=[self.contents objectAtIndex:indexPath.row];
    NSString *filePath=[self.path stringByAppendingPathComponent:fileName];
//    NSLog(@"self.path=%@,filePath=%@,fileName=%@",self.path,filePath,fileName);
    
    BOOL isDirectory=NO;

    ;
    if (!  [[NSFileManager defaultManager]fileExistsAtPath:filePath isDirectory:&isDirectory]) NSLog(@"fileExistsAtPath No");
    return isDirectory;


}

Используя эту функцию выводим картинку папку или файл в ячейку вместе с именем

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *identifier=@"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }

    NSString *fileName=[self.contents objectAtIndex:indexPath.row];
    cell.textLabel.text=fileName;
    if ([self isDirectoryAtIndexPath:indexPath]) {
        cell.imageView.image=[UIImage imageNamed:@"folder.png"];
    }
    else{
        cell.imageView.image=[UIImage imageNamed:@"file.png"];

    }
    return cell;

}

В viewDidLoad определяем заголовок навигационной панельки 

    self.navigationItem.title=[self.path lastPathComponent];

lastPathComponent - Метод возвращает последний компонент (папку) в строке с дисковым путем.


Создаем наш контроллер.
 В классе AppDelegate в методе didFinishLaunchingWithOptions
    TADirectoryViewController *controller=[[TADirectoryViewController alloc] initWithFolder:@"/"];

Создаем навигационный контроллер

    UINavigationController *navigation=[[UINavigationController alloc] initWithRootViewController:controller]; 

Устанавливаем в свойствах окна root контроллер

    self.window.rootViewController=navigation;

Для перемещения по папкам необходимо реализовать метод выделения строк

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    if([self isDirectoryAtIndexPath:indexPath]){
        NSString *fileName=[self.contents objectAtIndex:indexPath.row];
        NSString *filePath=[self.path stringByAppendingPathComponent:fileName];
        TADirectoryViewController *controller=[[TADirectoryViewController alloc] initWithFolder:filePath];
        [[self navigationControllerpushViewController:controller animated:YES];
    }
}

При нажатии на ячейку если содержимое является директория, создается и инициализируется путем новый контроллер и помещается на стек навигационного контроллера.

Для просмотра количества контроллеров в стеке навигационного контроллера и определения индекса текущего контроллера:

    NSLog(@"Path=%@. ViewController=%@. Index Current ViewController:%@",
          self.path,
          @([self.navigationController.viewControllers count]),
          @([self.navigationController.viewControllers indexOfObject:self]));

В viewDidLoad добавляем кнопку ссылку на начальный каталог - Root

    if ([self.navigationController.viewControllers count]>1) {
        UIBarButtonItem *item=[[UIBarButtonItem alloc]initWithTitle:@"Root"
                                                              style:UIBarButtonItemStylePlain
                                                             target:self action:@selector(actionRoot:)];
    self.navigationItem.rightBarButtonItem=item;

    }

И обработчик для кнопки выталкивает все контроллеры со стека навигационного контроллера до Root- контроллера

-(void) actionRoot:(UIBarButtonItem*) sender{
    [self.navigationController popToRootViewControllerAnimated:YES];

}

Ссылка на исходник тестового проекта.


 Домашнее задание к уроку 33-34


Я рекомендую вам немного задержаться на этом уроке и снова попрактиковать таблицы. Также будет довольно таки неплох о если вы углубитесь в NSFileManager

Ученик.

1. Добавьте возможность создавать директории
2. Добавьте возможность удалять файлы и папки

Студент

3. Сортируйте файлы и папки, сверху должны быть папки, снизу файлы, сортировка по имени
4. Не показывайте скрытые файлы

Мастер

5. В detailedTextField каждой ячейки файла, выводите размер файла.

Супермен

6. Тем же способом выводите размер папки (размер папки придется считать рекурсивно :) )



Выполнил домашнее задание "в коде" без использования storyboard

Исходник к домашнему заданию 33.



Комментариев нет:

Отправить комментарий