Как суммировать отфильтрованные данные ядра в SwiftUI? - PullRequest
1 голос
/ 10 января 2020

Как суммировать отфильтрованные значения базовых данных (используя предикат) в приложении SwiftUI?

У меня есть 1 объект с именем NPTransaction . Он имеет 5 атрибутов, и я хотел бы суммировать значения из атрибута с именем value (целое число 64) . По сути, это будет суммировать значения дохода в выбранном месяце (сейчас он установлен на текущую дату () в коде примера, но позже он будет установлен на весь текущий месяц).

Я нашел похожие Вопрос относительно Swift, но я не могу заставить этот код работать в моем приложении. Ссылка на связанный вопрос: Как суммировать числа (Int16) сохраненных базовых данных - Swift 3

Основываясь на коде по ссылке, у меня сейчас следующий код:

import SwiftUI

struct DashboardView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @State var selectedDate = Date()

   // This code in private var below produces many errors like:
   // Value of type 'AppDelegate' has no member 'managedObjectContext'
   // Use of undeclared type 'NSEntityDescription'
   // Use of undeclared type 'NSFetchRequest'
   // - so I assume that this linked question may be outdated or I should take different approach using SwiftUI
    private var income: Int64 {
        let context = (UIApplication.shared.delegate as! AppDelegate).managedObjectContext
        let entityDesc: NSEntityDescription = NSEntityDescription.entity(forEntityName: "NPTransaction", in: context)!
        let request: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest()
        request.entity = entityDesc

        request.predicate = NSPredicate(format: "date == %@", selectedDate)
        let records = try! context.fetch(request)

        try! context.fetch(request) as! [NSManagedObject]
        let monthlyIncome = result.reduce(0) { $0 + ($1.value(forKey: "value") as? Int64 ?? 0) }
        return monthlyIncome
    }

    var body: some View {
        NavigationView {
            VStack {                    
               Text("Monthly income:")
               Text("\(income) USD")
                }

// more code...

Я только изучаю Swift и SwiftUI, так что, может быть, есть лучший и совершенно другой способ решения этой проблемы?

Ответы [ 2 ]

0 голосов
/ 13 января 2020

Я обнаружил похожую проблему в этом вопросе: Сумма (двойного) поля запроса на выборку Я немного изменил код и нашел это решение:

import SwiftUI
import CoreData

struct DashboardView: View {
    @Environment(\.managedObjectContext) var managedObjectContext
    // FetchRequest with predicate set to "after now" 
    @FetchRequest(entity: NPTransaction.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \NPTransaction.value, ascending: false)], predicate: NSPredicate(format: "date > %@", Date() as NSDate)) var fetchRequest: FetchedResults<NPTransaction>

    // sum results using reduce
    var sum: Int64 {
        fetchRequest.reduce(0) { $0 + $1.value }
    }

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {

                HStack {
                    VStack(alignment: .leading) {
                        Text("sum")
                        Text("\(sum)")
                            .font(.largeTitle)

                    }
                    Spacer()
                }
                .padding()

                Spacer()
            }.navigationBarTitle("Title")
        }
    }

}

struct DashboardView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return DashboardView().environment(\.managedObjectContext, context)
    }
}
0 голосов
/ 10 января 2020

Это должно исправить ваш текущий код, вы пытаетесь уменьшить несуществующую переменную с именем result, которую, я полагаю, вы получили из связанного кода. Вы также делаете две выборки, которые не должны быть необходимыми. Надеюсь, это поможет.

request.predicate = NSPredicate(format: "date == %@", selectedDate)
let records = try! context.fetch(request) as! [NSManagedObject]

let monthlyIncome = records.reduce(0) { $0 + ($1.value(forKey: "value") as? Int64 ?? 0) }
return monthlyIncome

Кроме того, вы можете суммировать значения из CoreData через NSFetchRequest и NSExpression. Вот пример, который я нашел в этой статье: Группировка по количеству и сумме в CoreData .

let keypathExp1 = NSExpression(forKeyPath: "value")
let expression = NSExpression(forFunction: "sum:", arguments: [keypathExp1])
let sumDesc = NSExpressionDescription()
sumDesc.expression = expression
sumDesc.name = "sum"
sumDesc.expressionResultType = .integer64AttributeType

let request = NSFetchRequest(entityName: "NPTransaction")
request.returnsObjectsAsFaults = false
request.propertiesToFetch = [sumDesc]
request.resultType = .dictionaryResultType

let monthlyIncome = try! context.fetch(request) as? Int64 

if let monthlyIncome = monthlyIncome {
    print("monthly income total: \(monthlyIncome)")
}

Редактировать: я изменил пример кода с вашей сущностью и именем столбца.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...