0Pricing
Swift Academy · Lekcja

Możliwość ponownego użycia i ograniczenia

Projektuj generyczne wrappery z ograniczeniami typów (np. Value: Comparable ), dodawaj ukierunkowane API za pomocą where i łącz wiele wrapperów.

Możliwość ponownego użycia i ograniczenia to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 2 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 3 lekcji w sumie.

Po co ograniczenia typów

Utwórz jeden wrapper i używaj go ponownie dla wielu typów, czyniąc go generycznym za pomocą ograniczeń. Dodawaj wyspecjalizowane API z klauzulami where i twórz kompozycje z małych wrapperów.

Typ generyczny + Comparable

Użyj Comparable, aby jeden Bounded działał dla typów Int, String itd. Nieprawidłowe typy są odrzucane podczas kompilacji.

@propertyWrapper
struct Bounded<Value: Comparable> {
    private var value: Value
    private let range: ClosedRange<Value>

    var wrappedValue: Value {
        get { value }
        set {
            // clamp using Comparable
            if newValue < range.lowerBound { value = range.lowerBound }
            else if newValue > range.upperBound { value = range.upperBound }
            else { value = newValue }
        }
    }

    init(wrappedValue: Value, _ range: ClosedRange<Value>) {
        self.range = range
        self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
    }
}

struct Stats {
    @Bounded(0...100) var score: Int = 120
    @Bounded("a"..."z") var letter: String = "Swift"
}
var st = Stats()
print(st.score)   // 100
st.letter = "m"
print(st.letter)

Rozszerzenia z ograniczeniami

Użyj where, aby udostępniać dodatkowe elementy tylko wtedy, gdy typ je obsługuje, na przykład flagi całkowitoliczbowe lub aktualizacje wartości zmiennoprzecinkowych.

extension Bounded where Value: BinaryInteger {
    var isMaxed: Bool { wrappedValue == range.upperBound }
}
extension Bounded where Value: FloatingPoint {
    mutating func bump(by delta: Value) { wrappedValue = wrappedValue + delta }
}

struct Meter {
    @Bounded(0...10) var steps: Int = 9
    @Bounded(0.0...1.0) var progress: Double = 0.25
}
var m = Meter()
print(m.$steps)          // projectedValue not defined; accessing wrapper is not allowed directly here
print(m._steps)          // compiler creates backing storage name; shown for illustration only
print(m.steps)           // 9
print(m._progress)       // backing storage (illustrative)
m._progress.bump(by: 0.6)
print(m.progress)        // 0.85 (clamped if exceeded)

Wrapper tylko dla kolekcji

Ogranicz API do kolekcji, stosując ograniczenie do RangeReplaceableCollection. Działa dla typów String i Array.

@propertyWrapper
struct MaxLength<Value: RangeReplaceableCollection> where Value.Element: Sendable {
    private var storage: Value
    private let limit: Int

    var wrappedValue: Value {
        get { storage }
        set {
            var v = newValue
            if v.count > limit { v.removeLast(v.count - limit) }
            storage = v
        }
    }

    init(wrappedValue: Value, _ limit: Int) {
        self.limit = limit
        self.storage = wrappedValue
        if storage.count > limit { storage.removeLast(storage.count - limit) }
    }
}

struct Post {
    @MaxLength(10) var title: String = "hello swift learners"
    @MaxLength(5) var tags: [String] = ["swift","ios","spm"]
}
var p = Post()
print(p.title)  // "hello swif"
print(p.tags)   // ["swift","ios","spm"]

Kompozycja wrapperów

Możesz układać małe wrappery warstwowo. W tym przypadku Trimmed działa jako pierwszy, a następnie NonEmpty zapewnia wartość zastępczą.

@propertyWrapper
struct Trimmed {
    private var s: String = ""
    var wrappedValue: String {
        get { s }
        set { s = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
    }
    init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}

@propertyWrapper
struct NonEmpty {
    private var s: String = ""
    var wrappedValue: String {
        get { s }
        set { s = newValue.isEmpty ? "N/A" : newValue }
    }
    init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}

struct Profile {
    @NonEmpty @Trimmed var displayName: String = "  "
}
var prof = Profile()
print(prof.displayName)  // "N/A"

Zmienne lokalne + ponowne użycie

Wrappery działają także dla zmiennych lokalnych. Zachowaj ich generyczność, aby można było ponownie używać ich w różnych modułach.

@propertyWrapper
struct Default<Value> {
    private var value: Value
    private let make: () -> Value
    var wrappedValue: Value {
        get { value }
        set { value = newValue }
    }
    init(wrappedValue: Value, _ factory: @escaping () -> Value) {
        self.value = wrappedValue
        self.make = factory
    }
    mutating func reset() { value = make() }
}

// Local variable usage
do {
    @Default({ 0 }) var counter: Int = 5
    print(counter) // 5
    _counter.reset()
    print(counter) // 0
}

Ograniczenie wrappera sprawdzane podczas kompilacji

Szybkie sprawdzenie: Jak ograniczyć wrapper do typów zgodnych z Comparable?

Podsumowanie

Podsumowanie: Twórz wrappery generyczne, dodawaj ograniczenia, aby zapewnić bezpieczne użycie, udostępniaj ukierunkowane API za pomocą klauzul where i łącz małe wrappery dla większej przejrzystości.

Często zadawane pytania

Czy lekcja „Możliwość ponownego użycia i ograniczenia” jest bezpłatna?

Tak — pełny tekst „Możliwość ponownego użycia i ograniczenia” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 3 lekcji w sumie.

Co nauczysz się w „Możliwość ponownego użycia i ograniczenia”?

Projektuj generyczne wrappery z ograniczeniami typów (np. Value: Comparable ), dodawaj ukierunkowane API za pomocą where i łącz wiele wrapperów. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Swift Academy?

Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 3.

Ile czasu zajmuje lekcja „Możliwość ponownego użycia i ograniczenia”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?

Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tworzenie wrapperów, projectedValue
  2. Możliwość ponownego użycia i ograniczenia
  3. Typowe wzorce wrapperów (walidacja, buforowanie)
← Powrót do Swift Academy