在 CoreData 记录中进行更改,SwiftUI

Posted

技术标签:

【中文标题】在 CoreData 记录中进行更改,SwiftUI【英文标题】:Making Changes in CoreData record, SwiftUI 【发布时间】:2019-12-12 08:53:43 【问题描述】:

我正在使用 SwiftUI 学习 Core Data。我想制作一个应用程序,我可以在其中发布我喜欢的电影、进行评论和添加评分。

我已经可以在我的应用中添加新电影,删除它,查看电影详情。现在我想在 CoreData 中编辑我的记录。我发现这很困难,因为我不知道如何将默认值从已编辑的电影中放置到我的表单中。

我的代码:

struct EditMovieVIew: View 
let movie: Movie
@Environment(\.presentationMode) var presentationMode
@Environment(\.managedObjectContext) var moc

@State private var title = ""
@State private var director = ""
@State private var review = ""
@State private var genre = "Fantasy"
@State private var rating = 3
@State private var productionYear = Date()


    let genres = ["Sci-Fi","Fantasy", "Comedy", "Horror", "Thriller", "Criminal", "Kids", "Romance", "Drama"]

    var body: some View 
        NavigationView 
            Form 
                Section 
                    TextField("Name of movie", text: $title)
                    TextField("Director's name", text: $director)
                

                Section 
                    DatePicker(selection: $productionYear, in: ...Date(), displayedComponents: .date) 
                        Text("Date of production")
                    
                

                Section 
                    Picker(selection: $genre, label: Text("Genre")) 
                        ForEach(genres, id: \.self) 
                            Text($0).tag($0)
                        
                    
                .navigationBarTitle("Select your cheese")

                Section 
                    RatingView(rating: $rating)

                    TextField("Write a review", text: $review)
                

                Section 
                    Button("Save") 
                        let newMovie = Movie(context: self.moc)
                        newMovie.title = self.title
                        newMovie.director = self.director
                        newMovie.rating = Int16(self.rating)
                        newMovie.review = self.review
                        newMovie.genre = self.genre
                        newMovie.productionYear = Int16(Calendar.current.component(.year, from: self.productionYear))

                        try? self.moc.save()
                        self.presentationMode.wrappedValue.dismiss()


                    
                
            
            .navigationBarTitle("Add Movie")
        

    


struct EditMovieVIew_Previews: PreviewProvider 
static let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

static var previews: some View 
    let movie = Movie(context: moc)
    movie.title = "Test Movie"
    movie.director = "Test director"
    movie.genre = "Fantasy"
    movie.rating = 4
    movie.review = "Good movie"
    movie.productionYear = 2019

    return NavigationView 
        EditMovieVIew(movie: movie)
    

我也尝试过

@Binding var movie: Movie

但我的想法都没有奏效。

问题出在哪里? 当我想为我的 TextFields 和 Pickers 分配一个值时,我不能使用我的

文本:$movie.title。 //或文本:movie.title //或文本:self.movi​​e.title

接下来我想做的是为我的@State 值分配默认值。我写过:@State private var title = self.movie.title 但Xcode 说我不能在这里使用selfmovie

所以我的问题是 - 如何为我的 TextField 设置默认起始值​​,以便能够编辑我的电影并在我的 CoreData 中更新它?

PS。我还有另一个问题。我想让 DatePicker 只用于挑选年份。现在我有完整的选择器,然后我只使用用户选择的年份,但我认为最好只选择一年

I want TextFields to have default value got from original movie

【问题讨论】:

如果你想编辑/更新电影,那么你需要从核心数据存储中获取一个 Movie 对象来获取值并在更改完成时保存,但现在你正在保存一个新的实例。我没有太多地一起使用 SwiftUI 和 Core Data,但我猜你需要将电影属性作为观察对象。此外,您应该从问题中删除该 PS,并且一次只问一件事。 【参考方案1】:

您应该在自定义 init 函数中执行此操作。因为它们是@State 包裹的,所以您需要跳过一个小圈才能正确设置它们。

@State private var title: String // don't set up any initial value here

init(movie: Movie) 
  self.movie = movie
  self._title = State(initialValue: movie.title ?? "")
  // etc.

注意_title,这意味着您正在初始化包装器而不是包装器值。

对于问题 2,如果您只关心年份,请考虑存储 DateComponents 而不是 Date,并且只需设置自定义选择器而不是 DatePicker。填充可追溯到 1850 年(或任何时候)的一系列年份非常简单。或者有一个年份文本字段。有很多方法可以做到这一点。

【讨论】:

以上是关于在 CoreData 记录中进行更改,SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章

RestKit/CoreData 未更新 - 创建重复项

iPhone CoreData 属性:对 managedObjects 的更改太慢

coreData:从 NSSet 实体移动记录

神奇的记录 NSFetchedResultsController NSManagedObject 更改保存不工作

CoreData:错误:严重的应用程序错误。在核心数据更改处理期间捕获到异常

更新当前的 CoreData 条目