I am trying to use a completion handler in a view model that assigns values to @Published variables. I get an error stating I cannot use instance members within the property initializer. I tried adding these variables to the class init with no success. If someone could point me in the right direction it would be appreciated. Below is the view model.
class VOOViewModel: ObservableObject {
@Published var isloading: Bool
@Published var vooValues1: [TradingDayPrices]
var vooTempValues1: [TradingDayPrices] = []
let dataContainer: NSPersistentContainer
var vooCompactDataString: String = ""
var vooCompactDataArray: [IndexFund] = []
var vooContainerEmpty: Bool = false
var updatedVOODataAvailable: Bool = false
var latestVOOArrayDate: Date = Date()
var latestVOOContainerDate: Date = Date()
var vooFullDataString: String = ""
var vooFullDataArray: [IndexFund] = []
init() {
isloading = true
vooValues1 = []
dataContainer = NSPersistentContainer(name: "Index Funds")
dataContainer.loadPersistentStores { description, error in
if let error = error {
print("Core Data Failed to Load: \(error.localizedDescription)")
} // end if let
} // end load persistent stores
SetupVOO(using: vooCompletionHandler)
} // end init
let vooCompletionHandler: ([TradingDayPrices], Bool) -> Void = { prices, loadingComplete in
DispatchQueue.main.async {
vooValues1 = prices
// Error = Cannot use instance member 'vooValues1' within property initializer; property initializers run before 'self' is available
isloading = loadingComplete
// Error = Cannot use instance member 'isloading' within property initializer; property initializers run before 'self' is available
}
}
func SetupVOO(using completionHandler: ([TradingDayPrices], Bool) -> Void) {
Task(priority: .userInitiated) {
do {
vooCompactDataString = try await GetOnlineDataAA(urlString: URLStrings.VOOCompact)
vooCompactDataArray = await ConvertStringToArrayAA(stringData: vooCompactDataString)
let vooContainerEmpty = await IsDataContainerEmptyAA(moc: dataContainer.viewContext, fundName: "VOO")
if vooContainerEmpty == true {
updatedVOODataAvailable = true
} else {
latestVOOArrayDate = await GetLatestArrayDateAA(dataArray: vooCompactDataArray)
latestVOOContainerDate = await GetLatestContainerDateAA(moc: dataContainer.viewContext, fundName: "VOO")
if latestVOOArrayDate > latestVOOContainerDate {
updatedVOODataAvailable = true
await DeleteContainerDataAA(moc: dataContainer.viewContext, fundName: "VOO")
} // end if
} // end else
if updatedVOODataAvailable == true {
vooFullDataString = try await GetOnlineDataAA(urlString: URLStrings.VOOFull)
vooFullDataArray = await ConvertStringToArrayAA(stringData: vooFullDataString)
await UpdatePersistentStoreAA(moc: dataContainer.viewContext, fundName: "VOO", dataArray: vooFullDataArray)
await NormalizeDatesAA(moc: dataContainer.viewContext, numYears: 1, latestDate: latestVOOArrayDate, fundName: "VOO")
await NormalizeDatesAA(moc: dataContainer.viewContext, numYears: 5, latestDate: latestVOOArrayDate, fundName: "VOO")
await NormalizeClosingValuesAA(moc: dataContainer.viewContext, numYears: 1, latestDate: latestVOOArrayDate, fundName: "VOO")
await NormalizeClosingValuesAA(moc: dataContainer.viewContext, numYears: 5, latestDate: latestVOOArrayDate, fundName: "VOO")
} // end if statement
vooTempValues1 = await FetchContainerValuesAA(moc: dataContainer.viewContext, numYears: 1, latestDate: latestVOOArrayDate, fundName: "VOO")
} catch {
print("Error getting VOO data")
} // end catch
} // end task
completionHandler(vooTempValues1, false)
} // end func
} // end class
The easiest way to fix this is to make vooCompletionHandler
into a function:
func vooCompletionHandler(prices: [TradingDayPrices], loadingComplete: Bool) {
DispatchQueue.main.async {
vooValues1 = prices
isloading = loadingComplete
}
}
You'd use the function the same way in SetupVOO(using: vooCompletionHandler)