来自iOS swift app的Core Data的奇怪行为

时间:2015-02-12 21:28:52

标签: ios sqlite swift core-data xcode6

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

我有三个实体: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对象。

我已经尝试过几个东西,包括在获取期间返回的对象等。当我使用sqlite3打开.sqlite文件时,我可以看到正在创建的条目。我尝试使用sql debug flag设置为3,但没有跳出来。我并不是说那条大道已经筋疲力尽,但我绝对是。

有关这里可能发生什么的任何想法?我坚持了很长一段时间,任何想法都会受到赞赏。

错误为EXC_BAD_ACCESS,问题是match.bet.team1为零。这是我上面几行所做的相同的任务。

2 个答案:

答案 0 :(得分:0)

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

虽然理论上你的设置也应该有用,但是你会引入不必要的复杂性。您没有提供足够的信息来解决您的错误,但我认为没有必要打扰这个错误。

只需使用match.team1代替match.bet.team1

顺便说一句,值得注意的是,matchnilscorenil,或match.team1为{{1} } - 在所有情况下,nil也是score.team1

答案 1 :(得分:0)

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