You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CloudKit私有AccountInfo引用公共Wine记录查询报错求解决方案

问题分析与解决方案

错误根源

你遇到的Custom zones are not allowed in public DB错误,核心原因是你尝试查询的CKRecordID带有私有数据库的自定义zone标识(zoneID=AccountInformation:defaultOwner)。这说明你从AccountInfo中取出的Wine引用,指向的是私有区的记录,而非你预期的公共库Wine记录——要么是创建引用时选错了记录,要么是Wine记录本身就误存到了私有区。

修正步骤与代码调整

1. 先确认数据正确性

打开CloudKit Dashboard检查:

  • 公共数据库中是否存在目标Wine记录,且它们的recordID使用默认根zone(无自定义zone标识)。
  • 私有数据库中AccountInfo的Wines字段,所有引用的recordID均对应公共库的Wine记录。

2. 修正UserObj初始化代码

替换强制解包为可选绑定(避免崩溃),并行查询提升效率,同时增加zone合法性校验:

public class UserObj: ObservableObject {
    var Fname: String
    var Lname: String
    var username: String
    var password: String
    var email: String
    var phoneNumber: String
    var pfp: UIImage
    @Published var wines: [Wine] = [] // 用@Published让UI感知数据更新
    var recordID: String
    
    init(ckrecord: CKRecord) async throws {
        // 安全解析CKRecord字段
        guard let fname = ckrecord["FName"] as? String,
              let lname = ckrecord["LName"] as? String,
              let username = ckrecord["Username"] as? String,
              let password = ckrecord["Password"] as? String,
              let email = ckrecord["Email"] as? String,
              let phoneNumber = ckrecord["PhoneNumber"] as? String,
              let imageAsset = ckrecord["PFP"] as? CKAsset,
              let imageURL = imageAsset.fileURL,
              let imageData = try? Data(contentsOf: imageURL),
              let pfp = UIImage(data: imageData) else {
            throw NSError(domain: "UserObjInit", code: -1, userInfo: [NSLocalizedDescriptionKey: "解析用户记录失败"])
        }
        
        self.Fname = fname
        self.Lname = lname
        self.username = username
        self.password = password
        self.email = email
        self.phoneNumber = phoneNumber
        self.pfp = pfp
        self.recordID = ckrecord.recordID.recordName
        
        // 处理Wine引用列表
        guard let wineRefs = ckrecord["Wines"] as? [CKRecord.Reference] else {
            return
        }
        
        let publicDB = CKContainer.default().publicCloudDatabase
        // 并行查询所有Wine记录
        await withTaskGroup(of: Wine?.self) { group in
            for ref in wineRefs {
                group.addTask {
                    do {
                        // 校验引用的记录是否属于公共库根zone(公共库不允许自定义zone)
                        guard ref.recordID.zoneID == CKRecordZone.default().zoneID else {
                            print("无效引用:记录不在公共库根zone中,跳过 \(ref.recordID)")
                            return nil
                        }
                        guard let fetchedRecord = try await publicDB.record(for: ref.recordID) else {
                            print("未找到对应Wine记录:\(ref.recordID)")
                            return nil
                        }
                        return try await Wine(ckrecord: fetchedRecord)
                    } catch {
                        print("获取Wine记录失败:\(error.localizedDescription)")
                        return nil
                    }
                }
            }
            
            // 收集有效Wine对象
            for await wine in group {
                if let wine = wine {
                    self.wines.append(wine)
                }
            }
        }
    }
}

3. 修正Wine类初始化代码

同样优化数据解析逻辑,处理Vineyard引用:

class Wine: Identifiable {
    var type: String
    var vintage: String
    @Published var vineyard: Vineyard? // 用可选类型替代空对象初始化
    let id: UUID
    
    init(ckrecord: CKRecord) async throws {
        guard let type = ckrecord["Type"] as? String,
              let vintage = ckrecord["Vintage"] as? String else {
            throw NSError(domain: "WineInit", code: -1, userInfo: [NSLocalizedDescriptionKey: "解析Wine记录失败"])
        }
        
        self.type = type
        self.vintage = vintage
        self.id = UUID()
        
        // 处理Vineyard引用
        if let vineyardRef = ckrecord["Vineyard"] as? CKRecord.Reference {
            let publicDB = CKContainer.default().publicCloudDatabase
            do {
                guard vineyardRef.recordID.zoneID == CKRecordZone.default().zoneID else {
                    print("Vineyard引用无效:不在公共库根zone")
                    return
                }
                guard let fetchedRecord = try await publicDB.record(for: vineyardRef.recordID) else {
                    print("未找到对应Vineyard记录")
                    return
                }
                self.vineyard = try Vineyard(ckrecord: fetchedRecord)
            } catch {
                print("获取Vineyard失败:\(error.localizedDescription)")
            }
        }
    }
}

// 示例Vineyard类(需根据你的实际字段调整)
class Vineyard {
    var name: String?
    
    init() {}
    
    init(ckrecord: CKRecord) throws {
        self.name = ckrecord["Name"] as? String
        // 解析其他Vineyard字段
    }
}

内容的提问来源于stack exchange,提问作者JonGrimes20

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:32:09