Давайте признаем очевидное. Верстка экранов в iOS ужасна. Сравнивая с html, с WPF, с Android, с WinPhone — везде iOS проигрывает.
Верстка в iOS исторически напоминала WinForms (с аналогом якорей-Anchor’ов в виде AutoresizingMask). Однако WinForms уже давно отошло в прошлое, а iOS всё живет и живет :)
Да, на смену AutoresizingMask пришли Constraints, но работа с ними до жути неудобна, дизайнер ненаглядный, а результат работы — нечитаемый уже через неделю после создания.
А вообще, помимо удобства, наибольшей проблемой, конечно, становится динамическая верстка элементов. Если мы пришли из мира WPF/Android, то скучать по простейшему StackLayout/LinearLayout будем очень-очень сильно.
Возьмем например типичную задача: верстка элементов в строчку, при этом некоторые элементы могут быть спрятаны.
<StackLayout> <Button /> <Button Visibility="Collapsed" /> <Button /> </StackLayout>
Чтобы задать такую верстку в iOS — придется изрядно помучаться. В случае со «старым» AutoresizingMask — это и вовсе невозможно, и придется разруливать координаты кнопок руками при каждом изменении видимости кнопок.
В случае «нового» и «продвинутого» LayoutConstraints — это, конечно, возможно, но намного сложнее и куда менее очевидно, чем xml-верстка.
Решение нашлось на просторах сети — XibFree. Это довольно простой layout-движок, который позволяет верстать экраны в iOS без использования .xib-файлов или Storyboard’ов, полностью в c#-файлах.
Вот как выглядит верстка, аналогичная верхней:
var layout = new LinearLayout(Orientation.Horizontal) { Padding = new UIEdgeInsets(10, 10, 10, 10), LayoutParameters = new LayoutParameters() { Width = AutoSize.FillParent, Height = AutoSize.WrapContent, }, SubViews = new View[] { new NativeView() { View = new UIButton() { }, Init = v => { v.As<UIButton>().SetTitle("Test1", UIControlState.Normal) }, LayoutParameters = new LayoutParameters(AutoSize.WrapContent, AutoSize.WrapContent) }, new NativeView() { View = new UIButton() { }, Init = v => { v.As<UIButton>().SetTitle("Test2", UIControlState.Normal) }, LayoutParameters = new LayoutParameters(AutoSize.WrapContent, AutoSize.WrapContent) Gone = true, }, new NativeView() { View = new UIButton() { }, Init = v => { v.As<UIButton>().SetTitle("Test3", UIControlState.Normal) }, LayoutParameters = new LayoutParameters(AutoSize.WrapContent, AutoSize.WrapContent) Gone = true, }, }, };
А в чем же отличие от Xamarin.Forms, спросите вы? Да, действительно, есть некоторое сходство. Основное отличие же в том, что XibFree реализует исключительно View-часть и не претендует на кроссплатформенность. За счет этого XibFree работает быстрее, практически не влияет на минимальный размер приложения (который для Xamarin.Forms — 32Mb), и не накладывает на iOS-разработчика никаких ограничений (кроме языка c#, если кто-то это считает ограничением :)).
Из преимуществ можно выделить:
- Простоту освоения, схожесть с аналогами на Андроид/WPF
- Простота использования, отсутствие каких-либо абстракций над UI-элементами (используются напрямую UIButton/UILabel/etc.)
- Счастье при создании динамической верстки, под разные разрешения
- Отсутствие претензий по производительности
- Удобство при работе с системой контроля версий и поддержке — XibFree это код, а не нечитаемый xml как в случае xib и Storyboard
Из объективных минусов можно выделить «заброшенность» библиотеки: оригинальные разработчики не обновляли XibFree с января 2015. Тем не менее, весь функционал работает и вмешательства не требует.
Возможно, стандартных LinearLayout/FrameLayout будет и недостаточно для чересчур изощренных экранов — это тоже надо иметь ввиду.
Тем не менее, мы в своих проектах с такими ограничениями не столкнулись, активно используем XibFree и исключительно довольны.
Рекомендую :)
P.S. Некоторые существующие проблемы мы самостоятельно решаем. В частности, в нашем форке мы добавили WrapLayout, ведется работа над GridLayout.
Подытоживая, список ссылок: