Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optional @ObservableObject in SwiftUI

I want to have an optional @ObservedObject in SwiftUI but I keep getting a compile time error of.

Property type 'AModel?' does not match that of the 'wrappedValue' property of its wrapper type 'ObservedObject'

Here is some minimum reproducible code.

import SwiftUI

public struct AView: View {
    
    //MARK: View Model
    //Error thrown here.
    @ObservedObject var model: AModel?
    
    //MARK: Body
    public var body: some View {
        Text("\(model?.value ?? 0)")
    }
    
    //MARK: Init
    public init() {
        
    }
    
}

class AModel: ObservableObject {
    let value: Int = 0
}
like image 499
Jon Vogel Avatar asked Apr 12 '21 18:04

Jon Vogel


2 Answers

The technical reason is that Optional is not a class, so it cannot be conformed to ObservableObject.

But if you want to avoid refactoring the object itself - for example, if it's not in your control - you could do something like this:

struct AView: View {

    private struct Content: View {
       @ObservedObject var model: AModel
       var body: some View {
          Text("\(model.value)")
       }
    }

    var model: AModel?
    
    var body: some View {
       if let model = model {
          Content(model: model)
       } else {
          Text("0")
       }
    }    
}
like image 176
New Dev Avatar answered Oct 16 '22 19:10

New Dev


You actually want your init argument to be optional, not the struct property. In your case I would simply do:

import SwiftUI

public struct AView: View {
    
    //MARK: View Model
    @ObservedObject var model: AModel
    
    //MARK: Body
    public var body: some View {
        Text("\(model.value)")
    }
    
    //MARK: Init
    public init(model: AModel? = nil) {
        self.model = model ?? AModel()
    }
    
}

class AModel: ObservableObject {
    let value: Int = 0
}

like image 43
melMass Avatar answered Oct 16 '22 17:10

melMass