Декодирование json из файлового менеджера — WidgetKit

#json #swift #swiftui #codable #widgetkit

Вопрос:

Мое приложение запускает json для постоянных данных, и я пытаюсь использовать эти сохраненные данные в своем виджете.

В моем приложении я использую эту функцию для загрузки моих данных из файлового менеджера в объект и объект наблюдения, как это

 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))
    }
}
 

Который работает безупречно, но когда я добавил функцию загрузки к своему поставщику виджетов, как это:

 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))
    }
}
 

Я получаю ошибку Generic parameter 'T' could not be inferred в строке let books = self.load("list") в функции getTimeline.

То, что я пытаюсь сделать, это загрузить весь список книг в list.json и отобразить случайную книгу в виджете.

Комментарии:

1. let books: [Book] = self.load("list") ? Или какого там типа это должно быть? Возможно, вам потребуется помочь компилятору, потому что, как таковой, он не может угадать, какой тип возвращаемого значения, так что же T здесь? Или, может быть, let books = load("hello") as [Book]

2. @Larme Возвращаемое значение будет представлять собой массив структурной книги, который соответствует Хэшируемому, кодируемому и идентифицируемому, но да, я вижу, что в моем исходном классе я помог компилятору в опубликованной переменной.

3. @Larme это то, что я сделал, спасибо!