Я уже 2 месяца прохожу обучение в онлайн‑школе и у нас на этой неделе был открытый урок, нужно было подготовить доклад на тему «Малоизвестные фичи или особенности языка Swift»
Так вот — я решила погуглить этот вопрос, подготовилась, написала код. Но когда дело дошло до самого выступления, оказалось, что говорить ртом — это не так‑то и просто. Да и в целом выступать, даже в Zoom.
Тем не менее, поделюсь с вами маленькими фишечками, которые я нашла. Уровень легкий, в отличие от меня там ребята подготовили нормальные доклады про SPM и пр. Я же решила начать с простых вещей, которые, тем не менее, мне были неизвестны. Надеюсь кому‑то тоже окажется полезным.
Property Wrappers (Обертки для свойств)
Обертки позволяют добавлять функциональность к свойствам (таким как @State, @Binding и др.)
Например мы хотим создать обертку, которая автоматически будет делать все буквы заглавными:
@propertyWrapper
struct Capitalized {
private var value: String = ""
var wrappedValue: String {
get { value.uppercased() }
set { value = newValue }
}
}
struct User {
@Capitalized var name: String
}
var user = User()
user.name = "alice"
print(user.name) // ALICE
// Свойство name автоматически преобразуется
// к верхнему регистру благодаря обертке Capitalized
Opaque Types и some (Непрозрачные типы)
В данном примере some используется для указания типа результата функции, не раскрывая его конкретного типа. Это упрощает возврат типов из функций и скрывает внутреннюю реализацию.
protocol Shape {
func area() -> Double
}
struct Circle: Shape {
var radius: Double
func area() -> Double {
return .pi * radius * radius
}
}
func createShape() -> some Shape {
return Circle(radius: 5)
}
let shape = createShape()
print(shape.area()) // 78.54
// Использование some Shape позволяет скрыть
// конкретную реализацию Circle, возвращая объект как общий Shape.
Key Paths
С помощью Key Paths мы можем ссылаться на свойства объектов и структур без необходимости явно писать их имена. Например можно создать массив и отсортировать его по свойству.
struct Person {
let name: String
let age: Int
}
let people = [
Person(name: "Alice", age: 25),
Person(name: "Bob", age: 30),
Person(name: "Charlie", age: 22)
]
// Функция, которая сортирует массив по любому свойству с помощью KeyPath
func sortBy<T>(array: [T], keyPath: KeyPath<T, Int>) -> [T] {
return array.sorted { $0[keyPath: keyPath] < $1[keyPath: keyPath] }
}
let sortedByAge = sortBy(array: people, keyPath: \.age)
print(sortedByAge) // Charlie, Alice, Bob
// Здесь мы передаем свойство для сортировки как параметр
Dynamic Member Lookup (Динамический доступ к членам)
Атрибут @dynamicMemberLookup позволяет обращаться к свойствам объекта по имени, которое определяется в рантайме. Особенно интересно его использовать при работе с JSON или динамическими объектами. Например:
@dynamicMemberLookup
struct JSONWrapper {
private var data: [String: Any]
init(data: [String: Any]) {
self.data = data
}
subscript(dynamicMember member: String) -> Any? {
return data[member]
}
}
let json = JSONWrapper(data: ["name": "Alice", "age": 25])
print(json.name) // Alice
print(json.age) // 25
// Обращаемся к элементам словаря не зная заранее их типов
На этом всё, иду дописывать 3 часть статьи про переход на SwiftUI.
Проект добавила на GitHub
(не реклама, курсы прохожу в школе OTUS, если интересно, iOS Developer. Professional)