Xib swift что это

iOS Storyboards: анализ плюсов и минусов, best practices

Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

Apple создала Storyboards, чтобы разработчики могли визуализировать экраны iOS-приложений и связи между ними. Не всем понравился этот инструмент, и на то есть разумные причины. Я встречал много статей с критикой Storyboards, однако так и не нашел подробного и непредвзятого анализа всех плюсов и минусов с учетом best practices. В итоге я решил написать такую статью сам.

Я постараюсь подробно разобрать недостатки и преимущества использования Storyboards. Взвесив их, вы сможете принять осмысленное решение, нужны они в проекте или нет. Это решение не обязательно должно быть радикальным. Если в одних ситуациях Storyboards создают проблемы, в других — их использование оправдано: помогает эффективно решать поставленные задачи и писать простой, легко поддерживаемый код.

Начнем с недостатков и проанализируем, действительно ли все они до сих пор актуальны.

Недостатки

1. В Storyboards тяжело править конфликты при слиянии изменений

Storyboard – это XML-файл. Он хуже поддается чтению, чем код, поэтому разрешать конфликты в нем сложнее. Но эта сложность также зависит и от того, как мы работаем со Storyboard. Можно значительно упростить себе задачу, если следовать приведенным ниже правилам:

2. Storyboards мешают повторному использованию кода

Если речь идет об использовании в проекте только Storyboards без Xibs, то проблемы обязательно возникнут. Однако Xibs, на мой взгляд, – необходимые элементы при работе со Storyboards. Благодаря им можно легко создавать переиспользуемые Views, с которыми также удобно работать и в коде.

XibView будет загружать UIView из Xib в contentView и добавлять его как свой subview. Сделаем это в методе setup() :

Метод loadViewFromNib() выглядит так:

Метод setup() должен вызываться в инициализаторах:

Класс XibView готов. Переиспользуемые Views, внешний вид которых отрисован в Xib-файле, будут наследоваться от XibView :

Еще одной полезной деталью, о которой могут не все знать, является возможность добавлять цвета в каталог .xcassets. Это позволяет менять их глобально во всех Storyboards и Xibs, где они используются.

Чтобы добавить цвет, нажимаем «+» внизу слева и выбираем «New Color Set»:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Указываем нужное имя и цвет:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Созданный цвет появится в разделе «Named Colors»:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Кроме того, его можно получить и в коде:

Этот код можно сделать лучше с помощью каких-нибудь констант для представления идентификаторов или таких инструментов, как SwiftGen и R.swift, а может даже Perform. Но так мы лишь избавляемся от строковых литералов и добавляем синтаксический сахар, а не решаем проблемы, которые возникают:

4. По мере роста Storyboard навигация в нем становится все сложнее

Как мы уже отмечали ранее, не нужно помещать все в один Storyboard, лучше разбить его на несколько более мелких. С появлением Storyboard Reference это стало очень просто.
Добавляем Storyboard Reference из библиотеки объектов в Storyboard:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Выставляем необходимые значения полей в Attributes Inspector – это имя Storyboard-файла и по необходимости Referenced ID, что соответствует Storyboard ID нужного экрана. По умолчанию будет загружен Initial View Controller:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Если указать неверное имя в поле Storyboard или сослаться на несуществующий Storyboard ID, Xcode предупредит об этом на этапе компиляции.

5. Xcode тормозит при загрузке Storyboards

Если Storyboard содержит большое количество экранов с многочисленными constraints, то его загрузка действительно будет отнимать определенное время. Но опять же, лучше разбить большой Storyboard на более мелкие. По отдельности они грузятся значительно быстрее и с ними становится удобнее работать.

6. Storyboards хрупкие, ошибка может привести к падению приложения на этапе выполнения

Основные слабые места:

Можно снизить вероятность ошибки, если избавиться от строковых литералов в коде. Для этого идентификаторам UITableViewCell и UICollectionViewCell можно присваивать названия самих классов ячеек: например, идентификатором ItemTableViewCell будет строка «ItemTableViewCell». В коде достаем ячейку так:

Можно добавить в UITableView соответствующую generic-функцию:

И тогда получить ячейку становится проще:

Если вдруг вы забудете указать значение идентификатора ячейки в Storyboard, Xcode выдаст предупреждение, поэтому не стоит их игнорировать.

Что касается идентификаторов segues, то для них можно использовать перечисления. Создадим специальный протокол:

А запускать segue так:

