Pau*_*vis 5 ios swift urlsession combine
我的大部分功能都在工作,并且返回的正是我想要的。photos然而,当涉及到将数组放入response并将它们分配给适当的位置employees以便能够渲染它们时,我有点脑残。这是发生的事情:
Response、Company、Employee和ProfileImages。Response是 API 返回的主要对象,然后解码为Company一个数组[Employee],每个数组有 3x ProfileImages(小、中、大尺寸)companyPublisher可以获取company详细信息以及一系列employeesphotosPublisher获取employees数组并对它们进行排序以便能够检索其profileImages.large个人资料图像Publishers.Zip(companyPublisher, photosPublisher)设置发布者.sink()在获取所有请求的内容后响应完成。有人可以建议我需要采取哪些适当的步骤才能将正确的员工图像分配给实际员工?我正在考虑在可编码结构中设置一个可选UIImage类型,但仍然不确定如何将适当的 Future 对象分配给该员工。propertyEmployee
任何帮助将不胜感激。提前致谢!
Response.JSON:
{
"success": true,
"company": {
"id": 64,
"name": "XYZ (Birmingham, AL)",
"enabled": true
},
"employees": [{
"id": 35,
"name": "Chad Hughes",
"email": "chad.hughes@company.com",
"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": "melissa.martin@company.com",
"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"
}
}]
}
Run Code Online (Sandbox Code Playgroud)
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
}
Run Code Online (Sandbox Code Playgroud)
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)
}
}
Run Code Online (Sandbox Code Playgroud)
你已经快到了,但是你需要在内部(嵌套)级别“压缩”,即。在 - 的里面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()
Run Code Online (Sandbox Code Playgroud)
现在您拥有员工元组和个人资料图像的数组。同样,您也可以检索所有个人资料图像,例如使用Publishers.Zip3.
编辑
如果您想更新employee值而不是返回元组,则可以返回更新后的员工:
// ...
.map {
var employeeCopy = employee
employeeCopy.profileImageToShow = SomeImage(photo: $0)
return employeeCopy
}
// ...
Run Code Online (Sandbox Code Playgroud)
这为您提供了一组具有profileImageToShow属性集的员工,您可以.zip根据需要使用原始响应:
Publishers.Zip(companyPublisher, employeesPublisher)
.receive(on: DispatchQueue.main)
.sink { (response, employees) in
self.company = response.company
self.employees = employees
}
.store(in: &subscriptions)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1504 次 |
| 最近记录: |