July 11, 2021

Быстрые советы и рекомендации по Swift

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

1. Сравнение необязательных опций с точными значениями

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

Обычно можно найти такие вещи:

var someOptionalString: Строка? else let stringValue = someOptionalString, stringValue.isEmpty { ... }

Если ваша цель состоит в том, чтобы просто проверить, не пуста ли строка, и действовать на ее основе, вы можете просто сравнить isEmpty с точным ожидаемым результатом, в конечном итоге получить что-то вроде этого:

var someOptionalString: Строка? else stringValue?.isEmpty == false { ... }

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

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

Когда логическое значение объявляется optional, мы получаем 3 возможных значения: true, false и nil.

3. Использование вложенных типов для интервала имен

Пространство имен - это набор символов, которые используются для организации объектов различных видов, так что на эти объекты можно ссылаться по имени. Пространство имен гарантирует, что все идентификаторы в нем имеют уникальные имена, чтобы их можно было легко идентифицировать.
(Источник: Википедия)

В Swift это может быть достигнуто с помощью вложенных типов.

// Before

struct Product {

let category: ProductCategory

let description: ProductDescription

}

struct ProductCategory { ... }

struct ProductDescription { ... }

let category = ProductCategory()

let description = ProductDescription()

// After

struct Product {

let category: Category

let description: Description

}

extension Product {

struct Category { ... }

struct Description { ... }

}

let category = Product.Category()

let description = Product.Description()

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

4. Предоставление значения по умолчанию для параметров в протоколах

При извлечении интерфейсов из чего-то очень часто встречаются методы с параметрами по умолчанию, а протоколы Swift не позволяют этого иметь. Чтобы сохранить совместимость, лучше не менять это поведение.

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

// Before

final class ProductsAPI {

func getCatalog(productType: String, page: Int = 1, productsPerPage: Int = 30) { ... }

}

// After

protocol ProductsAPIProvider {

func getCatalog(productType: String, page: Int, productsPerPage: Int)

}

extension ProductsAPIProvider {

func getCatalog(productType: String, page: Int = 1, productsPerPage: Int = 30) {

self.getCatalog(productType: productType, page: page, productsPerPage: productsPerPage)

}

}

final class ProductsAPI: ProductsAPIProvider {

func getCatalog(productType: String, page: Int, productsPerPage: Int) { ... }

}

5. Использование интерфейсов для ваших singletons

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

// Before

final class MySingleton {

private init() {}

static let shared = MySingleton()

func someFunction() { ... }

}

// After

protocol MySingletonProtocol {

func someFunction()

}

final class MySingleton: MySingletonProtocol {

private init() {}

static let shared = MySingleton()

func someFunction() { ... }

}

/*** USAGE ***/

final class INeedTheSingleton {

private let theSingleton: MySingletonProtocol

init(theSingleton: MySingletonProtocol = MySingleton.shared) {

self.theSingleton = theSingleton

}

}