Еще один вариант избавиться от строковых литералов типа идентификаторов segues и других – использовать инструменты кодогенерации наподобие R.swift.

7. Storyboards менее гибкие, в отличие от кода

Да, это действительно так. Если стоит задача создать сложный экран с анимацией и эффектами, с которыми Storyboard не справится, то нужно использовать код!

8. Storyboards не позволяют сменить тип специальных UIViewControllers

9. Storyboards добавляют две дополнительные зависимости в проект. Они могут содержать ошибки, которые разработчик не в силах исправить

Это Interface Builder и парсер Storyboards. Такие случаи – редкость, и зачастую их можно обойти другими решениями.

10. Сложный code review

Нужно принять во внимание, что code review – это не совсем поиск багов. Да, их находят в процессе просмотра кода, но главной целью является выявление слабых мест, способных создать проблемы в долгосрочной перспективе. Для Storyboards это, в первую очередь, работа Auto Layout. Не должно быть никаких ambiguous и misplaced. Чтобы их найти, достаточно воспользоваться поиском в Storyboard XML по строкам «ambiguous=«YES»» и «misplaced=«YES»» или просто открыть Storyboard в Interface Builder и искать красные и желтые точки:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Однако этого может быть недостаточно. Конфликты между constraints могут выявляться и во время работы приложения. Если подобная ситуация имеет место, информация об этом выводится в консоли. Такие случаи – не редкость, поэтому к их поиску тоже нужно отнестись серьезно.

Все остальное – соответствие положения и размеров элементов с дизайном, корректная привязка IBOutlets и IBActions – не для code review.

Кроме того, важно делать коммиты чаще, тогда рецензенту будет проще просматривать изменения небольшими кусками. Он сможет лучше вникнуть в детали, ничего не упустив. Это, в свою очередь, положительно скажется на качестве ревью кода.

В списке недостатков Storyboards я оставил 4 пункта (в порядке убывания их значения):

Преимущества

1. Визуализация пользовательского интерфейса и constraints

Отдельно отметим Auto Layout. Это очень мощный и полезный инструмент, без которого трудно было бы создать приложение, поддерживающее все множество различных размеров экрана. Interface Builder позволяет увидеть результат работы с Auto Layout без запуска приложения, и если какие-то constraints не вписываются в общую схему, Xcode сразу же предупредит об этом. Конечно, существуют случаи, когда Interface Builder не способен обеспечить нужное поведение какого-то очень динамичного и сложного интерфейса, тогда приходится полагаться на код. Но даже в таких ситуациях можно сделать большую часть в Interface Builder и дополнить это лишь парой строчек кода.

Рассмотрим несколько примеров, демонстрирующих полезные возможности Interface Builder.

Динамичные таблицы на основе UIStackView

Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

Self-sizing ячейки

В Size inspector таблицы устанавливаем Row Height = Automatic, а Estimate – в какое-нибудь среднее значение:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Чтобы это работало, в самих ячейках должны быть верно настроены constraints и позволять точно вычислить высоту ячейки на основе содержимого на этапе выполнения. Если не понятно, о чем идет речь, очень хорошее объяснение есть в официальной документации.

В итоге, запустив приложение, мы увидим, что все корректно отображается:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

Self-sizing таблица

Нужно реализовать такое поведение таблицы:

Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

Заметим, что на видео в какой-то момент высота таблицы перестает меняться, достигая определенного максимального значения. Этого можно добиться, установив у таблицы height constraint со значением Relation = Less Than Or Equal:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
На данном этапе Interface Builder еще не знает, какой высоты будет таблица, ему лишь известно ее максимальное значение, равное 200 (из height constraint). Как было отмечено ранее, Intrinsic Content Size не равен содержимому таблицы. Однако у нас есть возможность установить placeholder в поле Intrinsic Size:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Это значение действительно только на время работы с Interface Builder. Безусловно, Intrinsic Content Size не обязан быть равен этому значению во время выполнения. Мы лишь сказали Interface Builder, что все под контролем.

Далее, создаем новый подкласс таблицы CustomTableView :

2. Возможность мгновенно увидеть результат своих действий

Использование @IBInspectable раскрывает это преимущество еще интереснее. Добавим к RedView два UILabel и два свойства:

Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

Видим, что Attributes Inspector объекта RedView обзавелся еще 4-мя новыми полями, с которыми теперь тоже можно поиграться:

Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader

3. Предварительный просмотр всех размеров экрана одновременно

