0Pricing
Swift Academy · Aula

Padrões comuns de wrappers (validação, armazenamento em cache)

Crie wrappers comuns de validação e armazenamento em cache : valide a entrada, forneça valores padrão, memorize operações dispendiosas e disponibilize sinalizadores auxiliares por meio de valores projetados.

Padrões comuns de wrappers (validação, armazenamento em cache) é uma aula grátis de Swift Academy no CoddyKit. Esta é a aula 3 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Swift Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Swift Academy inclui 3 aulas no total.

O que vamos construir

Esta lição apresenta dois padrões práticos:

  • Validação: aceite ou corrija entradas usando valores padrão e mensagens.
  • Armazenamento em cache: armazene resultados e disponibilize $helpers como clear() e isCached.

Validação: NonEmpty

@NonEmpty impede entradas vazias e fornece um valor padrão. O projectedValue informa se o último valor definido foi corrigido automaticamente.

@propertyWrapper
struct NonEmpty {
    private var value: String = ""
    private(set) var lastFixed: Bool = false

    var wrappedValue: String {
        get { value }
        set {
            if newValue.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
                value = "N/A"          // default fallback
                lastFixed = true
            } else {
                value = newValue
                lastFixed = false
            }
        }
    }

    var projectedValue: Bool { lastFixed } // $name -> was fixed?

    init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}

struct Profile {
    @NonEmpty var displayName: String = "  "
}
var p = Profile()
print(p.displayName)  // "N/A"
print(p.$displayName) // true (was fixed)

Validação: baseada em regras

@Validated é genérico e aceita um fechamento de regra e um valor alternativo. Use-o para verificações de comprimento, intervalo ou personalizadas.

@propertyWrapper
struct Validated<Value> {
    private var value: Value
    private let rule: (Value) -> Bool
    private let fallback: Value
    private(set) var lastValid: Bool = true

    var wrappedValue: Value {
        get { value }
        set {
            if rule(newValue) {
                value = newValue
                lastValid = true
            } else {
                value = fallback
                lastValid = false
            }
        }
    }

    var projectedValue: Bool { lastValid } // $prop -> is valid?

    init(wrappedValue: Value, rule: @escaping (Value) -> Bool, fallback: Value) {
        self.rule = rule
        self.fallback = fallback
        self.value = wrappedValue
        self.lastValid = rule(wrappedValue)
        if !lastValid { self.value = fallback }
    }
}

struct Form {
    @Validated(rule: { $0.count >= 3 }, fallback: "???")
    var nickname: String = "hi"
}
var f = Form()
print(f.nickname)   // "???" (invalid -> fallback)
print(f.$nickname)  // false

Armazenamento em cache: memorização preguiçosa

@LazyCached memoriza um valor obtido de um fechamento. $result disponibiliza os auxiliares isCached e clear().

@propertyWrapper
struct LazyCached<Value> {
    private var storage: Value?
    private let build: () -> Value

    var wrappedValue: Value {
        mutating get {
            if let v = storage { return v }         // hit
            let v = build()                         // miss -> compute
            storage = v
            return v
        }
        // Optional: allow manual set to override cache
        set { storage = newValue }
    }

    struct Controls {
        private let getter: () -> Bool
        private let clearer: () -> Void
        var isCached: Bool { getter() }
        func clear() { clearer() }
    }

    var projectedValue: Controls {
        Controls(
            getter: { self.storage != nil },
            clearer: { self.storage = nil }
        )
    }

    init(_ build: @escaping () -> Value) {
        self.build = build
        self.storage = nil
    }
}

// Demo: expensive computation (simulated)
var calls = 0
func heavy() -> Int { calls += 1; return (1...10_000).reduce(0, +) }

struct Engine {
    @LazyCached(heavy) var result: Int
}
var e = Engine()
print(e.$result.isCached) // false
print(e.result)           // computes once
print(e.result)           // uses cache
print(calls)              // 1

Armazenamento em cache: baseado em TTL

@TimedCache atualiza o valor após um TTL. O valor projetado pode disponibilizar age, permitindo que os pontos de chamada decidam quando atualizar.

@propertyWrapper
struct TimedCache<Value> {
    private var storage: Value?
    private var timestamp: Date?
    private let ttl: TimeInterval
    private let build: () -> Value

    var wrappedValue: Value {
        mutating get {
            let now = Date()
            if let t = timestamp, let v = storage, now.timeIntervalSince(t) < ttl {
                return v                              // fresh
            }
            let v = build()                           // refresh
            storage = v
            timestamp = now
            return v
        }
    }

    struct Status { let age: TimeInterval? }
    var projectedValue: Status {
        let age = timestamp.map { Date().timeIntervalSince($0) }
        return Status(age: age)
    }

    init(ttl: TimeInterval, _ build: @escaping () -> Value) {
        self.ttl = ttl
        self.build = build
    }
}

// Demo (age only; TTL behavior depends on real time)
struct Stats {
    @TimedCache(ttl: 60) { Int.random(in: 0...1000) } var score: Int
}
var s2 = Stats()
print(s2.score)         // computes
print(s2.$score.age ?? -1)

Diretrizes de projeto

Dicas de projeto:

  • Mantenha a validação pura e previsível; informe as correções com $flags.
  • Para o armazenamento em cache, mantenha o estado pequeno; forneça clear() ou isCached.
  • Prefira argumentos de init para políticas (valores alternativos, TTL).

Auxiliares projetados para armazenamento em cache

Verificação rápida: o que $value deve disponibilizar em um envoltório de armazenamento em cache?

Recapitulação

Recapitulação: use envoltórios para validar entradas (valores padrão, regras) e para armazenar em cache resultados dispendiosos (memorização preguiçosa, TTL). Coloque o controle e o status em projectedValue para obter pontos de chamada limpos.

Perguntas Frequentes

A aula “Padrões comuns de wrappers (validação, armazenamento em cache)” é grátis?

Sim — o texto completo de “Padrões comuns de wrappers (validação, armazenamento em cache)” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Swift Academy, atualize para CoddyKit PRO. O curso de Swift Academy inclui 3 aulas no total.

O que vou aprender em “Padrões comuns de wrappers (validação, armazenamento em cache)”?

Crie wrappers comuns de validação e armazenamento em cache : valide a entrada, forneça valores padrão, memorize operações dispendiosas e disponibilize sinalizadores auxiliares por meio de valores pro… Você pratica Swift Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Swift Academy?

Nenhuma experiência prévia é necessária. Swift Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 3.

Quanto tempo leva a aula “Padrões comuns de wrappers (validação, armazenamento em cache)”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Swift Academy?

Sim. Cada aula de Swift Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Criando wrappers, projectedValue
  2. Reutilização e restrições
  3. Padrões comuns de wrappers (validação, armazenamento em cache)
← Voltar para Swift Academy