Implementación avanzada de wrappers de propiedad en Swift: @Expirable y @LateInit para escenarios reales

Introducción técnica

Los wrappers de propiedad personalizados ofrecen una forma declarativa para extender el comportamiento de propiedades en Swift. Dos implementaciones destacadas en la biblioteca Burritos son @Expirable y @LateInit, diseñadas para resolver patrones comunes con mayor eficiencia.

@Expirable: Gestión automática de caducidad

Este wrapper permite definir proipedades con tiempo de vida limitado, ideal para datos sensibles a la vigencia:

  • Tokens de autenticación
  • Cachés con validez temporal
  • Datos de sesión

Ejemplo de implementación

struct AuthManager {
    @Expirable(timeout: 3600.0) var sessionToken: String?
    @Expirable(expirationDate: Date().addingTimeInterval(604800)) var refreshToken: String?

    mutating func fetchNewTokens() {
        let response = APIClient.authenticate()
        sessionToken = response.token
        refreshToken = response.refreshToken
    }

    func isTokenActive() -> Bool {
        return sessionToken != nil && _sessionToken.isValid
    }
}

@LateInit: Inicialización diferida segura

Resuelve el requisito de inicialización inmediata de propiedades almacenadas, permitiendo configuración dinámica:

  • Dependencias inyectadas
  • Configuración posterior a la creación
  • Resolución de dependencias circulares

Casos de uso práctico

class ProfileScreenController: UIViewController {
    @LateInit var userProvider: UserDataProvider
    @LateInit var analyticsTracker: AnalyticsTracker

    func setupDependencies(with provider: DependencyProvider) {
        userProvider = provider.userProvider
        analyticsTracker = provider.analytics
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        displayProfile()
    }

    private func displayProfile() {
        let profile = userProvider.fetchCurrentProfile()
        analyticsTracker.trackScreenView("Profile")
    }
}

Técnicas avanzadas

Configuración personalizada de caducidad

struct SubscriptionStatus {
    @Expirable(
        expirationDate: Calendar.current.date(byAdding: .month, value: 3, to: Date())!,
        timeout: 2592000
    ) var status: String

    mutating func updateStatus(_ newStatus: String, validUntil: Date) {
        status = newStatus
        _status.setExpiration(validUntil)
    }
}

Patrón de acceso seguro para @LateInit

class ServiceManager {
    @LateInit var coreService: CoreService

    var isConfigured: Bool {
        return _coreService.storage != nil
    }

    func executeOperation() {
        guard isConfigured else { return }
        coreService.processData()
    }
}

Consideraciones de rendimiento

  • Gestión de memoria: Limpiar datos caducados mediante expirationHandler
  • Seguridad de subprocesos: Implementar DispatchQueue para acceso concurrente
  • Pruebas: Validar comportamiento en escenarios de tiempo ajustado

Etiquetas: Swift Property Wrappers Delayed Initialization Expiry Management dependency injection Swift 5.7

Publicado el 9-23 11:20