0

My app runs off json for persistent data and i'm trying to use that stored data in my widget.

In my app I use this function to load my data from the FileManager into and ObservableObject like this

class jsonData: ObservableObject {
    @Published var bookData: [Book]
    
    init() {
        self.bookData = Bundle.load("list")
    }
}

extension Bundle {
    static func load<T: Decodable>(_ filename: String) -> T {

        let readURL = Bundle.main.url(forResource: filename, withExtension: "json")!
        let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        
        let jsonURL = documentDirectory
            .appendingPathComponent(filename)
            .appendingPathExtension("json")

        if !FileManager.default.fileExists(atPath: jsonURL.path) {
            try? FileManager.default.copyItem(at: readURL, to: jsonURL)
        }
        return try! JSONDecoder().decode(T.self, from: Data(contentsOf: jsonURL))
    }
}

Which works flawlessly, but when I added the load function to my widget Provider like this:

struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), book: testBook)
    }

    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), book: testBook)
        completion(entry)
    }

    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []
            
        let currentDate = Date()
        for hourOffset in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
            let books = self.load("list") //error here
            let entry = SimpleEntry(date: entryDate, book: testBook)
            entries.append(entry)
        }
            
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
        
    
    }
    
    func load<T: Decodable>(_ filename: String) -> T {
        let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        
        let jsonURL = documentDirectory
            .appendingPathComponent(filename)
            .appendingPathExtension("json")

        return try! JSONDecoder().decode(T.self, from: Data(contentsOf: jsonURL))
    }
}

I get the error Generic parameter 'T' could not be inferred on the line let books = self.load("list") in the getTimeline function.

What I am trying to do is load the entire list of books in list.json and display a random book on the widget.

Arnav Motwani
  • 707
  • 7
  • 26
  • `let books: [Book] = self.load("list")`? Or whatever type it's supposed to be? You might need to help the compiler, because as such, it can't guess what's the return value type, so what's `T` here? Or maybe `let books = load("hello") as [Book]` – Larme May 05 '21 at 14:18
  • @Larme The returned value would be a an array of the struct Book which conforms to Hashable, Codable and Identifiable but yes I see in my original class I did help the compiler out in the Published variable. – Arnav Motwani May 05 '21 at 14:23
  • @Larme that is what I did thanks! – Arnav Motwani May 05 '21 at 15:58

0 Answers0