繁体   English   中英

SwiftUI、Combine 和 Core Data — 未正确映射/显示的项目

SwiftUI, Combine, and Core Data — Items not being mapped/displayed properly

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我是 SwiftUI 和 Combine 的新手,并且有一个用于测试的简单项目。 我正在使用本文中概述的CDPublisher类来创建 Core Data 和 Combine 之间的桥梁。 我已经声明了一个名为ItemEntity的核心数据实体类。 它有一个属性,一个String ,包含一个序列化的 JSON 对象。 此对象反序列化为名为Item的结构。 我的 SwiftUI 视图只显示从我的 ViewModel 返回的项目列表:

struct ContentView: View {
    
    @ObservedObject
    var viewModel: MyListViewModel
    
    var body: some View {
        NavigationView {
            List {
                ForEach(viewModel.items, id: \.self.id) { item in
                    Text("\(item.name) - \(item.createdDate)")
                }
            }
            .onAppear {
                self.viewModel.fetchItems()
            }
            .toolbar {
                Button(action: addItem) {
                    Label("Add Item", systemImage: "plus")
                }
            }
        }
    }
    
    private func addItem() {
        let entity = ItemEntity(context: viewContext)
        let rand = arc4random()
        var model = Item(name: "Item \(rand)", createdDate: Date())
        model.id = UUID().uuidString
        let jsonData = try! JSONEncoder().encode(model)
        
        entity.modelJSON = String(data: jsonData, encoding: .utf8)
        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("\(nsError) - \(nsError.userInfo)")
        }
    }
}

我的ViewModel使用CDPublisher类从 Core Data 中获取实体。 它还有一个 map 函数,可以将每个条目中的 JSON 字符串反序列化为一个Item实例。 最终,一个Item对象Array是通过我的ViewModel可用的。 它看起来像这样:

import Foundation
import CoreData
import Combine
import SwiftUI

class MyListViewModel: ObservableObject {
    
    private var viewContext: NSManagedObjectContext =  PersistenceController.shared.container.viewContext
    
    @Published
    var items: [Item] = []
    
    private var cancellables = [AnyCancellable]()
    
    func fetchItems() {
        print("FETCHING...")
        
        let decoder = JSONDecoder()
        let fetchReq: NSFetchRequest<ItemEntity> = ItemEntity.fetchRequest()
        CoreDataPublisher(request: fetchReq, context: self.viewContext)
            .map({ (entities: [ItemEntity]) -> [Item] in
                var items: [Item] = []
                entities.forEach { (entity: ItemEntity) in
                    if let json = entity.modelJSON?.data(using: .utf8) {
                        if let item = try? decoder.decode(Item.self, from: json) {
                            items.append(item)
                        }
                    }
                }
                
                return items
            })
            .receive(on: DispatchQueue.main)
            .replaceError(with: [])
            .eraseToAnyPublisher()
            .sink { completion in
                print("COMPLETION : \(completion)")
            } receiveValue: { items in
                print("SUCCESS")
                items.forEach { (item) in
                    print("\t\(item)")
                }
                self.items = items
            }.store(in: &cancellables)
    }
}

我的代码编译并成功运行。 我看到打印语句源自我的fetchItems()方法,表明我的 items 数组包含所有预期的对象:

FETCHING...
SUCCESS
    Item(name: "Item 854277542", createdDate: 2021-01-25 19:19:16 +0000)
    Item(name: "Item 92334228", createdDate: 2021-01-25 19:19:17 +0000)
    Item(name: "Item 405319813", createdDate: 2021-01-25 19:19:18 +0000)
    Item(name: "Item 121330574", createdDate: 2021-01-25 19:19:18 +0000)
    Item(name: "Item 3025980536", createdDate: 2021-01-25 19:19:19 +0000)
    Item(name: "Item 1278077958", createdDate: 2021-01-25 19:19:19 +0000)
    Item(name: "Item 4274618146", createdDate: 2021-01-25 19:19:19 +0000)
    Item(name: "Item 2320455869", createdDate: 2021-01-25 19:19:19 +0000)
    Item(name: "Item 3542559526", createdDate: 2021-01-25 19:19:22 +0000)
    Item(name: "Item 4217121551", createdDate: 2021-01-25 19:19:23 +0000)
    Item(name: "Item 4139555338", createdDate: 2021-01-25 19:19:24 +0000)
    Item(name: "Item 1345067436", createdDate: 2021-01-25 19:20:49 +0000)

但是,我的 UI 没有按预期显示项目。 我希望每个Item对象都有一行。 相反,我看到多行,但它们都具有与数组中的第一个Item匹配的完全相同的文本。 它本质上是一遍又一遍地重复同一行。

我显然在这里做错了什么,但我没有足够的经验来确切知道是什么。 为什么我的 items 属性具有正确的值,但我没有看到在我的 UI 中反映出来? 是因为我的地图功能和 JSON 解码吗? (此外,是否有更好的方法来完成将ItemEntity实体数组映射到Item对象数组?)有什么提示吗?

