繁体   English   中英

如何在 Swift 中将对象数组过滤成不同的段

[英]How to filter an array of objects into different segments in Swift

晚上好,

问题

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

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

编码

注意 Model

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)))
            }
        }
    }

我如何在视图 controller 中获取数据

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
            }
        }
    }

}

集合视图设置

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
    }

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

一些东西:

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

enum NoteType {
    case atc
    case imaging
    case lab
}

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

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

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

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 }

暂无
暂无

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

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