如何为加载的Json数据创建Core Data对象?

2izufjch  于 2022-11-19  发布在  其他
关注(0)|答案(1)|浏览(97)

我 试图 弄 清楚 如何 从 Json 数据 ( 由 Financial Modeling Prep 提供 ) 创建 Core Data 对象 。
应用 程序 的 结构 如下 :

  • 具有 如下 函数 的 API _ SERVICE 类 :
func readJsonIncomeStatementFMP(keywords: String) -> AnyPublisher<[IncomeStatementFMP], Error>  {

        let result = parseQuery(text: keywords)
        var symbol = String()
        
        switch result {
        case .success(let query):
            symbol = query
        case .failure(let error):
            return Fail(error: error).eraseToAnyPublisher()
        }
        
        let urlString = "https://financialmodelingprep.com/api/v3/income-statement/\(symbol)?apikey=\(API_KEY)"
        
        let urlResult = parseURL(urlString: urlString)
        switch urlResult {
        case .success(let url):
            return URLSession.shared.dataTaskPublisher(for: url)
                .map({$0.data})
                .decode(type: [IncomeStatementFMP].self, decoder: JSONDecoder())
                .receive(on: RunLoop.main)
                .eraseToAnyPublisher()
        
        case .failure(let error):
            return Fail(error: error).eraseToAnyPublisher()
        }
    }

中 的 每 一 个

  • 调用 API _ SERVICE 的 SCREENER 视图 :
