Эта статья — результат изучения стиля Swift из The Pragmatic Bookshelf и жизненного опыта. Это руководство может использовать iOS-инженер любого уровня.
У вас не было понятия о стилевом коде
когда вы впервые начали писать программное обеспечение. Вероятно, удачная компиляция была фантастической. Однако с годами разработка фреймворка стилей кода необходима для полезности и означает наличие опыта. Некоторые из этих советов основаны на повышении производительности, а другие — на чистом визуальном стиле.
Стилизация фигурных скобок в Swift
прост. Если вы хотите ухаживать за своими коллегами, поделитесь этими занудными битами…
Существует 2 стиля форматирования фигурных скобок. Первый, One True Brace Style, насколько я знаю, напыщенный, известен как 1TBS.
1 ТБ Стиль
If let x = x { // code } else { // code }
Второй — стиль Allman, также известный как стиль BSD.
Оллман
If let x = x { // code } else { // code }
Без ведома многих программистов Swift, мы в подавляющем большинстве следуем стилю 1TBS. Однако стиль Allman может пригодиться в ситуациях, когда вам нужна лучшая читабельность. Вы можете использовать гибридный подход обоих в одной области.
Избегайте нетерпеливых оценок с помощью ключевого слова Lazy
при использовании функций высокого порядка. Lazy, конечно, задержит вычисление до тех пор, пока не понадобится функция более высокого порядка. Это избавит вас от ненужного создания массивов.
let newCars = allCars.lazy.filter({$0.isNew})
Сложные операторы Guard в Swift
должны быть помещены под индивидуальную охрану, а не числиться группами.
func validateScore() { //Prefer guard let score = score else {return} guard score.isEmpty else {return} guard let validator = validator else {return} //Avoid guard let score = score, score.isEmpty, let validator, validator else {return} }
Этот стиль позволяет вам легко комментировать отдельные операторы защиты и настраивать вертикальный интервал для комментариев.
Объединение и Тернарные операторы
могут оказаться уместными в подобных сценариях. Swift Style рекомендует отдавать предпочтение объединению из-за его краткости и ясности.
//Prefer backgroundColor ?? .grey //Avoid backgroundColor == nil ? .grey : backgroundColor!
При использовании тернарного оператора стек «?» и «:» вертикально вот так…
backgroundColor == nil ? .grey : backgroundColor!
По моему опыту, ваш наставник, коллеги и будущий я будут аплодировать такому стилю форматирования, потому что коммиты, изменяющие значения, повлияют только на одну строку. Если я изменю .grey на .white, это будет хорошо видно в PR.
Коллекции Стайлинга
является прямым, дайте каждому элементу отдельную линию и оставьте замыкающую скобку. Это, опять же, помогает в написании чистых PR.
// Prefer let carColors: [String: UIColor] = [ "Corvette": .yellow, "Tesla Model Y": .black, "Toyota Tundra": .blue ] //Avoid let carColors: [String:UIColor] = ["Corvette": .yellow, "Tesla Model Y": .black, "Toyota Tundra": .blue] //Short collections like this are okay let nascarNumbers: [Int] = [1, 23, 44, 62]
При добавлении коллекций
предпочитаю append(contentsOf:) и append() вместо «+». «+=» вызывает append(contentsOf:).
//Prefer cars.append(contentsOf: mustangs) //Prefer cars += mustangs //Avoid cars + mustangs
Более быстрая и чистая итерация опций
можно легко выполнить с помощью сопоставления с образцом case let. Оба этих шаблона делают одно и то же, за исключением того, что case let намного чище.
//Prefer for case let pet? in pets { } //Avoid for pet in pets { if let pet = pet { } }
Будьте более описательными с forEach
или используйте цикл for in, чтобы быть более наглядным.
//Prefer for car in cars {print(car)} //Prefer cars.forEach {car in access(car)} //Avoid cars.forEach {access{$0}}
Целочисленная читабельность
можно упростить с помощью этой тактики подчеркивания.
//Prefer let usBankruptValue: Int = 7_000_000 //Avoid let usBankruptValue: Int = 7000000 //What number is this ^ you mean I have to count the zeros now?
Swift игнорирует подчеркивание во время компиляции. Придерживайтесь естественного шаблона, обозначающего продвижение на 3 места.
Объявления типов
Должен быть последовательным, и мы должны избегать полагаться на вывод типа. Будьте как можно более описательными со значениями, потому что 20 может быть целым числом или двойным числом, но 20,0 не может быть целым числом.
//Prefer let leadingConstant: CGFloat = 20.0 //Avoid let leadingConstant: CGFloat = 20 //Avoid let leadingConstant = 20.0 as CGFloat
Придерживайтесь согласованных объявлений типов и, если позволяет руководство по стилю вашей компании, отдавайте предпочтение объявлениям типов перед знаком «=».
//Prefer let cars: [String] = [] //Prefer Repeating When Possible let cars: [String] = .init(repeating: "Chevy", 6) //Avoid let cars = [String]()
Предпочитаю литье или литералы
чтобы избежать дополнительных вызовов функций. В следующем примере avoid мы без необходимости используем инициализатор UInt.
//Prefer let carNumber: UInt8 = 8 //Avoid let carNumber = UInt(8)
С наборами опций
быть как можно более описательным с аргументами. Отличным примером из Swift Style является…
//Prefer accessQueue.sync(flags: [.barrier]) //Avoid accessQueue.sync(flags: .barrier)
Пусть скобки передают идею о том, что можно добавить больше вариантов.
При работе с опционами
вы можете использовать синтаксический сахар Swift, чтобы обеспечить более четкое сопоставление с образцом.
//Prefer switch (optionalOne, optionalTwo) { case let (first?, second?):... } //Avoid switch (optionalOne, optionalTwo) { case let (.some(first), .some(second):... }
Более чистые объявления кортежей
может сократить блоки кода по вертикали и позволить вам объявлять связанные элементы в одном и том же месте.
//Maybe use this var (carId, mpg) = (1395, 32) //Maybe use this var carId = 1395 var mpg = 32 //Avoid var carId = 1395; var mpg = 32
Замена с помощью кортежей может быть выполнена быстрее, чем классический способ установки временного значения…
//Prefer (x, y) = (y, x) //Prefer - write a function to swap swap(&first, &second) //Avoid let tmp = second second = first first = tmp
Использовать затенение с одинаковым именем
при разворачивании опций…
//Prefer guard let car = car else {return} //Avoid guard let mustang = car else {return}
Это может помочь вам избежать конфликтов имен за пределами области видимости и свести к минимуму необходимость использования self.
Вы также можете развернуть с помощью ключевого слова var…
//Prefer, mutable car if var car = car {} //Avoid if let car = car { //Making car mutable var variableCar = car }
Используйте ключевое слово «есть»
чтобы проверить, могут ли ключевые слова со стертым типом быть разрешены как другой тип. Это может быть полезно, если вам не нужно выполнять приведение типов.
if object is car { print("") }
Пытаться?
следует зарезервировать для случаев, когда вам все равно, почему операция не удалась. Вместо этого используйте шаблон do-catch.
//Prefer do { try requestCars() } catch { assertionFailure("Request Cars Failed") } //Avoid let cars = try? requestCars()
Когда нужны только индексы
вы можете перебирать их напрямую без перечисления.
//Prefer for carIdx in cars.indices { } //Avoid for (index, _) in cars.enumerated { }
Обновите свои операторы Switch
с предложениями where. Кроме того, выровняйте ключевые слова case по вертикали с ключевым словом switch.
switch car.isBlack() { //If car is available do something case true where car.isAvailable(): ... //If true and unavailable do something else case true: ... default:... }
Предпочитайте двойные числа, а не поплавки
поскольку двойники более точны. Двойное число содержит 15 десятичных цифр, а число с плавающей запятой имеет точность 9.
Предпочитайте Int UInt (или другим вариантам)
Int поддерживает лучшую совместимость. В 32-битной системе Int равен 32 битам. В 64-битной системе целое число равно 64 битам. Это не относится к Int32 или Int64 с фиксированным размером.
Следует использовать неявное «я»
по возможности для краткости. Избегайте явного вызова себя, когда это не нужно.
struct Car { var color: UIColor? = .black mutating func changeColor() { //Prefer color = .white //Avoid self.color = .white } }
Предпочитайте слабый захват, а не неизвестный
поскольку weak безопаснее, unowned предназначен для объектов с гарантированным сроком службы.