[英]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
并为NoteType
的allCases
数组中找到的每个值创建一个段。 (如果您打算让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.