0

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

5
  • Why do you need to do this when there is @AppStorage? Commented Oct 25, 2023 at 8:20
  • because i need to save my custom object from network Commented Oct 25, 2023 at 8:41
  • What's so special about your custom object? As far as I can see, it conforms to Codable, which @AppStorage supports. Commented Oct 25, 2023 at 8:45
  • i made that @Inject private var userRepository: UserDefaultsRepository and then i use this case .success(let response): userRepository[.user] = response.getData() Commented Oct 25, 2023 at 8:46
  • Use AppStorage that property wrapper does not have the ability to notify SwiftUI of changes. Also know that AppStorage is the most insecure and unreliable type of storage it is meant for small things like settings. You shouldn’t have anything sensitive there. Commented Oct 25, 2023 at 9:47

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.