Создание обёрток, projectedValue
Создайте пользовательскую обёртку, настройте wrappedValue и предоставьте метаданные и вспомогательные функции через projectedValue ( $ ).
«Создание обёрток, projectedValue» — бесплатный урок Swift Academy на CoddyKit. Это урок 1 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 3 уроков всего.
Зачем нужны обёртки свойств?
Обёртка свойства — это повторно используемый тип, управляющий тем, как свойство хранится и читается:
- wrappedValue: общедоступное значение
- projectedValue: дополнительный программный интерфейс через
$ - Настройка через инициализаторы и аргументы
Clamped и флаг projectedValue
@Clamped ограничивает число диапазоном. projectedValue ($hp) сообщает, было ли последнее присваивание ограничено диапазоном.
@propertyWrapper
struct Clamped {
private var value: Int
private let range: ClosedRange<Int>
private(set) var wasClampedLastSet = false
var wrappedValue: Int {
get { value }
set {
let clamped = min(max(newValue, range.lowerBound), range.upperBound)
wasClampedLastSet = (clamped != newValue)
value = clamped
}
}
var projectedValue: Bool { wasClampedLastSet } // $prop -> was it clamped?
init(wrappedValue: Int, range: ClosedRange<Int>) {
self.range = range
let clamped = min(max(wrappedValue, range.lowerBound), range.upperBound)
self.value = clamped
self.wasClampedLastSet = (clamped != wrappedValue)
}
}
struct Player {
@Clamped(range: 0...100) var hp: Int = 120 // init clamps to 100
}
var p = Player()
print(p.hp) // 100
p.hp = -5
print(p.hp, p.$hp) // 0 true (was clamped)Нормализация и альтернативное представление
Обёртки могут преобразовывать входные данные (убирать пробелы и переводить текст в нижний регистр). $property может предоставлять удобную альтернативную форму.
@propertyWrapper
struct Normalized {
private var storage: String = ""
var wrappedValue: String {
get { storage }
set { storage = newValue.trimmingCharacters(in: .whitespacesAndNewlines).lowercased() }
}
var projectedValue: String { storage.uppercased() } // alternate view
init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}
struct User {
@Normalized var username: String = " Alice "
}
let u = User()
print(u.username) // "alice"
print(u.$username) // "ALICE" (projected)Настраиваемая обёртка
Передавайте обёрткам аргументы (например, длину). Обёртка применяет форматирование при каждом присваивании свойства.
@propertyWrapper
struct Padded {
private var value: String
private let length: Int
var wrappedValue: String {
get { value }
set {
let s = newValue
value = s.count >= length ? String(s.prefix(length))
: s + String(repeating: " ", count: length - s.count)
}
}
var projectedValue: Int { value.count } // current width
init(wrappedValue: String, length: Int) {
self.length = length
self.value = ""
self.wrappedValue = wrappedValue
}
}
struct Row {
@Padded(length: 6) var code: String = "AB"
}
var r = Row()
print("|\(r.code)|") // |AB |
print(r.$code) // 6History через $value
Используйте projectedValue, чтобы предоставлять метаданные, например историю изменений, не перегружая основной программный интерфейс значения.
@propertyWrapper
struct History<Value> {
private var value: Value
private(set) var changes: [Value] = []
var wrappedValue: Value {
get { value }
set { changes.append(value); value = newValue }
}
var projectedValue: [Value] { changes } // $prop -> previous values
init(wrappedValue: Value) { self.value = wrappedValue }
}
struct Settings {
@History var level: Int = 1
}
var s = Settings()
s.level = 2
s.level = 3
print(s.level) // 3
print(s.$level) // [1, 2]Рекомендации по проектированию
Советы:
- Делайте обёртки небольшими и специализированными.
- Документируйте, что предоставляет $projectedValue.
- Отдавайте предпочтение чистым преобразованиям; избегайте тяжёлых побочных эффектов.
- Предоставляйте понятные инициализаторы и разумные значения по умолчанию.
Назначение projectedValue
Быстрая проверка: для чего используется $property в обёртках?
Итоги
Итоги: реализуйте @propertyWrapper с помощью wrappedValue; предоставляйте помощники, флаги и историю через projectedValue ($), а поведение настраивайте с помощью инициализаторов.
Часто задаваемые вопросы
Урок «Создание обёрток, projectedValue» бесплатный?
Да — полный текст урока «Создание обёрток, projectedValue» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 3 уроков всего.
Чему я научусь в уроке «Создание обёрток, projectedValue»?
Создайте пользовательскую обёртку, настройте wrappedValue и предоставьте метаданные и вспомогательные функции через projectedValue ( $ ). Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 3.
Сколько времени занимает урок «Создание обёрток, projectedValue»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Создание обёрток, projectedValue
- Повторное использование и ограничения
- Распространённые шаблоны обёрток (проверка, кэширование)