Статьи

iOS SDK: UIActivityIndicatorView и MBProgressHUD

UIKit предоставляет разработчикам UIActivityIndicatorView, который является не чем иным, как счетчиком. Тем не менее, этот простой подкласс UIView сообщает пользователю, что что-то находится в процессе — жизненно важный вопрос UX. В этом уроке я расскажу вам все о UIActivityIndicatorView и в качестве дополнительного бонуса я познакомлю вас с MBProgressHUD, классом индикатора активности на стероидах!

Всякий раз, когда пользователь взаимодействует с вашим приложением, важно, чтобы он знал о том, что делает ваше приложение. Если ваше приложение обновляет большую базу данных в фоновом режиме, и вы хотите, чтобы пользователь не взаимодействовал с вашим приложением до тех пор, пока этот процесс не будет завершен, то недостаточно просто предотвратить взаимодействие пользователя с вашим приложением. Всякий раз, когда процесс занимает более нескольких миллисекунд, может быть полезно показать обратную связь с пользователем. Люди любят отзывы, поскольку они рассказывают им, что происходит. Если вы мне не верите, я советую потратить час на чтение отзывов в App Store.


Нам не нужна сложная настройка для этого быстрого совета. Запустите Xcode и создайте новый проект, используя шаблон «Single View Application».

UIActivityIndicatorView Рисунок 1

Назовите свое приложение SpinnerDemo , введите идентификатор компании, установите «iPhone» для семейства устройств и снимите флажок «Использовать раскадровки». Вы можете оставить остальное нетронутым. Сообщите Xcode, где вы хотите сохранить этот проект, и нажмите «Сохранить».

UIActivityIndicatorView Рисунок 2

Как видно из его названия, UIActivityIndicatorView является подклассом UIView. UIActivityIndicatorView прост в настройке и использовании, поэтому давайте сделаем это прямо сейчас. В навигаторе проекта слева выберите ViewController.m и найдите метод — viewDidLoad . Замените реализацию по умолчанию на приведенную ниже.

1
2
3
4
5
6
7
— (void)viewDidLoad {
    [super viewDidLoad];
     
    UIActivityIndicatorView *ai = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    ai.center = self.view.center;
    [self.view addSubview:ai];
}

Для отображения UIActivityIndicatorView требуются только три строки кода. В первой строке мы инициализируем индикатор активности стилем. Нам доступны три стиля: (1) UIActivityIndicatorViewStyleWhiteLarge, (2) UIActivityIndicatorViewStyleWhite и (3) UIActivityIndicatorViewStyleGray. Названия стилей говорят сами за себя, то есть стили отличаются только цветом и размером. Во второй строке мы помещаем индикатор активности в центр представления нашего контроллера представления, а в последней строке мы добавляем наш UIActivityIndicatorView в качестве подпредставления к представлению контроллера представления.

Когда вы создадите и запустите свое приложение, вы будете удивлены отсутствием индикатора активности. Это почему? По умолчанию для свойства hidesWhenStopped установлено значение YES . Это означает, что UIActivityIndicatorView будет скрываться, когда он не анимируется (вращается). Давайте оживим наш индикатор активности, добавив одну дополнительную строку в наш файл реализации.

1
2
3
4
5
6
7
8
— (void)viewDidLoad {
    [super viewDidLoad];
     
    UIActivityIndicatorView *ai = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    ai.center = self.view.center;
    [ai startAnimating];
    [self.view addSubview:ai];
}

Создайте и запустите приложение еще раз, и теперь вы увидите, что ваш индикатор активности вращается, как никогда раньше. Потратьте немного времени, чтобы изменить стиль UIActivityIndicatorView, чтобы получить представление о том, как выглядят различные стили. В iOS 5 вы также можете изменить цвет индикатора активности, установив свойство цвета индикатора активности.

Остановить индикатор активности просто. Вы просто вызываете — прекращаете анимацию в UIActivityIndicatorView. Как я упоминал ранее, если для hidesWhenStopped установлено значение YES , индикатор активности будет скрываться автоматически. В большинстве случаев это именно то поведение, которое вам нужно.

