Hello!
As the title suggests i'm creating a JSON file in my app and then i'd like the home screen Widget to read that file to populate the widget. It seems like the file is being written OK because I write the file and then for debugging I read it and print it in the console.
I write to the JSON like this:
struct WidgetMetric: Codable {
var JSON_slug: String
var JSON_currency: String
var JSON_TotalRevenue: Double
var JSON_MissedRevenue: Int
var JSON_RevenueProjection: Double
var JSON_revenuePercent: Double
var JSON_revenueDirection: Int
var JSON_VisitValueProjection: Double
var JSON_VisitValuePercent: Double
var JSON_VisitValueDirection: Int
var JSON_TransValueProjection: Double
var JSON_TransValuePercent: Double
var JSON_TransValueDirection: Int
var JSON_DurationMonths: Int
}
func WidgetJSONGeneration(slug: String, currency: String, TotalRevenue: Double, MissedRevenue: Int, RevenueGrowth: Double, revenuePercent: Double, revenueDirection: Int, VisitValue: Double, VisitValuePercent: Double, VisitValueDirection: Int, TransValue: Double, TransValuePercent: Double, TransValueDirection: Int, DurationMonths: Int) async -> String {
let widgetMetrics = [
WidgetMetric(
JSON_slug: slug,
JSON_currency: currency,
JSON_TotalRevenue: TotalRevenue,
JSON_MissedRevenue: MissedRevenue,
JSON_RevenueProjection: RevenueGrowth,
JSON_revenuePercent: revenuePercent,
JSON_revenueDirection: revenueDirection,
JSON_VisitValueProjection: VisitValue,
JSON_VisitValuePercent: VisitValuePercent,
JSON_VisitValueDirection: VisitValueDirection,
JSON_TransValueProjection: TransValue,
JSON_TransValuePercent: TransValuePercent,
JSON_TransValueDirection: TransValueDirection,
JSON_DurationMonths: DurationMonths
)
]
// Encode the array as JSON data
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let jsonData = try! encoder.encode(widgetMetrics)
// Write the JSON data to a file
let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("mobData.json")
try! jsonData.write(to: fileUrl)
print("mob: WidgetJSONGeneration. JSON file URL:")
print(fileUrl)
return("JSONGenerated")
}
And to test I read it like this. the JSON displays OK.
func readJSON() -> [WidgetMetric]? {
print("")
print("mob. ConnectToMob: Generated JSON:")
print("")
let fileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("mobData.json")
do {
let data = try Data(contentsOf: fileUrl)
let decoder = JSONDecoder()
let widgetMetrics = try decoder.decode([WidgetMetric].self, from: data)
return widgetMetrics
} catch {
print("Error reading JSON file: \(error.localizedDescription)")
return nil
}
}
Then in my home screen Widget I basically use the same code to read the JSON as follows
func readJSON() -> [WidgetMetric]? {
print("")
print("mob. Mob_Widget: JSON found:")
print("")
let fileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("mobData.json")
do {
let data = try Data(contentsOf: fileUrl)
let decoder = JSONDecoder()
let widgetMetrics = try decoder.decode([WidgetMetric].self, from: data)
// Refresh the widget content
//WidgetCenter.shared.reloadAllTimelines()
return widgetMetrics
} catch {
print("Error reading JSON file: \(error.localizedDescription)")
print("JSON file URL: \(fileUrl)")
return nil
}
But when the widget tries to read the file I get the error:
Impossible to open the file because it does not exist
Thats because the fileUrl in the app and the widget are different. If I look at the fileUrl when the JSON is created in the main app it's:
file:///Users/jas/Library/Developer/CoreSimulator/Devices/AB0B8C29-139F-493A-AEE3-0C744D331F03/data/Containers/Data/Application/EB432EE6-2983-46FF-995B-63F9F79877D1/Documents/mobData.json
and the fileUrl in the home screen Widget is:
file:///Users/jas/Library/Developer/CoreSimulator/Devices/AB0B8C29-139F-493A-AEE3-0C744D331F03/data/Documents/mobData.json
So in summary, that's a long way of asking why is the fileUrl in the app and the widget different?
Thanks for any advice! :)