【问题标题】:How to filter an array of objects into different segments in Swift如何在 Swift 中将对象数组过滤到不同的段中
【发布时间】:2020-12-03 00:28:44
【问题描述】:

晚上好,

问题

我使用 GET 请求从 API 接收一组 Notes。每个笔记都有一个类型(ATC、成像和实验室)

问题是端点为我提供了所有笔记的列表,但我想按笔记类型将它们分成UISegmentedControl。即第 1 段有 ATC,第 2 段有成像,最后一段是实验室。

守则

笔记模型

var id: Int
var name: String?
var date: Date
var createdByFirstName: String?
var createdByLastName: String?
var type: String?
var isClosed: Bool

API 请求

func getAssociatedInjuryNotes(with injuryId: Int, completion: @escaping ((Result<[AssociatedInjuryNote], InjuryError>) -> Void)) {
        let baseURL = self.configuration.baseURL
        let endPoint = baseURL.appendingPathComponent("injury/\(injuryId)/notes")
        API.shared.httpClient.get(endPoint) { (result) in
            switch result {
            case .success(let response):
                do {
                    let injuryAssociatedNote = try API.jsonDecoder.decode([AssociatedInjuryNote].self, from: response.data)
                    completion(.success(injuryAssociatedNote))
                } catch (let error) {
                    completion(.failure(.unknown(message: error.localizedDescription)))
                }
            case .failure(let error):
                completion(.failure(.unknown(message: error.localizedDescription)))
            }
        }
    }

如何在视图控制器中获取数据

fileprivate class InjuryAssociatedNotesViewModel {
    private(set) var injuryId: Int
    @Published private(set) var injuryNotes: [AssociatedInjuryNote] = []
    @Published private(set) var error: String?

    init(injuryId: Int) {
        self.injuryId = injuryId
    }

    func refresh() {
        InjuryAPI.shared.getAssociatedInjuryNotes(with: injuryId) { (result) in
            switch result {
            case .success(let associatedNotes):
                self.injuryNotes = associatedNotes.sorted(by: {
                    $0.date.compare($1.date) == .orderedDescending
                })
            case .failure(let error):
                self.error = error.localizedDescription
            }
        }
    }

}

CollectionView 设置

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let viewModel = self.viewModel else { return UICollectionViewCell() }

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: NoteCell.reuseIdentifier, for: indexPath) as? NoteCell else { fatalError("Could not dequeue cell of type: '\(NoteCell.self)'") }


        let injuryAssociatedNote = viewModel.injuryNotes[indexPath.item]
        cell.configure(with: injuryAssociatedNote)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        guard let viewModel = self.viewModel else { return 0 }
        return viewModel.injuryNotes.count
    }

如果有人能指出我正确的方向,将不胜感激,我正在为此苦苦挣扎。

【问题讨论】:

    标签: ios swift xcode uikit


    【解决方案1】:

    一些事情:

    首先,鉴于音符类型的数量有限,我会将它们建模为枚举而不是字符串:

    enum NoteType {
        case atc
        case imaging
        case lab
    }
    

    如果您的后端提供了客户端无法识别的字符串,您始终可以添加 .unknown 大小写。为您的 NoteType 枚举提供一个原始类型的 String 并让每个 rawValue 对应于您的后端将提供的值也可能是有益的。

    其次,有点不清楚你想用UISegmentedControl 完成什么。我的假设是您想要为每种不同类型的 Note 设置一个单独的段?如果是这种情况,您可以使上述枚举符合CaseIterable 并为NoteTypeallCases 数组中找到的每个值创建一个段。 (如果你打算让NoteTypes 成为字符串,那么每个段的标题可以设置为每个案例的 rawValue)。这真的完全取决于你到底想要完成什么。

    第三,我认为最终你想要的是三个(或存在许多NoteTypes)单独的Notes 数组,其中每个Note 的类型相同。这样您就可以根据选择的UISegmentedControl 的哪个段来确定您的UICollectionView 的数据源是什么。如果这就是您想要的(请随时纠正我),您可以通过一个简单的过滤器调用来实现:

    let sortedNotes = associatedNotes.sorted(by: {
        $0.date.compare($1.date) == .orderedDescending
    })
    let atcNotes = sortedNotes.filter { $0.type == .atc }
    let imagingNotes = sortedNotes.filter { $0.type == .imaging }
    let labNotes = sortedNotes.filter { $0.type == .lab }
    

    【讨论】:

    • 首先,感谢您的及时和翔实的回复。它在帮助我:)。你完全理解我想要做什么,我想把每个笔记类型分成一个片段。所以我用原始值创建了 NoteType 枚举,我添加了代码来对 API 调用中的注释进行排序。现在我不知道在哪里使用排序值(atcNotes、imagingNotes、labNotes)。我是否会在 cellForItemAt 中编写一些逻辑,并且我是否需要像在 API 调用中处理伤害笔记一样为每个笔记创建一个 @Published var
    • 如果不知道你的 UI 设置的范围和这里所有类的逻辑,很难完全回答你的问题,但我会尽我所能回答:“我需要为每个笔记创建一个 @Published var,就像我在 API 调用中处理伤害笔记一样”是的,你可能需要三个类级别的数组,就像你有 injuryNotes
    • “现在我不知道在哪里使用排序值”——如果不确切知道你想要完成什么,这是不可能回答的。我的猜测是你想在一个列表中显示所有的笔记?如果是这样,您将需要一个单独的 UI 组件(UICollectionView 或 UITableView)。 UISegmentedControl 将用于切换集合显示的笔记类型
    • “我可以在 cellForItemAt 中写一些逻辑吗”——如果不知道代码的结构,这也是无法回答的。 UISegmentedControl 和 UICollectionView 是否会存在于您调用 configure 的 UICollectionViewCell 中?如果是这样,也许它们被传递到configure 方法中,并且您的集合的数据源被设置在那里。同样,这完全是猜测,不知道您要做什么
    猜你喜欢
    • 2020-11-01
    • 2019-02-27
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    相关资源
    最近更新 更多