Realm将数据附加到List <t>类型

时间:2015-11-15 23:57:36

标签: ios swift realm

我正在尝试浏览数据并将其保存在我的模型中,但无论我做什么,我都会收到以下错误:Can't mutate a persisted array outside of a write transaction.。我究竟做错了什么?我将每场比赛追加到联赛但是它似乎不起作用?

领域模型

class League: Object {
    dynamic var id: Int = 0
    dynamic var name: String? = ""
    var matches = List<Match>()

    override class func primaryKey() -> String {
        return "id"
    }
}

class Match: Object {
    dynamic var matchId: Int = 0
    dynamic var date: NSDate?
    dynamic var homeName: String? = ""
    dynamic var awayName: String? = ""
    dynamic var awayScore: Int = 0
    dynamic var homeScore: Int = 0
    dynamic var leagueName: String? = ""
    dynamic var homeLogo: NSData?
    dynamic var awayLogo: NSData?
}

代码

    for (_, item) in result {
        if let leagueId = item["league"].int,
            let leagueName = item["name"].string,
            let allMatches = item["matches"].array {
                let league = League()
                league.name = leagueName
                league.id = leagueId

                for match in allMatches {
                    if let matchId = match["matchId"].int,
                        let tournament = match["tournament"].string,
                        let homeTeam = match["homeName"].string,
                        let awayTeam = match["awayName"].string,
                        let homeScore = match["homeScore"].int,
                        let awayScore = match["awayScore"].int,
                        let homeLogo = match["homeLogo"].string,
                        let awayLogo = match["awayLogo"].string,
                        let date = match["date"].string {
                            if let awayLogoUrl = NSURL(string: awayLogo),
                                let homeLogoUrl = NSURL(string: homeLogo) {
                                    if let awayLogoData = NSData(contentsOfURL: awayLogoUrl),
                                        let homeLogoData = NSData(contentsOfURL: homeLogoUrl) {
                                            let matchObject = Match()
                                            matchObject.matchId = matchId
                                            matchObject.leagueName = tournament
                                            matchObject.homeName = homeTeam
                                            matchObject.awayName = awayTeam
                                            matchObject.homeScore = homeScore
                                            matchObject.awayScore = awayScore
                                            matchObject.homeLogo = homeLogoData
                                            matchObject.awayLogo = awayLogoData

                                            let formatter = NSDateFormatter()
                                            formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
                                            formatter.timeZone = NSTimeZone(abbreviation: "CET")
                                            matchObject.date = formatter.dateFromString(date)!

                                            league.matches.append(matchObject)
                                    }
                            }
                    }

                    print(league)

                    try! realm.write {
                        realm.add(league, update: true)
                    }
                }
        }
    }
}

2 个答案:

答案 0 :(得分:5)

简化代码以仅显示一般结构有助于揭示问题:

let league = League()
league.name = leagueName
league.id = leagueId

for match in allMatches {
    if … {
        let matchObject = Match()
        …

        league.matches.append(matchObject)
    }

    print(league)

    try! realm.write {
        realm.add(league, update: true)
    }
}

这是事件序列:首先创建一个独立的,未加载的League实例league。对于每个匹配,您创建一个独立的,未加载的Match实例,并将其附加到league.matches。然后创建一个写事务,并将league保存到Realm。从这一点开始,league不再是独立的,只能在写入事务中进行修改。在循环的下一次迭代中,您创建另一个Match实例并尝试将其附加到league.matches。由于league被持久存在而且我们不在写入事务中,因此抛出。

这里的一个解决方案是重构代码,这样你只需将league保存到Realm一次,如下所示:

let league = League()
league.name = leagueName
league.id = leagueId

for match in allMatches {
    if … {
        let matchObject = Match()
        …

        league.matches.append(matchObject)
    }
}

print(league)

try! realm.write {
    realm.add(league, update: true)
}

答案 1 :(得分:5)

上面的帖子是错误的,你不能在写块之外改变领域模型的列表。

正确的方法是:

try! realm.write {
    league.matches.append(matchObject)
    realm.add(league, update: true)
}

至少这是Realm Version 0.98

的常用方法