Индикатор имеет значение, когда он указывает на что-то, но если он не указывает на что-то, его не должно быть. -Jony Ive, объективированный (2009)

Есть еще один метод, о котором я хотел бы поговорить, так как он может пригодиться при работе с UIActivityIndicatorView. Вызов — isAnimating в UIActivityIndicatorView сообщит вам, является ли индикатор активности в данный момент анимируемым.

Прежде чем мы продолжим, я хотел бы отметить кое-что очень важное и то, с чем сталкиваются многие новые разработчики iOS. Я не хочу вдаваться в детали и фоны сегодня, но суть в том, что вы всегда должны быть уверены, что не блокируете основной поток вашего приложения. Возможно, вы слышали это раньше, и это особенно верно для UIActivityIndicatorView. Обновление пользовательского интерфейса выполняется в главном потоке, и это означает, что когда вы блокируете основной поток, выполняя длительную задачу в основном потоке, это сделает ваше приложение не только не отвечающим на пользователя, но и предотвратит вашу активность. индикатор от появления или анимации. Как я уже сказал, я напишу об этом немного больше в следующем посте.


Давайте теперь посмотрим на MBProgressHUD. Если вы разрабатывали приложения для iOS в течение некоторого времени, вы обязательно увидите преимущества этого удивительного класса с открытым исходным кодом. Вы можете найти MBProgressHUD по адресу https://github.com/jdg/MBProgressHUD. Спасибо Матею Буковински за разработку и поддержку MBProgressHUD.

Вы заметите, что MBProgressHUD (HUD расшифровывается как head-up display) выглядит знакомо, и это потому, что он очень похож на HUD прогресса, который Apple использует в некоторых своих собственных приложениях. Тем не менее, прогресс HUD, который использует Apple, является частным и поэтому недоступен сторонним разработчикам.


Добавить MPProgressHUD в ваше приложение очень просто. Загрузите проект с GitHub, распакуйте архив и перетащите файлы MBProgressHUD.h и MBProgressHUD.m в ваш проект Xcode. Убедитесь, что вы отметили «Копировать элемент в папку целевой группы (если необходимо)», а также добавили MBProgressHUD к вашей цели, SpinnerDemo.

MBProgressHUD Рисунок 3

MBProgressHUD был разработан, чтобы дать пользователю обратную связь, когда трудоемкие задачи выполняются в фоновом режиме. Запомните это последнее слово — фон. Как я упоминал ранее, вы не хотите блокировать основной поток, выполняя трудоемкую задачу в основном потоке. Я не могу подчеркнуть это достаточно.


Использование MBProgressHUD почти так же просто, как UIActivityIndicatorView. Требуется чуть больше работы, чтобы все настроить, но вы получите много взамен этих усилий. Сначала закомментируйте четыре строки кода, которые мы добавили для настройки индикатора активности. Нам это больше не понадобится. Далее мы собираемся добавить новую переменную экземпляра (ivar) в заголовочный файл нашего класса ViewController. Не забудьте также добавить объявление прямого класса MBProgressHUD, чтобы ваш класс ViewController знал о MBProgressHUD.

1
2
3
4
5
6
7
8
9
#import <UIKit/UIKit.h>
 
@class MBProgressHUD;
 
@interface ViewController : UIViewController {
    MBProgressHUD *HUD;
}
 
@end

Вернитесь к ViewController.m и импортируйте файл заголовка MBProgressHUD, добавив следующую строку чуть ниже первого оператора импорта.

1
#import «MBProgressHUD.h»

Если вы выполнили предыдущие шаги, метод — viewDidLoad вашего класса ViewController теперь должен содержать только вызов метода суперкласса — viewDidLoad и четыре закомментированные строки кода. Теперь давайте инициализируем наш MBProgressHUD, изменив метод — viewDidLoad на приведенный ниже (закомментированный код не показан).

1
2
3
4
5
6
7
— (void)viewDidLoad {
    [super viewDidLoad];
 
    HUD = [[MBProgressHUD alloc] initWithView:self.view];
    [self.view addSubview:HUD];
    [HUD show:YES];
}

