【发布时间】:2020-07-14 12:45:41
【问题描述】:
我的大部分功能都可以正常工作并返回我想要的东西。但是,当谈到在response 中获取photos 数组并将它们分配给适当的employees 以便能够渲染它们时,我有点脑残。这是发生了什么:
- 有 4 个可编码结构:
Response、Company、Employee和ProfileImages。Response是API返回的主对象,然后解码成Company,有一个[Employee]的数组,每个有3个ProfileImages(大小分别为小、中、大) - 有一个
companyPublisher获取company详细信息以及employees数组 - 然后有一个
photosPublisher,它从上一步中获取employees数组并对它们进行排序,以便能够检索他们的profileImages.large个人资料图片 - 最后,我有一个
Publishers.Zip(companyPublisher, photosPublisher),它设置发布者的.sink(),以便在获取所有请求的内容后以完成响应。
有人可以建议我需要采取哪些适当的步骤才能将正确的员工形象分配给实际员工?我正在考虑在Employee 可编码结构中设置一个可选的UIImage 类型property,但我仍然不确定如何将适当的Future 对象分配给该员工。
任何帮助将不胜感激。提前致谢!
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"
}
}]
}
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)
}
}
【问题讨论】:
-
@NewDev 是的,这确实帮助我最初制定我的算法以输出正确的响应......我正在努力!现在我只是停留在如何将适当的嵌套未来照片对象(每个 Employee 的 ProfileImage.large)关联到它们的相关数组元素(作为公司返回的员工数组中的 Employee)
标签: ios swift combine urlsession