我的应用程序中有两个实体,“Card”和“CardRecord”,它们具有 1:n 关系,一张卡有很多记录。我有一个视图需要显示每张卡中有多少条记录,所以这是我的代码:
@SectionedFetchRequest
private var sectionRecords: SectionedFetchResults<Card, CardRecord>
init(month: Int32) {
let predicate = NSPredicate(format: "month = %i", month)
_sectionRecords = SectionedFetchRequest<Card, CardRecord>(
entity: CardRecord.entity(),
sectionIdentifier: \CardRecord.card!,
sortDescriptors: [],
predicate: predicate
)
}
var body: some View {
VStack(alignment: .leading) {
ForEach(sectionRecords) { section in
CardExpansionView(card: section.id, num: Int32(section.count))
}
}
}
我只需要循环sectionRecords,因为我只需要每个部分的编号,并且我需要显示@ObservedObjectCard,这就是为什么我使用关系对象Card作为部分id。
当我在模拟器中运行应用程序时,出现错误:
ForEach<SectionedFetchResults<Card, CardRecord>, Card, CardExpansionView>: the ID <Card: 0x6000025fdf40> (entity: Card; id: 0xe565b4b98e84a111 <x-coredata://292B0160-058F-48AE-BFCC-11196BF00552/Card/p24>; data: {
cid = "6E3C25B7-2DC2-4538-B3D9-950A387C13AD";
color = CardBrown;
createTime = "2024-04-04 07:47:22 +0000";
icon = "cup.and.saucer";
name = "NO COFFEE";
records = "<relationship fault: 0x60000063f6e0 'records'>";
}) occurs multiple times within the collection, this will give undefined results!
同时又出现了一个问题,页面显示的节数不正确,并且有重复的卡片。
然后我在实体“CardRecord”中添加属性“cardId”,并将sectionid更改为cardId
sectionIdentifier: \CardRecord.cardId!
当我再次运行该应用程序时...错误消失了,但是部分的数量仍然错误并且重复仍然存在。
那么,问题是什么以及我需要做什么。
最后,一个问题:如何通过“section.count”对“sectionRecords”进行排序
谢谢。
var body: some View {
VStack(alignment: .leading) {
ForEach(ranksFetcher.ranks, id: \.id) { rank in
CardExpansionView(card: rank.card, num: rank.count, maxWidth: rank.width)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.onAppear() {
if fetch {
ranksFetcher.moc = moc
ranksFetcher.maxWidth = viewWidth()
ranksFetcher.fetch(yearmonth: yearmonth)
fetch.toggle()
}
}
}
class RanksFetcher: NSObject, ObservableObject {
var moc: NSManagedObjectContext?
var maxWidth: CGFloat?
@Published
private(set) var ranks: [CardRankModel] = []
func fetch(yearmonth: Int32) {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "CardRecord")
fetchRequest.predicate = NSPredicate(format: "month = %i", yearmonth)
fetchRequest.propertiesToGroupBy = ["cardId"]
fetchRequest.resultType = .dictionaryResultType
// Defining column 'count'
let expressDescription = NSExpressionDescription()
expressDescription.resultType = .integer32
let name = "count"
expressDescription.name = name
// Count witch column
let cardId = NSExpression(forKeyPath: \CardRecord.cardId)
let express = NSExpression(forFunction: "count:", arguments: [cardId])
expressDescription.expression = express
fetchRequest.propertiesToFetch = ["cardId", expressDescription]
var groups = (try? moc!.fetch(fetchRequest) as? [[String: Any]]) ?? []
groups.sort { e1, e2 in
let i1 = e1["count"] as? Int32 ?? 0
let i2 = e2["count"] as? Int32 ?? 0
return i1 > i2
}
var cardIds = [String]()
for gp in groups {
cardIds.append(gp["cardId"] as! String)
}
let cardsFetchRequest = NSFetchRequest<Card>(entityName: "Card")
cardsFetchRequest.predicate = NSPredicate(format: "cid in (%@)", cardIds)
let cards = (try? moc!.fetch(cardsFetchRequest)) ?? []
let cardMap = Dictionary.init(cards.map { ($0.cid, $0) }) { $1 }
let maxWidth = maxWidth!
let maxCount = groups.first?["count"] as? Int32
var data: [CardRankModel] = []
for gp in groups {
let cardId = gp["cardId"] as! String
let count = gp["count"] as? Int32 ?? 0
if let card = cardMap[cardId] {
let cardRankModel = CardRankModel(id: card.cid!, card: card, count: count, width: maxWidth * (CGFloat(count) / CGFloat(maxCount!)))
data.append(cardRankModel)
}
}
ranks = data
}
}