Возможно, следует разделить структуру Book на две структуры. Первый из них называется BookInfo , и их массив загружается с вызовом функции search .
struct BookInfo {
let title: String
let authors: [String]
let coverImageURL: URL
}
Создание экземпляра BookInfo вместе с данными coverImage может привести к Book структуре, подобной этой:
struct Book {
let bookInfo: BookInfo
let coverImage: Data
}
Цепочка RxSwift будет выглядеть так:
self.search(query: "<someQuery>")
.flatMap { (bookInfos: [BookInfo]) -> Observable<BookInfo> in
Observable.from(bookInfos)
}
.flatMap { (bookInfo: BookInfo) -> Observable<Book> in
//use the coverImageURL from the closure parameter and fetch the coverImage
//return an Observable<Book>
}
.observeOn(MainScheduler.instance)
.do(onNext: { (book: Book) in
//e.g. add a book in main thread to the UI once the cover image is available
})
.subscribe()
.disposed(by: disposeBag)
Вместо использования вывода типов я добавил явные спецификации типов, чтобы было более очевидно, какие элементы передаются по цепочке.
UPDATE
Если вы хотите использовать только одну Книгу структуру, вы можете использовать это:
self.search(query: "<someQuery>")
.flatMap { (books: [Book]) -> Observable<Book> in
Observable.from(books)
}
.flatMap { (book: Book) -> Observable<Book> in
//use the book.coverImageURL from the closure parameter and fetch the coverImage
//since the closure parameter 'book' is a let constant you have to construct a new Book instance
//return an Observable<Book>
}
...
Обратите внимание, что параметры замыкания являются let константами. Это означает, что вы не можете изменить свойство coverImage , даже если оно определено как var в структуре. Вместо этого вы должны создать новый экземпляр структуры Book, заполнить его значениями из параметра Closure и добавить данные coverImage . Соответственно, если вы хотите пойти по этому маршруту, вы также можете изменить coverImage на let константу.
Полагаю, лично я бы предпочел первый подход к двум структурам.