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
DispatchQueuepara acceso concurrente - Pruebas: Validar comportamiento en escenarios de tiempo ajustado