iOS swift 应用中 Core Data 的奇怪行为

Strange behavior from Core Data in iOS swift app

我正在为实体分配非零值,保存它们,然后立即检索它们。但是这些值返回为零。这是 iOS 8.1 和 Xcode(最新的 GA 版本)上的 Swift,在模拟器和设备上具有相同的行为。

我有三个实体:MatchScoreTeam。每个 Match 有两支球队,team1team2Score 还有 team1team2MatchScore 具有 1x1 关系,字段分别为 betbetForMatch 由其字段 matchNumber 标识。

所以我有以下代码:

    var match:CBMatch?
    var betCard:CBScore?
    for matchNum in 1...42 {
        match = CBMatch.lookup(self.managedObjectContext!, matchNumber: matchNum)

        betCard = CBScore.addForBet(self.managedObjectContext!, match: match!)

        betCard!.team1 = match!.team1
        betCard!.team2 = match!.team2

        match!.bet = betCard!

        println("For match \(matchNum), \(betCard!.team1.shortname) vs \(betCard!.team2.shortname)")
        // This is fine for all matchNum values
    }

    // Verify
    if true {
        var err:NSError? = nil
        self.managedObjectContext!.save(&err)
        if err != nil {
            abort() // Hasn't happened yet
        }
        match = CBMatch.lookup(self.managedObjectContext!, matchNumber: 1)
        betCard = match!.bet

        println("For match 1, \(betCard!.team1.shortname) vs \(betCard!.team2.shortname)")
     // Crashes with NPE
    // It complains that betCard!.team2 is nil but betCard!.team1 is fine
    }

基本上,尝试检索我刚刚设置的信息时返回的结果为 nil。

CBMatch:lookupCBScore:addForBet 是微不足道的:

class func lookup(moc: NSManagedObjectContext, matchNumber: Int) -> CBMatch? {
    var fetchRequest = NSFetchRequest(entityName: "CBMatch")
    var predicate = NSPredicate(format: "matchNumber == %d", matchNumber)
    fetchRequest.fetchLimit = 1
    fetchRequest.predicate = predicate
    //        fetchRequest.returnsObjectsAsFaults = false
    // With or without didn't make a difference
    var err:NSError? = nil
    let matches = moc.executeFetchRequest(fetchRequest, error: &err)!

    if matches.count == 1 && err == nil {
        let fetchedMatch = matches[0] as CBMatch
        return fetchedMatch
    }
    println("Could not find match \(matchNumber)")
    return nil
}


class func addForBet(moc: NSManagedObjectContext, match:CBMatch) -> CBScore {
    var entity = NSEntityDescription.insertNewObjectForEntityForName("CBScore", inManagedObjectContext: moc) as CBScore

    entity.betFor = match
    return entity
}

我不能通过简单地丢弃 bet.team1 等来简化数据模型,因为在某些情况下 bet.team1 和 match.team1 会不同,我需要能够比较它们。对于这种(最简单的)情况,它们是相同的,因为这是第一次初始化 Score 对象。

我已经尝试了几种方法,包括在获取期间 returnsObjectsAsFault = false 等。当我使用 sqlite3 打开 .sqlite 文件时,我可以看到正在创建的条目。我尝试使用 sql 调试标志设置为 3,但没有跳出来。我不是说大道已尽,但我确实是。

对这里可能发生的事情有什么想法吗?我坚持这个很长一段时间,任何想法将不胜感激。

错误是 EXC_BAD_ACCESS,问题是 match.bet.team1 是 nil 。这与我在上面几行中所做的相同。

在我看来,您的数据模型存在缺陷。你两次引用每个团队,这真的没有必要。 Bet 实体不需要了解团队,因为它与 Match 实体具有一对一的关系。 Bet 可能包含类似于 firstValuesecondValue 的内容。

虽然理论上您的设置也应该有效,但您引入了不必要的复杂性。您没有提供足够的信息来解决您的错误,但我认为甚至没有必要费心去寻找那个错误。

只需使用 match.team1 而不是 match.bet.team1

顺便说一句,很明显要注意 matchnilscorenil,或者 match.team1nil - 在所有情况下 score.team1 也是 nil.

在我的代码中发现了错误 - team1 和 team2 的关系是 1:1,但为了允许多次分配,它们需要 1:N。