核心数据 - 再次获取 JSON 时,收藏的帖子变得重复

Posted

技术标签:

【中文标题】核心数据 - 再次获取 JSON 时,收藏的帖子变得重复【英文标题】:Core Data - Favorited posts become duplicate when fetching JSON again 【发布时间】:2021-03-15 11:30:53 【问题描述】:

在我的应用程序中,我获取 Json 条目并将其直接保存在 CoreData 中。 我在实体中添加了额外的 Boolean IsFavorite(默认为 False),让用户标记为收藏并在单独的视图中显示。

到目前为止一切都很好,问题是当我再次从更新的 json 获取内容以引用内容时,女巫已经最喜欢的帖子被复制了。

这就是我获取和保存数据的方式:

class JSONViewModel: ObservableObject 

    @Published var listings: [ListingModel] = []
  //  @Published var tags :[Tags] = []
    // saving Json to Core Data...
    
    func saveData(contex: NSManagedObjectContext) 
        
        listings.forEach  (data) in
            
            let entity = Listing(context: contex)
           // entity.id = Int64(data.id)
            entity.title = data.title
            entity.name = data.name
            entity.expires = data.expires
            entity.adresa = data.adresa
            entity.listingtype = data.listingtype
            entity.latitude = Double(truncating: NSNumber(value: data.latitude))
            entity.longitude = Double(truncating: NSNumber(value: data.longitude))
            entity.isFavorite = false
           
        

        // saving all pending data at once
        
        do
            try contex.save()             
            print("success")
        
        catch
            print(error.localizedDescription)
        
    
    
    func fetchData(context: NSManagedObjectContext)
        
        let url = "https://... my json"
        
        var request = URLRequest(url: URL(string: url)!)
        request.addValue("swiftui2.0", forHTTPHeaderField: "field")
        
        let session = URLSession(configuration: .default)
        
        session.dataTask(with: request)  (data, res, _) in
            
            guard let jsonData = data elsereturn
            
            // check for errors
            
            let response = res as! HTTPURLResponse
            // checking by status code
            
            if response.statusCode == 404 
                print("error Api Errror")
            
            
            // fetching JSON Data ..
            do 
                let listings = try JSONDecoder().decode([ListingModel].self, from: jsonData)
                
                DispatchQueue.main.async 
                  
                    self.listings = listings
                    self.saveData(contex: context)
                
            
            catch 
                print(error.localizedDescription)
            
        
        
        
        
        .resume()
    

我使用此代码将帖子标记为收藏:

 Button(action:  fetchedData!.isFavorite.toggle();
                            do 
                                try context.save()   
                            
                            catch 
                                print(error)   
                             )  Image(systemName: fetchedData!.isFavorite ? "heart.circle.fill" : "heart.circle")

在 ContentView 上,我会像这样加载最新的帖子:

  HStack 
                    // checkin if core data exists
                    if results.isEmpty
                        
                        if jsonModel.listings.isEmpty
                            
                            HStack(alignment: .center) 
                                HStack(spacing: 10) 
                                    ProgressView()
                        
                                        .progressViewStyle(CircularProgressViewStyle(tint: Color("dinamicPillsGrass")))
                                        .scaleEffect(2, anchor: .center)
                                        // fetching data
                                        .onAppear(perform: 
                                            jsonModel.fetchData(context: context)
                                            
                                    )
                                .frame(width: UIScreen.main.bounds.width)
                            .modifier(cardHeight())
                            
                            // when array is clear indicator appears
                            // as result data is fetched again
                        
                        else
                            
                            HStack(spacing: 20) 
                                
                                
                                ForEach(jsonModel.listings,id: \.self)listing in
                                    NavigationLink (destination: CardDetailView(listing: listing)) 
                                        
                                        HStack 
                                            CardViewOrizontal(listing: listing)
                                        
                                    .buttonStyle(PlainButtonStyle())
                                    // display fetched Json Data..
                                
                            
                        
                        
                    
                    
                    else
                        // results.prefix(?) unde ? cata articole sa arate
                       HStack(spacing: 20) 
                        ForEach(results.prefix(10))listing in
                               
                                NavigationLink (destination: CardDetailView(fetchedData: listing)) 
                                    
                                    HStack 
                        CardViewOrizontal(fetchedData: listing)
                                    
                                .buttonStyle(PlainButtonStyle())
                            
                        
                        .padding(.trailing, 15)
                        .padding(.leading, 15)
   
                    
                    // update finish
                    
                .padding(.top, 10)

我像这样更新数据: 注意:我还会检查 Internet 连接。

                Button(action: 

                    // clearing data in core data..

                    if Reachability.isConnectedToNetwork() 
                      //
                        do
                        
                            jsonModel.listings.removeAll()
**// This code is deleteing all the saved posts - also the favorite ones**                            
//                      results.forEach  (listing) in
//                                context.delete(listing)
//                                
 
**// this code is duplicating only the favorite posts**
                            results.forEach  (listing) in

                                if  listing.isFavorite.self == false 
                                    context.delete(listing)
                                    jsonModel.listings.removeAll()
                                
                                else 
                                    jsonModel.fetchData(context: context)
                                
                            
                            
                            try context.save()
                        
                        catch
                            print(error.localizedDescription)
                        
                        print("Network is connected")
                        self.isError = false
               
                     else 

                        print("Network is not connected")
                        self.isError = true
                    
 
                , label: 
                    HStack(alignment: .center) 
                        Image(systemName: "icloud.and.arrow.down")
                            .modifier(textSectionIcon())
                        Text("Update")
                            .modifier(textSectionTagline())
                    
                    .padding(5)
                    .padding(.trailing, 5)
                    .background(Color("blueLeading"))
                    .cornerRadius(20)
                    .modifier(shadowPills())
                ).alert(isPresented: $isError) 
                    Alert(title: Text("Network is not connected"),
                          message: Text("WiFi or Cellular not availible. You can still browse offline content!"),
                          dismissButton: .default(Text("OK")))
                

如何在不复制收藏的帖子的情况下更新获取?

【问题讨论】:

很明显,当帖子不是收藏夹时,您将其删除,但如果它是收藏夹,则您不收藏(这很好),而是下载并插入 all发布到核心数据。您对每个收藏夹都执行此操作,因此对于 2 个收藏夹,您实际上将下载帖子两次,最终在您的存储中获得三份收藏夹和复制非收藏夹。您需要重新考虑 fetchData 应该如何工作,也需要重新考虑如何调用它,现在它太粗糙了。也许在插入之前检查帖子是否已经存在。 嗨。您将使用 JSON 中的什么值来确定该列表是否已存在于您的核心数据中?我看到您已将 ID 注释掉。可以重新介绍吗? 您好 rlong405 - 请查看更新。谢谢 【参考方案1】:

我用过 受 id 约束 并介绍:

 container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy

`现在数据是唯一的,下一个问题是,当我获取 agian 时,收藏夹现在被抹掉了!

这里有新问题:Update CoreData when fetch again from online Json

【讨论】:

以上是关于核心数据 - 再次获取 JSON 时,收藏的帖子变得重复的主要内容,如果未能解决你的问题,请参考以下文章

核心数据自动更新查询

知乎上关于数据分析和数据挖掘帖子的收藏~

MagicalRecord:删除整个数据并再次设置核心数据堆栈

在通过核心数据获取数据的同时,自动再次插入已有的行

从子数组 JSON IOS 获取数据

获取调用的 JSON 函数时复制数据