英文:
App crashes on CoreData deletion...how to code this correctly?
问题
I have 2 core data entity's set up with a many to one and one to many relationship between them (Show -> Season one to many / Season -> Show many to one). I have the class for Show manually created with the code below. However, when I delete a show or season (if only one), it is crashing the app saying 'Fatal error: Unexpectedly found nil while unwrapping an Optional value' for the following code in the manual class, which was set up to create the relationship between the two entities. I have the app set up to use a for loop to delete all seasons of a show prior to deleting the show as well, which causes the same error, obviously because there are no seasons left. How do I fix this so that it deletes all seasons without an error?
Shows+CoreDataProperties.swift (manual class for Show Entity)
@NSManaged public var season: Set<Seasons>?
public var seasons: [Seasons] {
    let setOfSeasons = season
    return setOfSeasons!.sorted {
        $0.id > $1.id
    }
}
Deletion code within view
// DELETE SHOW
public func deleteShow(show: Shows) {
    deleteSeasonsInShow(show: show)
    viewContext.delete(show)
    do {
        try viewContext.save()
    } catch {
        print(error)
    }
}
// DELETE SEASONS WITHIN SHOW PRIOR TO DELETING SHOW
public func deleteSeasonsInShow(show: Shows) {
    for season in show.seasons {
        viewContext.delete(season)
        do {
            try viewContext.save()
        } catch {
            print(error)
        }
    }
}
英文:
I have 2 core data entity's set up with a many to one and one to many relationship between them (Show -> Season one to many / Season -> Show many to one). I have the class for Show manually created with the code below. However, when I delete a show or season (if only one), it is crashing the app saying 'Fatal error: Unexpectedly found nil while unwrapping an Optional value' for the following code in the manual class, which was setup to create the relationship between the two entities. I have the app set up to use a for loop to delete all seasons of a show prior to deleting the show as well, which causes the same error obviously because there are no seasons left. How do I fix this so that it deletes all seasons without an error?
**Shows+CoreDataProperties.swift (manual class for Show Entity)
**
@NSManaged public var season: Set<Seasons>?
    public var seasons: [Seasons]{
            let setOfSeasons = season
            return setOfSeasons!.sorted{
                $0.id > $1.id
            }
        }
Deletion code within view
    // DELETE SHOW
    public func deleteShow(show: Shows){
        deleteSeasonsinShow(show: show)
        viewContext.delete(show)
        do{
            try viewContext.save()
        } catch{
            print(error)
        }
    }
    
    // DELETE SEASONS WITHIN SHOW PRIOR TO DELETING SHOW
    public func deleteSeasonsinShow(show: Shows){
        
        for season in show.seasons {
            viewContext.delete(season)
            do{
                try viewContext.save()
            } catch{
                print(error)
            }
        }
    }
答案1
得分: 0
Use a guard statement in the computed property to avoid having to use forced unwrapping
public var seasons: [Seasons] {
    guard let season else { return [] }
    return season.sorted {
        $0.id > $1.id
    }
}
英文:
Use a guard statement in the computed property to avoid having to use forced unwrapping
public var seasons: [Seasons] {
    guard let season else { return [] }
    return season.sorted {
        $0.id > $1.id
    }
}
答案2
得分: 0
首先,关于单数/复数方面,你的命名方式令人困惑。实体应以单数形式命名,而一对多的关系应以复数形式命名。
如果 Show 是手动创建的,无论如何都应该将 set 声明为非可选的 Set,通过移除问号并取消模型中的 Optional 复选框。
@NSManaged public var seasons: Set<Season>
实际上,你不需要转换为 Array。该 set 可以像数组一样被枚举。
如果确实需要一个可选项,请添加一个计算属性,安全地取消包装该可选项:
var unwrappedSeasons: Set<Season> {
    return seasons ?? Set<Season>()
}
而且 - 与此无关 - 不要在循环中多次保存上下文。在循环之后调用一次即可。
public func deleteSeasonsInShow(show: Shows) {
    
    for season in show.seasons {
        viewContext.delete(season)
    }
    do {
        try viewContext.save()
    } catch {
        print(error)
    }
}
英文:
First of all your naming is confusing with regard to singular/plural. Entities are supposed to be named in singular form and a to-many relationship is supposed to be named in plural form.
If Show is created manually anyway, declare the set as non-optional Set by removing the question mark and unchecking Optional in the model
@NSManaged public var seasons : Set<Season>
And actually you don't need the conversion to Array. The set can be enumerated like an array.
If you really need an optional add a computed property which unwraps the optional safely
var unwrappedSeasons : Set<Season> {
    return seasons ?? Set<Season>()
}
And - unrelated - do not save the context multiple times in a loop. Call it once after the loop.
public func deleteSeasonsinShow(show: Shows){
    
    for season in show.seasons {
        viewContext.delete(season)
    }
    do {
        try viewContext.save()
    } catch{
        print(error)
    }
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论