更新:以下是我的Item结构的定义

import Foundation

struct Item {
    
    var name: String = ""
    var createdDate: Date = Date()
    
}

extension Item: Codable {
    
}

extension Item: Identifiable {
    private struct IdentifiableHolder {
        static var _id: String = ""
    }
    
    var id: String {
        get {
            return IdentifiableHolder._id
        }
        set(newId) {
            IdentifiableHolder._id = newId
        }
    }
}
1 个回复

您为fetchItems显示的代码没有任何内容确保您解码的 Item 对象具有唯一的id值 - 但 List 明确依赖于这些( id: \\.self.id )。 相反,您的所有 Item 对象都具有默认id ,即"" 因此,该id的每个Item对象的是id第一Item对象的,说明的现象。

你可能一直在追求这样的事情:

struct Item : Codable {
    var name: String = ""
    var createdDate: Date = Date()
    private var idHolder = IdentifiableHolder(id: UUID().uuidString)
}

extension Item: Identifiable {
    private struct IdentifiableHolder : Codable {
        var id: String = ""
    }
    var id: String {
        get {
            return idHolder.id
        }
        set(newId) {
            idHolder.id = newId
        }
    }
}

现在每个项目都有一个唯一的 ID,它作为其 Codable 实现的一部分进行存储和检索。

1 SwiftUI 列表未显示任何项目

我想将 NavigationView 与 ScrollView 一起使用,但我没有看到列表项。 我看到的只有文字。 如果我删除 ScrollView,我会看到所有内容,但文本会被推到最底部。 我只是希望能够在一个漂亮的可滚动页面中添加列表和视图。 ...

2 SwiftUI 图像未正确显示为叠加层

我正在尝试实现一个自定义的“使用苹果登录”按钮: 它看起来像一个静态的 RoundedRectangle: 但它不会正确显示为按钮的叠加: 我该如何解决? ...

3 工具栏未正确显示 SwiftUI

在我的 GeneralView 中,我有一个 NavigationView 和一个选项卡视图。 在每个 tabItem 中,我使用一些 ZStack 导航(使用 zIndex,隐藏和显示项目) 随机前导和尾随项目未正确显示且无法单击。 见下文,屏幕顶部的后退按钮未满。 但是我选择了相同的按钮来打开 ...

4 SwiftUI 列表未显示所有项目

我正在尝试在 iOS 中显示横向滚动列表列表。 一些列表显示,但其他列表不显示,即使它们都有数据。 我放了一个调试点,看到每个部分都调用了带有EventItemView的ForEach 。 我不确定我做错了什么。 事件屏幕 事件部分视图 事件项视图 ...

5 使用Combine 和SwiftUI 显示变化值的最简洁方法是什么?

我正在尝试围绕 SwiftUI 和组合进行思考。 我想让 UI 中的一些文本带有一个值是最新的。 例如,在这种情况下,它是设备的电池电量。 这是我的代码。 首先,这似乎是实现我想要做的事情的相当多的代码,所以我想知道我是否可以不用其中的一些代码。 此外,这段代码曾经在整个夏天运行,但现在它崩溃了, ...

6 我在 SwiftUI 中设计的堆栈视图未正确显示

我还在学习 Swift UI。 但是,我想模拟我的 UI 设计以在 SwiftUI 中显示,但由于某种原因它没有完全正确显示。 任何人都可以指导我在我的代码中做错了什么,而不是像我的 UI 设计那样显示吗? 谢谢您的帮助。 这是我的 UI 设计: https : //imgur.com/a/y6I ...

2020-01-23 03:39:34 1 91   swiftui
7 砌体未正确显示项目

我正在使用砌体jquery插件在容器中排列一些图像,该插件似乎正在工作,但未正确显示项目。 有可以由项目填充的空间,但项目是“浮动”在下一行的左侧,这不应该发生。 可以在这里看到问题: http : //riley87.co.uk/theme/ionic/portfolio-masonr ...

2014-07-19 16:56:46 1 483   masonry
9 Jetpack Compose LazyList 未正确显示项目

世界! 我使用 Jetpack Compose 已经有一段时间了,而且效果非常好。 但是,我发现了这个问题:我有一个项目列表,我使用LazyColumn将它们显示给用户。 但是当我向上和向下滚动时,有些项目没有正确显示,它们看起来就像没有信息一样。 我不知道我是否遗漏了什么,或者这种行为将来会得 ...

10 RecyclerView的项目未正确显示

在我的onBindViewHolder我的RecyclerView.Adapter&lt;SearchAdapter.ViewHolder&gt;当用户点击cardview按钮变得可见。 但是当我滚动recyclerview时,其他一些项目按钮也显示为可见。 为什么会这样? 这是我的代 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM