How to bind @Published variable value to @propertyWrapper in SwiftUI

63 Views Asked by At

I want to make variable user @Published, but then i get error:

'nil' is not compatible with expected argument type 'Published<UserLoginOutput.Response.Data?

import Foundation

protocol CodableSaving: Codable { }

class UserDefaultsRepository: ObservableObject {
    
    @UserDefault("user_profile", defaultValue: nil)
    @Published var user: UserLoginOutput.Response.Data?
    
    private let encoder = PropertyListEncoder()
    private let decoder = PropertyListDecoder()
    
    subscript<Value: CodableSaving>(index: DefaultKey<Value>) -> Value {
        get {
            if let data = UserDefaults.standard.data(forKey: index.key) {
                do {
                    return try decoder.decode(Value.self, from: data)
                } catch {
                    return index.defaultValue
                }
            }
            return index.defaultValue
        }
        set {
            do {
                let encoded = try encoder.encode(newValue)
                UserDefaults.standard.set(encoded, forKey: index.key)
            } catch {  }
        }
    }
    
    subscript<Value: CodableSaving>(index: DefaultKey<Value?>) -> Value? {
        get {
            if let data = UserDefaults.standard.data(forKey: index.key) {
                do {
                    return try decoder.decode(Value.self, from: data)
                } catch {
                    return index.defaultValue
                }
            }
            return index.defaultValue
        }
        set {
            if let newValue = newValue {
                do {
                    let encoded = try encoder.encode(newValue)
                    UserDefaults.standard.set(encoded, forKey: index.key)
                } catch {  }
            } else {
                UserDefaults.standard.removeObject(forKey: index.key)
            }
        }
    }
}

class DefaultKey<Value>: TypedKey<Value> {
    class var user: DefaultKey<UserLoginOutput.Response.Data?> {
        .init("user", default: nil)
    }
}

class TypedKey<Value> {
    var key: String
    var defaultValue: Value
    
    init(_ key: String, default defaultValue: Value) {
        self.key = key
        self.defaultValue = defaultValue
    }
}

extension TypedKey where Value: ExpressibleByNilLiteral {
    convenience init(_ key: String) {
        self.init(key, default: nil)
    }
}

Thats how my @propertyWrapper looks like:

import Foundation

@propertyWrapper
public struct UserDefault<T> {
    let key: String
    let defaultValue: T

    public init(_ key: String, defaultValue: T) {
        self.key = key
        self.defaultValue = defaultValue
    }

    public var wrappedValue: T {
        get {
            return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }
        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}

My Model:

import Foundation

class UserLoginOutput: Codable {
    var Status: Int?
    var Message: String?
    var Response: Response
    
    class Response: Codable {
        
        var Data: Data
        
        class Data: Codable, CodableSaving {
            var id: String?
            var email: String?
            var password: String?
            var firstname: String?
            var lastname: String?
            var region_id: String?
        }
    }
    
    func getData() -> UserLoginOutput.Response.Data {
        return self.Response.Data
    }
}

I need to make it so I can update the UI. Because to update my UI i need to close my app and then open again my app

0

There are 0 best solutions below