问题描述
我的大部分功能都可以正常工作并返回我想要的功能.但是,在将 photos
数组放入 response
中并将它们分配给适当的 employees
时,我有点放屁.能够渲染它们.这是怎么回事:
I have majority of the functionality working and returning exactly what I want. However, I'm having bit of a brain fart when it comes to taking the photos
array in the response
and assigning them to appropriate employees
to be able to render them. Here's what's going on:
- 有4种可编码结构:
响应
,公司
,Employee
和ProfileImages
.Response
是API返回的主要对象,然后解码为具有[Employee]
数组的Company
,每个都有3xProfileImages
(大小不一) - 有一个
companyPublisher
可以获取company
的详细信息以及一组employees
- 然后有一个
photosPublisher
,它从上一步中获取employees
数组,并对它们进行排序,以便能够检索其profileImages.large
个人资料图像 - 最后,我有一个
Publishers.Zip(companyPublisher,photosPublisher)
,用于设置发布者的.sink()
以在完成请求的所有内容后做出响应
- There are 4x Codable structs:
Response
,Company
,Employee
, andProfileImages
.Response
is the main object returned by the API and then decoded intoCompany
having an array of[Employee]
, each have 3xProfileImages
(small, medium, and large in size) - There's a
companyPublisher
that fetches thecompany
details along with an array ofemployees
- Then there's a
photosPublisher
which takesemployees
array from the previous step and sequences them to be able to retrieve theirprofileImages.large
profile image - At last, I have a
Publishers.Zip(companyPublisher, photosPublisher)
that sets up the publisher's.sink()
to respond with completion once everything requested has been fetched.
有人可以建议我需要采取哪些适当的步骤,才能将正确的员工形象分配给实际员工?我当时在考虑在 Employee
可编码结构中设置一个可选的 UIImage
类型 property
,但仍不确定如何分配合适的将来会反对该雇员.
Can someone advise what would be the appropriate steps I need to take to be able to assign the correct employee image to the actual employee? I was thinking about setting up an optional UIImage
type property
inside the Employee
codable struct but am still unsure on how I would go about assigning the appropriate Future object to that employee.
任何帮助将不胜感激.预先感谢!
Any help would be greatly appreciated. Thanks in advance!
Response.JSON
:
{
"success": true,
"company": {
"id": 64,
"name": "XYZ (Birmingham, AL)",
"enabled": true
},
"employees": [{
"id": 35,
"name": "Chad Hughes",
"email": "[email protected]",
"profileImages": {
"small": "https://via.placeholder.com/150/09f/fff.png",
"medium": "https://via.placeholder.com/300/09f/fff.png",
"large": "https://via.placeholder.com/600/09f/fff.png"
}
}, {
"id": 36,
"name": "Melissa Martin",
"email": "[email protected]",
"profileImages": {
"small": "https://via.placeholder.com/150/F2A/fff.png",
"medium": "https://via.placeholder.com/300/F2A/fff.png",
"large": "https://via.placeholder.com/600/F2A/fff.png"
}
}]
}
Models.swift
(可编码结构):
struct Response: Codable {
let success: Bool
let company: Company
let employees: [Employee]
let message: String?
}
struct Company: Codable, Identifiable {
let id: Int
let name: String
let enabled: Bool
}
struct Employee: Codable, Identifiable {
let id: Int
let name: String
let email: String
let profileImages: ProfileImage
let profileImageToShow: SomeImage?
}
struct SomeImage: Codable {
let photo: Data
init(photo: UIImage) {
self.photo = photo.pngData()!
}
}
struct ProfileImage: Codable {
let small: String
let medium: String
let large: String
}
CompanyDetails.swift
:
class CompanyDetails: ObservableObject {
private let baseURL = "https://my.api.com/v1"
@Published var company: Company = Company()
@Published var employees: [Employee] = []
var subscriptions: Set<AnyCancellable> = []
func getCompanyDetails(company_id: Int) {
let url = URL(string: "\(baseURL)/company/\(company_id)")
// Company Publisher that retrieves the company details and its employees
let companyPublisher = URLSession.shared.dataTaskPublisher(for url: url)
.map(\.data)
.decode(type: Response.self, decoder: JSONDecoder())
.eraseToAnyPublisher()
// Photo Publisher that retrieves the employee's profile image in large size
let photosPublisher = companyPublisher
.flatMap { response -> AnyPublisher<Employee, Error> in
Publishers.Sequence(sequence: response.employees)
.eraseToAnyPublisher()
}
.flatMap { employee -> AnyPublisher<UIImage, Error> in
URLSession.shared.dataTaskPublisher(for url: URL(string: employee.profileImages.large)!)
.compactMap { UIImage(data: $0.data) }
.mapError { $0 as Error }
.eraseToAnyPublisher()
}
.collect()
.eraseToAnyPublisher()
// Zip both Publishers so that all the retrieved data can be .sink()'d at once
Publishers.Zip(companyPublisher, photosPublisher)
.receive(on: DispatchQueue.main)
.sink(
receiveCompletion: { completion in
print(completion)
},
receiveValue: { company, photos in
print(company)
print(photos)
}
)
.store(in: &subscriptions)
}
}
推荐答案
您已经快到了,但是您需要"zip"在内部(嵌套)级别,即在 flatMap
内:
You're almost there, but you need to "zip" at an inner (nested) level, ie. inside the flatMap
:
let employeesPublisher = companyPublisher
.flatMap { response in
response.employees.publisher.setFailureType(Error.self)
}
.flatMap { employee -> AnyPublisher<(Employee, UIImage), Error> in
let profileImageUrl = URL(string: employee.profileImages.large)!
return URLSession.shared.dataTaskPublisher(for url: profileImageUrl)
.compactMap { UIImage(data: $0.data) }
.mapError { $0 as Error }
.map { (employee, $0) } // "zip" here into a tuple
.eraseToAnyPublisher()
}
.collect()
现在您有了一个由雇员和个人资料图像组成的元组数组.同样,您也可以检索所有配置文件图像,例如,使用 Publishers.Zip3
.
Now you have and array of tuples of employee and the profile image. Similarly, you could also retrieve all the profile images, for example, by using Publishers.Zip3
.
编辑
如果要更新 employee
值而不是返回元组,则可以返回已更新的雇员:
If you want to update the employee
value instead of returning a tuple, you can instead return the updated employee:
// ...
.map {
var employeeCopy = employee
employeeCopy.profileImageToShow = SomeImage(photo: $0)
return employeeCopy
}
// ...
这为您提供了一组具有 profileImageToShow
属性集的员工,您可以根据需要使用原始响应对 .zip
进行设置:
What this gives you is an array of employees with profileImageToShow
property set, which you can .zip
with the original response, as you wanted:
Publishers.Zip(companyPublisher, employeesPublisher)
.receive(on: DispatchQueue.main)
.sink { (response, employees) in
self.company = response.company
self.employees = employees
}
.store(in: &subscriptions)
这篇关于使用2x Publisher快速组合URLSession检索数据集/照片的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!