3

I use Realm + SwiftUI 2.0, iOS 14. I successfully linked (read/write) Realm to Swift 2.0 iOS app.

final class DataEntryStore: ObservableObject {
    
    private var entryCancellable: AnyCancellable?
    private(set) var entryDB = DataObservable<Entry>()
    // could store related references to other related DataObservables
    
    @Published private(set) var entries: [Entry] = []
    
    // MARK: - init
    init() {
        entryDB = DataObservable<Entry>()
        entryCancellable = entryDB.$items.assign(to: \.entries, on: self)
    }
}

class RealmEntry: Object, UUIDIdentifiable {
    @objc dynamic var id: String = UUID().uuidString
    @objc dynamic var entryType = ""
    @objc dynamic var entryDate = Date()
    @objc dynamic var note: String?
    @objc dynamic var trainingType: String?
    @objc dynamic var trainingTime = 0
    
    override static func primaryKey() -> String? {
        return "id"
    }
}

// MARK: - Abstracted Data Struct which is what is presented with the UI

// UI Model
struct Entry: Hashable, RealmConvertible {
    typealias RealmType = RealmEntry
    
    // MARK: - Properties
    
    var id: String
    var entryType: DataEntryType
    var entryDate: Date
    var note: String?
    var trainingType: TrainingType?
    var trainingTime: Int

    func toRealmObject() -> RealmEntry {
        let realmObj = RealmEntry()
        
        realmObj.id = id
        realmObj.entryType = entryType.rawValue
        realmObj.entryDate = entryDate
        realmObj.note = note
        
        if let trainingTypeValue = trainingType?.rawValue {
            realmObj.trainingType = trainingTypeValue
        }
        realmObj.trainingTime = trainingTime
        
        return realmObj
    }

    static func fromRealmObject(_ obj: RealmEntry) -> Entry {
        Entry(obj)
    }
    
    init() {
        self.id = UUID().uuidString
        self.entryType = .note
        self.entryDate = Date()
        self.trainingTime = 0
    }
    
    init(_ obj: RealmEntry) {
        self.id = obj.id
        self.entryType = DataEntryType(fromRawValue: obj.entryType)
        self.entryDate = obj.entryDate
        self.note = obj.note
        if let trainingType = obj.trainingType {
            self.trainingType = TrainingType(fromRawValue: trainingType)
        }
        self.trainingTime = obj.trainingTime
    }
}

protocol StringIdentifiable {
    var id: String { get }
}

protocol UUIDIdentifiable: Identifiable { var id: String { get } }
//protocol Initializable { init() }

// MARK: - Map Between the Two

protocol RealmConvertible where Self: Equatable & UUIDIdentifiable {
    associatedtype RealmType: Object & UUIDIdentifiable
    
    func toRealmObject() -> RealmType
    init(_ dest: RealmType)
}

// Dynamic Realm Binding for live data editing

extension RealmConvertible {
    func realmBinding() -> Binding<Self> {
        let h = RealmHelper()
        return Binding<Self>(get: {
            if let r = h.get(self.toRealmObject()) {
                // get the latest realm version for most uptodate data and map back to abstracted structs on init
                return Self(r)
            } else {
                // otherwise return self as it's the most uptodate version of the data struct
                return self
            }
        }, set: h.updateConvertible)
    }
}

However, I am having an issue when tried to link (read) it to Widget Extension.

@main
struct MyWidget: Widget {
    let kind = "MyWidget"

    var body: some WidgetConfiguration { IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            WidgetView()
        }
        .supportedFamilies([.systemSmall, .systemMedium])
        .configurationDisplayName("My Widget")
        .description("This is widget.")
    }
}

struct WidgetView: View {
    @EnvironmentObject var data: DataEntryStore
    
    var body: some View {
        Text(data.getRealmData)
        ViewWithRealmDataFromMainApp()
    }
}

I have tried to follow these instructions by using "App Groups" and Shared Objects to Main iOS App and to Widget Extension, but it didn't work.

More than that, if I link it to Realm, I can't even show static data on the widget. It shows blurry rectangles.

How to show data from the Realm on the iOS 14 widget?

https://i.stack.imgur.com/yzUG1.jpg https://i.stack.imgur.com/nKy6i.jpg

pawello2222
  • 46,897
  • 22
  • 145
  • 209
Anton IOS
  • 39
  • 2
  • 1
    I don't think you can use your DataEntryStore like that in your Widget. You need to pass all the data to your Widget in the form of an SimpleEntry (like in the example widget when you first create the extension). The data for the SimpleEntry should be collected and passed in the TimelineProvider. Widgets are static and you cannot access data from somewhere else, they can only show what is passed to them. – Andrew Nov 24 '20 at 11:13
  • @Andrew Yes, I'm using SimpleEntry, but this is for TimelineEntry and TimelineProvider. How do I transfer the whole database here? – Anton IOS Dec 01 '20 at 10:47

0 Answers0