Инициализация MBProgressHUD немного отличается от инициализации UIActivityIndicatorView. Вместо передачи стиля вы передаете представление в качестве аргумента вашего метода — init . Это представление является представлением, которое MBProgressHUD будет блокировать (пользователь не сможет взаимодействовать с этим представлением), когда отображается HUD прогресса. Вторая строка должна быть знакома, а в третьей строке мы говорим HUD показывать себя, поскольку он скрыт по умолчанию. Готов? Создайте и запустите ваше приложение в симуляторе iOS и посмотрите на отображаемый прогресс HUD.

На первый взгляд вы можете подумать, что это менее полезно, чем UIActivityIndicatorView. Он разбрызгивается в середине экрана, и, похоже, нет способа позиционировать прогресс HUD. Это потому, что MBProgressHUD служит другой цели, как я уже говорил ранее. Он предназначен для того, чтобы показать пользователю, что задача выполняется, и также предотвращает взаимодействие пользователя с представлением, к которому добавляется HUD прогресса.

MBProgressHUD имеет гораздо больше возможностей, чем просто показывать и скрывать себя. Например, вы можете назначить делегата, который получит уведомление, когда прогресс HUD спрятался. Кроме того, вы можете в большой степени настроить HUD для прогесов с помощью индикатора прогресса, одной или двух меток, сообщающих пользователю о том, что делает ваше приложение, и его также можно использовать для отображения сообщения. Серьезно, MBProgressHUD очень полезен, и я предлагаю вам взглянуть на демонстрационное приложение, которое поставляется вместе с загруженным вами проектом, чтобы понять, что оно может сделать для вас.


В завершение этого урока я хотел бы показать вам один пример того, как вы можете использовать MBProgressHUD в более сложном сценарии. Мы собираемся выполнить трудоемкую задачу в фоновом режиме, в то время как наш прогресс HUD показывает ход этой задачи. Если честно, мы не собираемся выполнять задание в фоновом режиме. Мы подражаем этому с умным решением, которое также используется демонстрационным приложением, включенным в MBProgressHUD. Отредактируйте установочный код вашего MBProgressHUD так, чтобы он выглядел так, как показано ниже.

1
— (void)viewDidLoad { [super viewDidLoad];

Во второй и третьей строке мы устанавливаем текст первичной и вторичной метки прогресса HUD, чтобы дать пользователю некоторую информацию о том, что происходит. Четвертая строка устанавливает режим нашего HUD. MBProgressHUD поставляется с несколькими различными режимами, и выбранный нами режим MBProgressHUDModeAnnularDeterminate покажет индикатор хода выполнения, который показывает ход выполнения нашей фоновой задачи. В последней строке мы не просто показываем HUD, но мы показываем HUD и говорим ему, что мы выполняем задачу, и она должна показывать себя, пока она выполняется. Разве я не говорил вам, что MBProgressHUD прост в использовании. Давайте теперь посмотрим на — doSomeFunkyStuff .

1
2
3
4
5
6
7
8
9
— (void)doSomeFunkyStuff {
    float progress = 0.0;
     
    while (progress < 1.0) {
        progress += 0.01;
        HUD.progress = progress;
        usleep(50000);
    }
}

Мы объявляем float с именем progress и устанавливаем его в 0.0. Используя цикл while, мы увеличиваем прогресс и устанавливаем для свойства progess MBProgressHUD это значение. Это приведет к продвижению индикатора прогресса нашего HUD. Последняя строка цикла while — хитрый трюк, чтобы убедиться, что запуск этого метода занимает больше нескольких миллисекунд. Используя функцию usleep , выполнение основного потока приостанавливается на величину, которую мы передаем в качестве аргумента (в микросекундах). Наконец, цикл while работает до тех пор, пока progess меньше 1.0. HUD автоматически исчезнет, ​​когда наш метод завершится. Создайте и запустите ваше приложение, чтобы увидеть все это в действии.


Как видите, как UIActivityIndicatorView, так и MBProgressHUD имеют свои варианты использования, и оба они чрезвычайно полезны, если вы хотите создать удобное для пользователя приложение. Не забудьте взглянуть на демонстрационное приложение MBProgressHUD, чтобы увидеть, что он может сделать для вас.