Программирование под iPhone, iPad Objective-C уроки на русском статьи новости

2013-07-10 11:29


В этом уроке я предлагаю не создавать новый проект, а воспользоваться отличным примером от компании Apple. Исходный код этого примера Вы можете загрузить по следующей ссылке SimpleFTPSample. Вот так выглядит приложение при первом запуске:

 

 

Как видно со скриншота, в примере реализован основной функционал для работы с FTP.

 

Давайте теперь заглянем "под капот". Первым, что бросается в глаза является класс NetworkManager. Это синглтон, он импортирован во все контроллеры представления и является вспомагательным классом для работы с сетью.

 

Первым в списке примеров является загрузка картинки через FTP с сервера NASA. Здесь представлено два способа загрузки. Через NSURLConnection (URLGetController) и NSInputStream (GetController). Рассмотрим подробней первый способ. Все начинается с нажатия кнопки Get:

 

- (IBAction)getOrCancelAction:(id)sender
{
    #pragma unused(sender)
    if (self.isReceiving) {
        [self stopReceiveWithStatus:@"Cancelled"];
    } else {
        [self startReceive];
    }
}

 

В обраотке нажатия добавлен условный оператор. Если при нажатии программа уже загружает данные - это процесс будет отменен, иначе - начнется новая загрузка. Если заглянуть в метод startReceive - там Вы увидите знакомый код с урока Закачка данных. То есть, загрузка любого файла по протоколу FTP ничем не отличается от той же загрузки по HTTP или HTTPS. Если в методе startReceive строчку:

 

url = [[NetworkManager sharedInstance] smartURLForString:self.urlText.text];

 

заменить на:

 

url = [NSURL URLWithString:@"http://www.imaladec.com/img/logo.png"];

 

Приложение без проблем загрузит логотип сайта imaladec.com.

 

С получением списка файлов с FTP-сервера такая же ситуация как с картинками. Следует обратить внимание лишь на два ньюанса:

 

  • список файлов мы будем получать в том случае, когда ссылка не буедт вести на какой-то конкретный файл (ссылка должна вести на каталог). 
  • весь список приходит одной строкой (не XML или JSON)

 

В классе ListController для загрузки используется NSInputStream, но как я уже говорил, это лишь дело вкуса. А обратить внимание следует на метод parseListData, в нем как раз и просиходит процесс парсинга полученого списка.

 

В классе PutController приведет пример загрузки изображения на FTP-сервер. Здесь следует обратить внимание на то как создается объект fileStream. Если раньше мы использовали метод outputStreamToFileAtPath:append:, то теперь следует писать inputStreamWithFileAtPath:, а в качестве параметра передавать ссылку на тот файл, который хотим "залить" на сервер. Может быть ситуация, когда файла как такового у вас нету. Есть переменная с данными в памяти. В таком случае нет необходимости сохранять данные на диск и передавать ссылку на сохраненный файл. Возмоно использовать метод inputStreamWithData:, в который в качестве параметра передать данные типа NSData.

 

Для редактирования содержимого FTP-сервера может потребоваться учетная запись (необходим будет ввести логин и пароль). Следующий код как раз и реализует эту возможность:

 

if ([self.usernameText.text length] != 0) {
    success = [self.networkStream setProperty:self.usernameText.text forKey:(id)kCFStreamPropertyFTPUserName];
    assert(success);
    success = [self.networkStream setProperty:self.passwordText.text forKey:(id)kCFStreamPropertyFTPPassword];
    assert(success);
}

 

Для создания нового подкаталога следует дописать к полной ссылки на сервер имя новой папки. То есть, если исходная ссылка выглядит так: ftp://localhost/ то для создания новой папки с именем untitled ее следут преобразовать в ftp://localhost/untitled/. В случае с созданием каталога нет необходимости использовать объект типа NSInputStream. Пример создания новой папки Вы можете посмотреть в методе startCreate класса CreateDirController.

 

Я не знаю почему, но в коде нет примера удаления файлов или каталогов с FTP-сервера. Для этого используется метод CFURLDestroyResource:

 

- (void)removeFolder {
    SInt32 status = 0;
    NSURL *url = [[NSURL alloc] initWithString:@"ftp://localhost/untitled/"];
    
    Boolean success = CFURLDestroyResource((__bridge CFURLRef)url, &status);
    if (success) {
        NSLog(@"deletion success");
    } else {
        NSLog(@"deletion failed");
    }
}

 

Здесь следует обратить внимание на то, что папка должна быть пустой (то есть, перед удалением каталога следует удалить все файлы и подкаталоги в нем). Кроме этого, последний слеш (/) в ссылке при удалении обязательный, этого требует FTP протокол.