Ludovic
Ludovic

Reputation: 2002

GroupBy using @FetchRequest in SwiftUI

I have a SwiftUI view like :

@FetchRequest(
    entity: Message(),
    sortDescriptors: [NSSortDescriptor(keyPath: \Message.date, ascending: false)]
) var allMessages: FetchedResults< Message.date >

var body: some View {
    NavigationView {
        List(self.allMessages) { message in
            Text(message.text)
        }
        .navigationBarTitle(Text("Last Messages"))
    }
}

I would like the FetchRequest to return only last message of each user. I need to use a group by. Is there a way using @FetchRequest ? If not, how would you do ?

Upvotes: 5

Views: 924

Answers (1)

93sauu
93sauu

Reputation: 4097

Step by step:

  1. Create NSFetchRequest
  2. Specify an NSPredicate to filter according to your chosen criteria
  3. Set the resultType to ".DictionaryResultType" (required for "Group By")
  4. Set the properties to be included in the fetch.
  5. Set the properties to group by
  6. Create an NSSortDescriptor to order by name, descending
  7. Finally you can create @FetchRequest using the initializer "@FetchRequest(fetchRequest: ")
class TODOItem: NSManagedObject, Identifiable {
    @NSManaged public var name: String?
    @NSManaged public var notes: String?
}

extension TODOItem {
    static func allTODOItem() -> NSFetchRequest<TODOItem> {
        //1º
        let fetchRequest = NSFetchRequest<TODOItem>(entityName: "TODOItem")
        //2º
        //fetchRequest.predicate = NSPredicate(format: "", ...)
        //3º
        fetchRequest.resultType = .dictionaryResultType
        //4º
        // To get computed props you can use NSExpression (for example the sum of something)
        fetchRequest.propertiesToFetch = ["name", "notes"]
        //5º
        fetchRequest.propertiesToFetch = ["name"]
        //6º
        let sort = NSSortDescriptor(key: "name", ascending: false)
        fetchRequest.sortDescriptors = [sort]

        return fetchRequest
    }
}

struct Home : View {
    @FetchRequest(fetchRequest: TODOItem.allTODOItem()) var items: FetchedResults<TODOItem>

    var body: some View {
        Text("Home")
    }
}

Upvotes: -1

Related Questions