var body: some View {
        @Environment(\.managedObjectContext) private var viewContext
    
            //CoreData
            @FetchRequest(entity: Entreprise.entity(), sortDescriptors: [NSSortDescriptor(key: "companyName", ascending: true)]) var entreprises: FetchedResults<Entreprise>
        @State var subscribers = Set<AnyCancellable>()
            @ObservedObject var apiServiceFMP = APIServiceFMP()
            @State var resultScreener: [ResultScreener]?
        @State var incomeStatementFMP: [IncomeStatementFMP]?
        
        ZStack{
            VStack{
                ScrollView(.horizontal){

                VStack{
                    Button(action: {
                        handleSelectionStockScreenerMultipleProperties(exchange: exchange, country: country, marketCap: marketCap)
                    }){
                        Text("Lancer le screen")
                            .fontWeight(.semibold)
                    }
                    .padding()
                    .foregroundColor(.white)
                    .background(Color(.green))
                    .cornerRadius(10)
                }
                if resultScreener != nil{
                    VStack{
                        List(searchResults, id: \.id){ results in
                            HStack{
                                Text(results.symbol)
                                Divider()
                                Text(results.companyName)
                                Divider()
                                Button(action: {
                                    Task{
                                        await handleSelectionIncomeStatementForFMP(for: results.symbol)
                                        await handleSelectionBalanceSheetForFMP(for: results.symbol)
                                        await handleSelectionCashFlowForFMP(for: results.symbol)
                                        await handleSelectionCompanyOutlookForFMP(for: results.symbol)
                                        await handleSelectionHistoricalDailyPriceFMP(for: results.symbol)
                                    }
                                }){
                                    Text("Infos").foregroundColor(.white)
                                }.buttonStyle(.plain)
                                
                                
                                if incomeStatementFMP != nil && balanceSheetFMP != nil && cashFlowFMP != nil && companyOutlookFMP != nil && historicalDailyPriceFMP != nil && incomeStatementFMP!.count > 0 {
                                    if incomeStatementFMP![0].symbol == results.symbol{
                                        Button(action: {
                                            Task{
                                                await handleSelectionIncomeStatementForFMP(for: results.symbol)
                                                await handleSelectionBalanceSheetForFMP(for: results.symbol)
                                                await handleSelectionCashFlowForFMP(for: results.symbol)
                                                await handleSelectionCompanyOutlookForFMP(for: results.symbol)
                                                await handleSelectionHistoricalDailyPriceFMP(for: results.symbol)
                                            }
                                            addEntreprise(incomeStatementFMP: incomeStatementFMP!, balanceSheetFMP: balanceSheetFMP!, cashFlowFMP: cashFlowFMP!, companyOutlookFMP: companyOutlookFMP!, ticker: results.symbol)
                                        }){
                                            Text("Ajout BDD").foregroundColor(.white)
                                        }.buttonStyle(.plain)
                                        .padding()
                                        .background(.blue)
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

private func handleSelectionIncomeStatementForFMP(for symbol: String) async{
 
        apiServiceFMP.readJsonIncomeStatementFMP(keywords: symbol).sink { (completionResult) in
            
            switch completionResult {
            case .failure(let error):
                print(error)
            case .finished: break
            }
        } receiveValue: { (incomeStatementResults) in
            self.incomeStatementFMP = incomeStatementResults
        }.store(in: &subscribers)
    }
private func addEntreprise(incomeStatementFMP: [IncomeStatementFMP], balanceSheetFMP: [BalanceSheetFMP], cashFlowFMP: [CashFlowFMP], companyOutlookFMP: [CompanyOutlookFMP], ticker: String){
        if incomeStatementFMP.count > 0 && balanceSheetFMP.count > 0 && cashFlowFMP.count > 0 {
            if companyOutlookFMP[0].profile.symbol == ticker && incomeStatementFMP.count > 0 && incomeStatementFMP[0].symbol == ticker && balanceSheetFMP[0].symbol == ticker && cashFlowFMP[0].symbol == ticker{
                if entreprises.filter({$0.ticker == ticker}).count != 0 {

                    for entreprise in entreprises.filter({$0.ticker == ticker}){
                        if entreprise.incomes!.count == incomeStatementFMP.count {
                            ///Si les données fondamentales n'ont pas changé, on arrête
                            return
                        }
                        else {
                            ///Si les données fondamentales sont plus nombreuses que celles déjà enregistrées
                            ///Il mettre à jour les données de l'objet existant
                            print("Il faut intégrer la méthode pour modifier l'objet sans le recréer")
                        }
                    }
                } else {
                    createNewEntreprise(companyOutlookFMP: companyOutlookFMP, incomeStatementFMP: incomeStatementFMP, balanceSheetFMP: balanceSheetFMP, cashFlowFMP: cashFlowFMP, historicalDailyPriceFMP: historicalDailyPriceFMP!, ticker: ticker)
                }
            }
        } else {
            print("Il n'y a pas assez de données, pas d'intérêt d'enregistrer l'entreprise")
        }
    }
    
    func createNewEntreprise(companyOutlookFMP: [CompanyOutlookFMP], incomeStatementFMP: [IncomeStatementFMP], balanceSheetFMP: [BalanceSheetFMP], cashFlowFMP: [CashFlowFMP], historicalDailyPriceFMP: [HistoricalDailyPriceFMP], ticker: String){
        if companyOutlookFMP[0].profile.symbol == ticker && incomeStatementFMP[0].symbol == ticker && balanceSheetFMP[0].symbol == ticker && cashFlowFMP[0].symbol == ticker && historicalDailyPriceFMP[0].symbol == ticker{
            let newEntreprise = Entreprise(context: viewContext)
            newEntreprise.ticker = companyOutlookFMP[0].profile.symbol
            newEntreprise.industry = companyOutlookFMP[0].profile.industry
            newEntreprise.sector = companyOutlookFMP[0].profile.sector
            newEntreprise.companyName = companyOutlookFMP[0].profile.companyName
            
            newEntreprise.currency = companyOutlookFMP[0].profile.currency
            newEntreprise.region = companyOutlookFMP[0].profile.country
            newEntreprise.exchange = companyOutlookFMP[0].profile.exchangeShortName
            
            let s = companyOutlookFMP[0].profile.isin
            let any : Any? = s
            if any != nil {
                newEntreprise.isin = companyOutlookFMP[0].profile.isin
            } else {
                newEntreprise.isin = "Pas de ISIN"
            }

            newEntreprise.lastPrice = Array(getLastDailyPrice(historicalDailyPrice: historicalDailyPriceFMP)).sorted(by: >)[0].value
            newEntreprise.dateLastPrice = Array(getLastDailyPrice(historicalDailyPrice: historicalDailyPriceFMP)).sorted(by: >)[0].key
            
            //Ajouter les données fondamentales
            for i in addIncomeToEnterprise(incomeStatementFMP: incomeStatementFMP){
                newEntreprise.addToIncomes(i)
                //On enregistre les Income Statement
                do {
                    try viewContext.save()
                } catch {
                    let nsError = error as NSError
                    fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                }
            }
            for i in addBalanceToEnterprise(balanceSheetFMP: balanceSheetFMP){
                newEntreprise.addToBalances(i)
                //On enregistre les Balance Sheet
                do {
                    try viewContext.save()
                } catch {
                    let nsError = error as NSError
                    fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                }
            }
            for i in addCashToEnterprise(cashFlowFMP: cashFlowFMP){
                newEntreprise.addToCashFlows(i)
                //On enregistre les Cash Flow
                do {
                    try viewContext.save()
                } catch {
                    let nsError = error as NSError
                    fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
                }
            }
            //On enregistre l'objet newEntreprise avec toutes les Relationships
            do {
                try viewContext.save()
            } catch {
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}

格式
我 认为 我们 应该 使用 异步 等待 的 概念 。
我 想 加载 的 数据 与 一 个 点击 " Ajout BDD " 。
这 就是 它 不能 完美 工作 的 地方 - 〉 我 必须 先 单击 * * " Info " * * 按钮 , 它 调用 API _ SERVICE 函数 , 然后 才 能 按 下 * * " Ajout BDD " * * 按钮 , 它 用于 创建 核心 对象 数据 。
为什么 当 我 直接 按 * * " Ajout BDD " * * 时 没有 任何 React ? 如果 我 按 两 次 , 它 会 将 对象 添加 到 Core Data 中 。
谢谢 你 的 帮助

vptzau2j

vptzau2j1#

我 发现 了 一 个 需要 改进 的 解决 方案 , 但 它 很 有效 。 在 我 想 监控 的 四 个 变量 中 , 我 添加 了 一 个 DidSet :

@State var incomeStatementFMP: [IncomeStatementFMP]?{
    didSet{
        observeEntreprise()
    }
}
@State var balanceSheetFMP: [BalanceSheetFMP]?{
    didSet{
        observeEntreprise()
    }
}
@State var cashFlowFMP: [CashFlowFMP]?{
    didSet{
        observeEntreprise()
    }
}
@State var companyOutlookFMP: [CompanyOutlookFMP]?{
    didSet{
        observeEntreprise()
    }
}

中 的 每 一 个
其余 部分 由 函数 observeEntreprise 处理 :

func observeEntreprise(){
    if incomeStatementFMP != nil && balanceSheetFMP != nil && cashFlowFMP != nil && companyOutlookFMP != nil && historicalDailyPriceFMP != nil{
        let newEntreprise = Entreprise(context: viewContext)
        ............
}

格式

相关问题