Сегодня в рамках направления «Knowlage Sharing» у нас состоялся интересный доклад. Андрей Бойко Senior iOS Developer, стажеры Дима Куликов и Вика Мацкевич рассказали о стэке технологий, которые они использовали для реализации нативного iOS клиента «PROVENG» в рамках проекта стажировки Provectus.
Мы поговорили о Swift 2.x/3.x vs Objective-C, Alamofire, Object Mapper, Realm, Eureka, Fabric.
Ребята рассказали о достоинствах и недостатках вышеперечисленных технологий, о тех проблемах с которыми они столкнулись.
7. Язык
Swift
• Новизна
• Функциональный подход
• Опыт
• Перспектива
• Поддержка Apple
• Простота
• Надежность
• Сырость и Разочарование
Objective-C
• Надежность
• Инструментарий
• Востребованость
рынком
• Наработки
21. Почему ObjectMapper
• Написан на Swift
• С легкостью преобразует JSON в объект модели и наоборот
• Отображение вложенных объектов
• Пользовательское преобразование
• Возможность наследоваться от других объектов
• Использование контекстов
32. Почему Carthage
• Первый менеджер зависимостей для работы с Swift
• Легко установить и удалить с проекта
• Не изменяет проект и не вынуждает использовать
workspace
• Использует исключительно динамические фреймворки
вместо статических библиотек
• Легко добавить зависимости в проект
33. Недостатки
• Нет возможности просмотреть исходный код библиотеки
• Ограниченна поддержка Carthage
• Проект должен поддерживать iOS 8 или более позднюю
версию
• Миграция Swift 2.x->3.x
Xamarin
В процессе миграции мы столкнулись с тем что многие фреймворки не были адаптированы к swift 3 но у многих была beta ветка с одноименным названием из которой по отзывам других разработчиков все работало. Так же некоторые не массивные библиотеки или расширения которые не имели поддержки swift 3 можно было найти на чужих ветках.
Выбор БД:
При выборе локального хранилища мы ориентировались на следующие критерии:
удобная API-шка
Документация, поддержка и комьюнити(исправление багов и поддержка новой версии свифта , к примеру)
Качественные харакеристики: скорость доступа к данным и т.п.
Хотели провести Боевую проверку, инвестигейт
Core Data из коробки не имеет удобного fetch-инга, обертки вроде MagicalRecords конечно упрощают взаимодействие но хотелось более простого решения. NSUserDefaults и работа с файлами были на последнем месте и конкуренцию в выше перечисленных критериях не выдерживали. Поэтому выбор пал на Realm.
Realm быстра и проста в использовании, всего пара строк кода для выполнения любой задачи записи или чтения из базы данных.
Простая в установка: поддержка Cocoapods и Carthage. Удобная Api для работы с БД
Быстрая: Realm быстрее, чем SQLite и CoreData, по сравнительным тестам которые правда представляют сами разработчики( https://realm.io/news/introducing-realm/#fast).
Кросс-платформенная: файлы базы данных Realm кросс-платформенные и могут совместно использоваться на iOS и Android.
Хорошо документированная и есть отличная поддержка: команда разработчиков предоставила легко читаемую и глубокую (лучшую которую мне приходилось читать) документацию о Realm. Но так же можно найти очень много ответов на Github или Stackoverflow.
Встроенный маппинг Обьект можно создавать из соответствующего Dictionary.Мы правда использовали расширенный и удобный фреймворк для этих целей ObjectMapper
Популярная: Realm используется известными компаниями в мобильных приложениях, как Pinterest, Dropbox, Amazon, Ebay и др. Более 1 миллиарда пользователей используют приложения с данной БД.
Бесплатная: Realm как локальное хранилище абсолютно бесплатна. Тарифные планы существуют на клиент-серверные решения (Realm Mobile Platform).
Так же у Realm есть удобное приложение для просмотра и редактирования таблиц БД - RealmBrowser
На данном слайде показано объявление класса Dog и его свойств имя и хозяин а так же класс самого Хозяина его имени ДР и коллекцию собак. Подержка primaryKey
Создание объектов и пример добавления записи в хранилище.
Как мы видим все просто и понятно, отдельно есть свойство, определяющее, должна ли запись быть перезаписанной или все же добавленной (по prim key)
Удобная фильтрация и сортировка основаная на Предикатах.
Можно использовать как предикат строки так и непосредственно свои подготовленные предикаты.
На нижней строке показана цепочка из фильтра и сортировки.
У Realm есть механизм отслеживания изменения обьектов(аналог NSFetchedResultsController в Core Data)
Для использования нужно инициализировать дефолтный Реалм и у коллекции наших объектов вызвать блок "addNotificationBlock" в котором вернется enum c данными о изменениях.Которые в свою очередь удобно использовать для анимированного появления ячеек "beginUpdates...endUpdates".
Deinit чистится токен
Мы столкнулись с ситуацией когда надо было создать unmanaged копию записанного объекта.
Можно конечно было просто создать объект и перебирать свойства, но при изменении модели надо бы было контролировать это во всех местах поэтому мы решили сконвертировать существующий объект в JSON используя сериализатор и на основе его создали нужный unmanaged объект.
Так же не хватало такой удобной вещи как в кор дате где визуально можно было рассмотреть связи между объектами.
Для описания запросов в сетевом уровне мы решили использовать enum.
Так как Swift дает нам возможность определить набор свойств для энама, мы можем указать необходимые параметры, пути, боди и методы запроса для каждого его кейса, что позволяет задать все компоненты запроса на уровне создания энама. При таком подходе на верхнем уровне приложения создание запроса заключается всего лишь в вызове нужного кейса энама с соответствующими параметрами.
Это дает возможность инкапсулировать все параметры запроса, но не делать его, к примеру запустить запрос позже, поставить его в очередь или отослать еще раз в случае получения ошибки.
Минусом такой реализации есть создание большого класса с объявлениями всех кейсов и присваиванием всех компонентов запроса для данных кейсов энама. Кроме того, данный пример является реализацией продвигаемого Apple подхода основывающегося на value тайпах, так что будут проблемы с мутабельностью (изменением).
В данном коде мы видим пример создания компонентов запроса и установки их значений для каждого кейса энама.
Для объявления параметров запроса мы используем переменные, которые передали при формировании запроса
Далее устанавливаем путь запроса
Для объявления боди запроса мы опять же используем переменные, которые передали при формировании запроса, в данной ситуации это модель ивент которую мы конвертируем в JSON строку. О методе конвертации на строке 17 мы еще вернемся.
И конечно же метод HTTP, в котором мы выбираем нужный кейс енама HTTPMethod
До выхода iOS 7.0 общепринятым интерфейсом для загрузки данных по сети служил класс NSURLConnection , затем был добавлен NSURLSession, который со временем стал полноценным преемником, обладающим расширенными и более гибкими возможностями. Начиная с iOS 9.0 NSURLConnection более не рекомендуется использовать.
Но мы искали библиотеку которая бы имела более удобную апишку.
Наиболее популярная библиотека для работы с HTTP-запросами — это AFNetworking. Она имеет богатый набор функций API и является одним из самых распространенных open-source проектов на Github.
Но так как эта библиотека написана на Objective C, мы обратили внимание на библиотеку Alamofire, которую выпустил основатель AFNetworking, предназначенную специально для современных конвенций Swift и его особенностей.
Alamofire имеет хороший обработчик запросов, который вызывается по цепочке после завершения реквеста, он использует стерилизаторы данных responseData, responseString и responseJSON, который в случае успеха вернет результат типа Data, String, JSON. Alamofire дает возможность проверки статус кода ответа. Вызов метода validate перед обработчиком ответа вызывает ошибку, которая должна сгенерироваться, если статус код ответа был недопустим.
Имеет автоматическую проверку наличия сети и в случае отсутствия интернета уведомляет об этом.
Создатели Alamofire добавили дополнительные библиотеки компонентов для лучшей работы с сетевым уровнем. Это библиотека для загрузки картинок которая включает в себя использование пользовательских фильтров изображений AlamofireImage и библиотека для управления отображения индикатора сетевой активности AlamofireNetworkActivityIndicator
Библиотека Alamofire является очень популярной среди Swift разработчиков, документация очень понятна, кроме того имеет большое число комьюнити(более 3500) которые улучшают данную библиотеку
Задаем путь запроса, при необходимости выбираем один из методов HTTP, список которых в Alamofire реализуется в помощью перечислений, затем указываем параметры запроса. Что касается кодировки Alamofire поддерживает три типа кодирования параметров, включая: URL , JSON и PropertyList. В данном запросе мы использовали JSONEncoding, который создает параметры объекта в виде JSON представления. После завершения запроса обрабатывается результат запроса. В случае успешного результата мы попадаем в кейс success в котором выполняем дальнейшие операции с результатом запроса, в случае прихода с сервера ошибки вызывается кейс failure в котором можно выполнить какие-либо действия с ошибкой.
????
Стандартным методом преобразования данных полученных с сервера в свойства объекта модели является метод с использованием NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования данных в NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования данных в NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования данных в объект NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования данных в объект NSDictionary. Основным минусом этого метода является сложная конвертация с большим количеством кода. Библиотека SwiftyJSON и встроенные средства Realm делают конвертация немного проще. Также существует более продвинутая библиотека Mantle которая написана на Objective C но мы ориентировались на Swift библиотеки по-этому остановили свой выбор на библиотеке ObjectMapper, которая на наш взгляд проще и имеет большое количество фитч для преобразования данных в объект модели
ObjectMapper является библиотекой написанной на Swift,что делает ее легкой в использовании.
ObjectMapper поддерживает точечную нотацию в пределах ключей для удобного отображения вложенных объектов
ObjectMapper также поддерживает пользовательские преобразования, которые преобразуют значения в процессе отображения. Например преобразование лонг даты в Date, String в Int или преобразование массива данных в массив объектов
Наследуясь от другой модели (при условии что родительская модель использует маппер) нужно всего лишь вызвать супер методы для маппинга и в случае необходимости дописать новые соотношения свойств дочерней модели и ключей JSON
Об использовании контекстов мы поговорим чуть позже
Для преобразования JSON в объект модели и наоборот необходимо реализовать Mappable протокол и использовать оператор ←, чтобы определить, каким образом каждый член переменной будет конвертироваться в JSON и с JSON,
ObjectMapper может использовать большое количество типов для конвертации
ObjectMapper имеет очень простые функции вызова конвертации JSON строки в объект, массива JSON объектов с массив объектов модели и конвертации объектов модели (или их массива) в JSON строку
При получении данных с сервера и преобразовании его в объект User используются все свойства данного объекта.
Но может возникнуть ситуация если нам не нужны все свойства модели, например чтобы обновить данные юзера нам нужно отправить на сервер лишь его имя, друзей и дату рождения. Чтобы не создавать модель аналогичную модели User но с меньшим количеством свойств мы используем контексты.
Контекст упрощает работу с объектом если возникла необходимость использовать разные наборы полей в объекте модели.
Для этого нужно сначала объявить энам с контекстами которые нам необходимы.
Затем использовать контекст write при конвертации объекта модели в JSON строку.
И главное в методе mapping() определить необходимый набор свойств для каждого контекста.
Еще одно полезная функция контекстов — можно вызывать контекст в контексте. Допустим нам необходимо отсылать на сервер массив друзей в которых нужно указать только их айди. В таком случае нам можно вызвать контекст short перед определением свойства friends. Важно не забыть перед вызовом нового контекста short запомнить значение старого и вернуть это значение после определения свойств с контекстом short.
ЧТО КАСАЕТСЯ НЕДОСТАТКОВ - не обнаружили
Проанализировав ux нашего приложения мы пришли к выводу что будет много где использоваться UITableView, и подумали что целесообразнее подобрать фреймворк. В топах фреймворков на swift фигурировала Eureka и мы решили выбрать ее.
На гитхабе представлено довольно понятное описание и визуализация возможностей фреймворка и в демопроекте можно понять как код выглядит на практике.
Eureka богата на разнообразные ячейки из коробки:даты, тексты, картинки, пикеры, все есть и все красиво.
Так же все готово для создания кастомизированных ячеек,секций и хидера(в демопроекте все это есть на примерах).
Присутствует валидация текстовых ячеек.
Фреймворк имеет популярность среди разработчиков и много положительных отзывов.
На данном слайде представлен визуальный пример что может данный фреймворк
Для реализации UItableView используя Эврику нужно унаследоваться от FormViewController,в котором уже будет свойство tableView и определены методы делегата и дата соурс.
Вся логика фреймворка основана на том чтоб добавлять, удалять, и работать с таблицей без дата соурс, хотя такая возможность есть.
В объект form мы добавляем секции,а в секции соответственно ячейки.
Вы можете видеть не очень привычный и не особо читаемый синтаксис ввиде <<< и +++
Все взаимодействия с ячейкой проходят специализированных callback-ах куда приходят сама ячейка и ее row –объект надстройка над cell который можно использовать для настройки и вызова нужных callback-в например для обновления ячейки.
На слайде вы можете увидеть пример реализации переключения свичера с изменением текста.
Так же у Еврики есть удобный доступ к ячейкам и секциям по tag ввиде строки, мы указывали тип ячейки + id отображаемого объекта.
Теперь можно удобно перезагрузить или обновить нужный элемент.
Минусы с которыми мы столкнулись это нечитабельный синтаксис(как-то не привычно видеть стрелочки плюсики и тд)
и самое тяжелой это встроенная анимация ячеек, которая спрятана внутри фреймворка, при нажатии на ячейку съезжала таблица или при переходе на уже существующий контроллер происходили анимированные увеличения ячеек что выглядит не очень гуд, многое конечно ушло после обновлений от разработчиков библиотеки, но все равно на данный момент есть не решенные моменты, которые пришлось не очень красиво прибить.
Еще мы сделали вывод что Эврика хороша для статических ячеек, если нет необходимости динамически удалять или добавлять ячейки, т.к. данного функционала в ней нет.
Недостатки CocoaPods:
1. Библиотеки должны создавать, обновлять и содержать Podspec файлы
2.Создает новый Xcode проект с таргетом для каждого отдельного pod. Затем необходимо использовать workspace и полагаться, что CocoaPods проект работает правильно
4. Централизованое хранилище данных, которое может быть проблематичным, если по некоторым причинам оно исчезло или стало недоступным
1. Создан специально для Swift
2. Для установки скачать программу с githab и выполнить carthage bootstrap в командной строке. Для удаления с проекта нужно всего лишь удалить Cartfile и Cartfile.resolved, файлы и папки Cartfile.
4. Использует исключительно динамические фреймворки вместо статических библиотек Нет необходимости для Podspecs или централизованного хранилища данных, чтобы авторы библиотеки представляли свои pods. Ваш проект может быть разработан как фреймворк, он может быть использован с Carthage. Он использует существующую информацию прямо из Git и Xcode.
1.Для просмотра кода библиотеки нужно будет качать библиотеку с гита, так как в проекте доступны только хидеры библиотек
2. Некоторые библиотеки нужно будет качать и добавлять вручнуюОграниченна поддержка Carthage - если pod стал де факт стандартом и вплоть до того что такие монстры как Google деплоят свой код через него, то с картежем все сложней
Самым популярным сервисом дистрибуции являлся TestFlight. Однако, после приобретения компанией Apple в начале 2014 года, сервис претерпел ряд неоднозначных изменений, которые сказались негативно на его позиции лидера и дали шанс альтернативным сервисам побороться за первое место. Основным минусом TestFlight является большое количество времени на выпуск приложения для тестирования так как тестовая версия приложения должна быть отправлена для обзора и одобрена специалистами Apple.Еще один значительный минус в том что количество приложений, одновременно доступных для тестирование ограничено до 10. Поэтому мы решили воспользоваться сервисом Fabric.
Интеграция SDK Fabric является быстрой и простой . Добавление приложения для тестирования осуществляется не на сайте сервиса, а в десктопном клиенте, благодаря чему приложение становиться доступным для тестирования очень быстро (в течении 10 минут)
Добавление новых пользователей/тестировщиков возможно как при помощи приложения-клиента, так и на вебсайте сервиса. При этом максимум используемых устройств равен 100 на каждое семейство устройств.
Можно установить любую из предоставленных версий приложения, а не только последнюю
Инструмент обработки падений Crashlytics, является очень мощным средством сбора отчётов о падении приложения. После отправки отчёта с устройства на сервер Fabric (это происходит после перезапуска “упавшего” приложения), сервис рассылает уведомления по электронной почте, а также выводит оповещение на компьютерах с установленным клиентом. При этом отчете можно увидеть не только название класса но и название метода и даже номер строчки кода который вызвал падение
Минусы - отсутствие встроенной системы сбора отзывов
Недостаток по слаку: шарить экран, групповое общение
Ушли от гитфлоу так как он оказался избыточным для небольших задач
В процессе разработки мы в основном использовали голосовой вариант связи, через скайп или iMessage демонстрировали экраны для обсуждения текущих проблем и пути их решения. Слак оказался удобным мессенджером для общения с командой, довольно полезной фичей было создание сниппетов для демонстрации примера читабельного кода