Итак, первый классический — обычный NSLayoutConstraint. Удобный, нативный и нисколько не обременяющий в написании. Но что если ваше приложение должно работать на iPhone SE 1 поколения? Тогда с вероятностью в 100% где-то вёрстка поедет. Для этого случая вы можете использовать UIDevice.current.
Второй помощник — UIDevice.current. Эта переменная, которую вы можете сами прописать в extension UIDevice. Она позволяет вам высчитывать размеры текущего устройства и исходя из этого создавать другие переменные и делегировать устройства по группам: таким, как isSmallScreen/isXScreenDevice . Но даже этого не всегда бывает достаточно, и приходится отказываться от разного рода дизайнерских решений.
extension UIDevice { var iPhone: Bool { return UIDevice().userInterfaceIdiom == .phone } enum ScreenType: String { case iPhone8 case iPhone8Plus case iPhoneX case iPhoneXSMax case iPhone11 case iPhone11Pro case iPhoneSE case iPhone12 case iPhone12Pro case iPhone12Mini case Unknown } var current: ScreenType { guard iPhone else { return .Unknown} switch UIScreen.main.nativeBounds.height { case 1136: return .iPhoneSE case 1334: return .iPhone8 case 2208: return .iPhone8Plus case 2436: return .iPhoneX case 2521: return .iPhone12 case 2532: return .iPhone11Pro case 2688: return .iPhoneXSMax case 2778: return .iPhone12Pro case 1792: return .iPhone11 default: return .Unknown } } }
И третий, о котором я узнал лишь на первой работе и больше нигде его не применял. Для этого мы создаём константы screenHeight и screenWidth, которые равны UIScreen.main.bounds.height/width . При использовании в NSLayoutConstraint придерживаемся такой формулировки:
// Для вертикальных констрейнтов (например topAnchor, bottomAnchor) 20/812*screenHeight // Для горизонтальных констрейнтов (например leadingAnchor, trailingAnchor) 20/375*screenWidth
Этот вариант практически идеально позволяет распределить UI-объекты на разных устройствах, и элементы вашего приложения будут выглядеть всегда одинаково и на iPhone 14 Pro Max, и на iPhone SE.
При первом взгляде это самый подходящий вариант. Однако чем чаще его используешь, тем больше приходит понимание, что это не панацея, а скорее не нужный, объёмный «костыль», который заполоняет весь код магическими числами и непременно вызовет негодование у вашего тимлида. Поэтому я бы рекомендовал его использовать только в редких случаях.
NSLayoutConstraint.activate([ secondTitleLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -156/812*screenHeight), secondTitleLabel.rightAnchor.constraint(equalTo: view.rightAnchor), secondTitleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), secondTitleLabel.leftAnchor.constraint(equalTo: view.leftAnchor) ]) NSLayoutConstraint.activate([ mainTitleLabel.bottomAnchor.constraint(equalTo: secondTitleLabel.topAnchor, constant: -32/375*screenWidth), mainTitleLabel.rightAnchor.constraint(equalTo: view.rightAnchor), mainTitleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor), mainTitleLabel.leftAnchor.constraint(equalTo: view.leftAnchor) ])
В заключение скажу, что спустя время я чаще прибегаю к обычной работе констрейнтов, и их всегда хватает с головой. Иногда в редких случаях я использую UIDevice.current. И практически никогда третий вариант.
Экспериментируйте! Если найдёте для себя полезным тот или иной вариант, попробуйте его в своём проекте. Если я упустил что-то, не стесняйтесь поделиться этим в комментариях.
Надеюсь, эта статья была для вас полезна.
ссылка на оригинал статьи https://habr.com/ru/post/709088/
Добавить комментарий