Вот мы закинули необходимые элементы на экран, настроили их вид и добавили нужные constraints. Как нам выяснить, будет ли содержимое корректно отображаться на разных размерах экрана? Конечно, можно запустить приложение на каждом симуляторе, но это займет немало времени. Существует вариант получше: у Xcode есть режим предварительного просмотра, он позволяет увидеть сразу несколько размеров экрана одновременно без запуска приложения.

Вызываем Assistant editor, в нем нажимаем на первый сегмент панели переходов, выбираем Preview –> Settings.storyboard (как пример):
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Сначала мы видим лишь один экран, но можем добавить столько, сколько нужно, нажав «+» в левом нижнем углу и выбрав необходимые устройства из списка:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Кроме того, если Storyboard поддерживает несколько языков, можно посмотреть, как будет выглядеть выбранный экран с каждым из них:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Язык можно выбрать как для всех экранов сразу, так и для каждого по отдельности.

4. Удаление шаблонного UI кода

Создание пользовательского интерфейса без Interface Builder сопровождается либо большим количеством шаблонного кода, либо суперклассами и расширениями, которые влекут за собой дополнительную работу по обслуживанию. Этот код может проникать в другие части приложения, затрудняя чтение и поиск. Использование Storyboards и Xibs позволяет разгрузить код, благодаря чему он становится более сфокусированным на логике.

5. Size classes

Каждый год появляются новые устройства, под которые нужно адаптировать пользовательский интерфейс. В этом помогают концепции trait variations и, в частности, size classes, которые позволяют создавать UI под любые варианты размеров и ориентации экрана.

Size classes классифицируют высоту (h) и ширину (w) экранов устройств в терминах compact и regular (C и R). Например, iPhone 8 имеет size class (wC hR) в портретной ориентации и (wC hC) – в альбомной, а iPhone 8 Plus – (wC hR) и (wR hC) соответственно. По остальным девайсам можно узнать здесь.

В одном Storyboard или Xib для каждого из size classes можно хранить свой набор данных, а приложение уже на этапе выполнения будет использовать подходящий в зависимости от устройства и ориентации экрана, идентифицируя таким образом текущий size class. Если какие-то параметры макета одинаковы для всех size classes, то их можно настроить в категории «Any», которые уже выбрана по умолчанию.

Например, настроим размер шрифта в зависимости от size class. Выберем для просмотра в Storyboard устройство iPhone 8 Plus в портретной ориентации и добавим новое условие для font : если width – Regular (все остальное устанавливаем в «Any»), то размер шрифта должен быть равен 37:
Xib swift что это. image loader. Xib swift что это фото. Xib swift что это-image loader. картинка Xib swift что это. картинка image loader
Теперь, если мы поменяем ориентацию экрана, размер шрифта увеличится – сработает новое условие, так как в альбомной ориентации iPhone 8 Plus имеет size class (wR hC). В Storyboard в зависимости от size class можно также скрывать Views, включать/отключать constraints, менять их значение constant и многое другое. Подробнее о том, как все это делать, можно прочитать здесь.

На скриншоте выше стоит еще отметить нижнюю панель с выбором устройства для отображения макета. Она позволяет быстро проверить адаптивность UI на любом устройстве и при любой ориентации экрана, а также показывает size class текущей конфигурации (рядом с названием устройства). Помимо прочего, справа есть кнопка «Vary for Traits». Ее цель в том, чтобы включить trait variations только для определенной категории ширины, высоты или ширины и высоты одновременно. Например, выбрав iPad с size class (wR hR), нажимаем «Vary for Traits» и ставим галочки напротив width и height. Теперь все последующие изменения макета будут применяться только к устройствам с (wR hR), пока мы не нажмем «Done Varying».

Источник

Правильная передача данных

Xib swift что это. 400%D1%85111 2%D1%85. Xib swift что это фото. Xib swift что это-400%D1%85111 2%D1%85. картинка Xib swift что это. картинка 400%D1%85111 2%D1%85 Xib swift что это. snow 1374%D1%85182 2%D1%85. Xib swift что это фото. Xib swift что это-snow 1374%D1%85182 2%D1%85. картинка Xib swift что это. картинка snow 1374%D1%85182 2%D1%85

Xib swift что это. 684%D1%85112 2%D1%85. Xib swift что это фото. Xib swift что это-684%D1%85112 2%D1%85. картинка Xib swift что это. картинка 684%D1%85112 2%D1%85 Xib swift что это. snow 1374%D1%85182 2%D1%85. Xib swift что это фото. Xib swift что это-snow 1374%D1%85182 2%D1%85. картинка Xib swift что это. картинка snow 1374%D1%85182 2%D1%85

Правильная передача данных

Доброго времени суток, друзья!

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

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

В этой статье я покажу вам такие практики передачи данных:

Передача данных вперед

Передача данных происходит каждый раз, когда на экране появляется новый ViewController.

Это может произойти через segue или программно.

Передача данных вперед между ViewController с использованием segues

Заметка

Всегда правильно задавайте идентификатор для segue. Хорошей практикой будет называть идентификатор тем, что он делает. Потому что может быть ситуации когда Вам нужно передать 2 и более segue в один контроллер. В дальнейшем это поможет свободно ориентироваться в проекте.

Передача данных вперед между ViewController без segues

Иногда вы можете подключить ViewController программно, а не использовать segue.

И готово! Так как в SecondViewController не поменялся код, показываем код FirstViewController :

Передача данных в обратном направлении

Передача данных назад в приложении iOS так же важна, как и их перемещение вперед. Пользователи часто возвращаются к предыдущему экрану, который они посетили.

Когда пользователь взаимодействует с вашим приложением, вы должны обновлять эти предыдущие экраны. Это не происходит автоматически, поэтому вы можете использовать разные методы.

Передача данных в обратном направлении через unwind segue

Передача данных в обратном направлении при помощи делегата

Иногда техники, которые Вы видели, все еще недостаточны.

Заметка

Для закрепления можете сами попробовать сделать это, взяв примеры из 1.2 Передача данных вперед между ViewController без segues.

Продвинутые техники

Замена делегирования на замыкания (closures) Swift

Некоторые разработчики используют замыкания ( closures ) Swift для передачи данных назад между ViewControllers. Этот метод похож на делегирование, но более гибкий. Это также причина, почему я обычно рекомендую не использовать его.

И теперь в FirstViewController также устанавливает связь с этим замыканием, когда происходит переход. Но в этом случае вместо передачи ссылки на себя, он передает замыкание.

Также обратите внимание, что замыкание содержит ссылку на себя. Таким образом, как и делегирование, использование замыканий по-прежнему создает связь между двумя ViewController.

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

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

На мой взгляд, замыкания лучше работают как обратные вызовы для асинхронных задач, таких как сетевые запросы или анимации. Делегирование является лучшим решением для связи ViewController.

Неправильные техники

Мы познакомились с одними из лучших практик для передачи данных между ViewController. Но к сожалению, в просторах интернета наблюдается и много неправильных.

В этом разделе мы рассмотрим, какие из них, и почему вы не должны их использовать.

Не используйте UserDefaults iOS

В iOS UserDefaults хранят пользовательские настройки, которые должны сохраняться между запусками приложения.

Кроме того, вы можете хранить только простые типы данных в UserDefaults в форме списков свойств. Это означает, что вам нужно преобразовать любой пользовательский тип, прежде чем вы сможете поместить его туда.

В общем, ваше приложение должно получать доступ к UserDefaults через одну точку, которая обычно является настраиваемым контроллером совместно используемой модели.

Не используйте Notifications

Notifications в iOS дают вам канал, по которому какой-то код может отправлять сообщение другим объектам, на которые он не имеет прямой ссылки.

Я видел, как многие разработчики используют Notifications для передачи данных между контроллерами представления. Это не то, для чего они нужны!

Выводы

Как я и говорил, существует много способов передачи данных между ViewController. Но только некоторые из них можно назвать хорошей практикой. Поначалу другие могут показаться удобными, но потом они могут создать Вам проблемы в будущем.

Поэтому выбирайте правильный подход и двигайтесь дальше!

Источник

Общее представление об архитектуре Clean Swift

В этой статье я расскажу об архитектуре iOS приложений — Clean Swift. Мы рассмотрим основные теоретические моменты и разберем пример на практике.

Xib swift что это. 8r z0fpt1kekmkabu1y92ctoriy. Xib swift что это фото. Xib swift что это-8r z0fpt1kekmkabu1y92ctoriy. картинка Xib swift что это. картинка 8r z0fpt1kekmkabu1y92ctoriy

Теория

Мостом между компонентами выступает файл Models, который хранит в себе передаваемые данные. Так же есть Router, отвечающий за переход и передачу данных между сценами, и Worker, который берет часть логики Interactor’a на себя.

Xib swift что это. xfkttir6l7nud2q m8ptw 1kfl8. Xib swift что это фото. Xib swift что это-xfkttir6l7nud2q m8ptw 1kfl8. картинка Xib swift что это. картинка xfkttir6l7nud2q m8ptw 1kfl8

Storyboard’ы, XIB’ы или UI элементы, написанные через код.

ViewController

Отвечает только за конфигурацию и взаимодействие с View. В контроллере не должно находиться никакой бизнес логики, взаимодействия с сетью, вычислений и так далее.
Его задача обрабатывать события с View, отображать или отправлять данные (без обработки и проверок) в Interactor.

Interactor

Содержит в себе бизнес логику сцены.

Он работает с сетью, базой данных и модулями устройства.

Interactor получает запрос из ViewController’a (с данными или пустой), обрабатывает его и, если это требуется, передает новые данные в Presenter.

Presenter

Занимается подготовкой данных для отображения.

Как пример, добавить маску на номер телефона или сделать первую букву в названии заглавной.
Обрабатывает данные, получение из Interactor’a, после чего отправляет их обратно во ViewController.

Models

Набор структур для передачи данных между компонентами VIP цикла. Каждый круг цикла имеет в себе 3 вида структур:

Worker

Разгружает Interactor, забирая на себя часть бизнес логики приложения, если Interactor стремительно разрастается.

Так же можно создавать общие для всех сцен Worker’ы, если их функционал используется в нескольких сценах.

Как пример, в Worker можно выносить логику работы с сетью или базой данных.

Router

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

Для прояснения картины работы VIP цикла приведу стандартный пример — авторизация.

Практика

А теперь разберем небольшой практический пример, который покажет как проходит VIP цикл. В этом примере мы сымитируем подгрузку данных при открытии сцены (экрана). Основные участки кода я пометил комментариями.

Весь VIP цикл завязан на протоколах, что обеспечивает возможностью подмены каких-либо модулей без нарушения работы приложения.
Для ViewController’a создается протокол DisplayLogic, ссылка на который передается в Presenter для последующего вызова. Для Interactor’a создаются два протокола BusinessLogic, отвечающий за вызов методов из ViewController’a, и DataSource, для хранения данных и передачу через Router в Interactor другой сцены. Presenter подписывается под протокол PresentationLogic, для вызова из Interactor’a. Связующим элементом всего этого выступает Models. Он содержит в себе структуры, с помощью которых идет обмен информаций между компонентами VIP цикла. С него и начнем разбор кода.

Xib swift что это. . Xib swift что это фото. Xib swift что это-. картинка Xib swift что это. картинка

Models

В примере ниже, для сцены Home, я создал файл HomeModels, который содержит в себе набор запросов для VIP цикла.
Запрос FetchUser будет отвечать за подгрузку данных о пользователе, который мы и будем рассматривать дальше.

ViewController

При инициализации класса мы создаем экземпляры классов Interactor’a и Presenter’a этой сцены и устанавливаем зависимости между ними.
Далее во ViewController’e остается ссылка только на Interactor. С помощью этой ссылки мы будем создавать запрос к методу fetchUser(request:) в Interactor’е, для запуска VIP цикла.

Здесь стоит обратить внимание, как происходит запрос к Interactor. В методе loadUserInfromation() мы создаем экземпляр структуры Request, куда передаем начальное значение. Оно может быть взято из TextField, таблицы и так далее. Экземпляр структуры Request передается в метод fetchUser(request:), который находится в протоколе BusinessLogic нашего Interactor’a.

Interactor

Экземпляр класса Interactor’a содержит в себе ссылку на протокол PresentationLogic, под который подписан Presenter.

В методе fetchUser(request:), может содержаться любая логика подгрузки данных. Для примера я просто создал константы, с якобы полученными данными.

В этом же методе создается экземпляр структуры Response и заполняется, полученными ранее, параметрами. Response передается в PresentationLogic с помощью метода presentUser(response:). Другими словами, здесь мы получили сырые данные и передали их на обработку в Presenter.

Presenter

Имеет ссылку на протокол DisplayLogic, под который подписан ViewController. Не содержит никакой бизнес логики, а только форматирует полученные данные перед отображением. В примере мы отформатировали номер телефона, подготовили экземпляр структуры ViewModel и передали его на ViewController, с помощью метода displayUser(viewModel:) в протоколе DisplayLogic, где уже происходит отображение данных.

Заключение

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *