I'm facing this issue while trying to nest 2 network API using RxSwift, the flatMap keeps saying type of expression is ambiguous. I'm new to RxSwift so this takes me almost 2 days but no clues. I tried to declare every thing explicit but not helping.
I'm not sure why it didn't know the return type of the closure. Here is full code:
private func uploadImage(imageUrl: URL) -> Observable<String> {
do {
let data = try Data(contentsOf: imageUrl)
let fileExtension = imageUrl.pathExtension
return Single<String>.create(subscribe: { single in
AppManager.shared.dataAdapter.apiCallUploadDocument(data: data, fileExtension: fileExtension) { result in
switch result {
case .success(let documentId):
single(.success(documentId))
case .failure(let error):
single(.failure(error))
}
}
return Disposables.create()
}).asObservable()
} catch let error {
return Observable.error(error)
}
}
func subscribePlan(data: SCSubscribeData) -> Observable<PurchaseResponse> {
let settings = AppManager.shared
let idCardPhoto = data.idCardPhoto
let governmentPassportPhoto = data.governmentPasspordIdPhoto
let isUserProfileUpdated = settings.loginResult.profileUpdated
if isUserProfileUpdated {
let icDocumentType = settings.eligibilityInput.getSubscriberData()["idType"] ?? ""
return uploadImage(imageUrl: idCardPhoto.url)
.flatMap({ documentId in
let param: [String: String] = [
"eligibilityDocument": documentId,
"icDocument": "EXISTED",
"icDocumentType": icDocumentType,
"eligibilityDocumentNo": data.idNumber,
]
let scAdditionalParameter: [String : AnyObject] = [
"properties": param
]
return subscribe(purchaseModel: data.purchaseModel, additionalParam: scAdditionalParameter)
})
}
return Observable<PurchaseResponse>.error(NSError())
}
func subscribe(purchaseModel: PurchaseModel, additionalParam: [String: AnyObject]) -> Observable<PurchaseResponse> {
return Single.create(subscribe: { single in
AppManager.shared.dataAdapter.apiCallPurchaseSubscription(purchaseModel: purchaseModel,
additionalParameter: additionalParam,
result: { result in
switch result {
case .success(let res):
single(.success(res))
case .failure(let error):
single(.failure(error))
}
})
return Disposables.create()
}).asObservable()
}
The fundamental problem here is that you are using dictionaries of type [String: AnyObject]
and then trying to put non-Objects in them. The param
type is not an Object (class type), it's a Dictionary (struct type). Use [String: Any]
instead.
It might be instructive to show how I figured out the problem. I simply moved the offending closure into its own function:
func purchaseResponse(data: SCSubscribeData, icDocumentType: String, documentId: String) -> Observable<PurchaseResponse> {
let param: [String: String] = [
"eligibilityDocument": documentId,
"icDocument": "EXISTED",
"icDocumentType": icDocumentType,
"eligibilityDocumentNo": data.idNumber,
]
let scAdditionalParameter: [String : AnyObject] = [
"properties": param
]
return subscribe(purchaseModel: data.purchaseModel, additionalParam: scAdditionalParameter)
}
By doing this, the error jumps right out. Also, if you want, you can curry the above function and use it in the original code:
import Curry // https://github.com/thoughtbot/curry
func subscribePlan(data: SCSubscribeData) -> Observable<PurchaseResponse> {
let settings = AppManager.shared
let idCardPhoto = data.idCardPhoto
let governmentPassportPhoto = data.governmentPasspordIdPhoto
let isUserProfileUpdated = settings.loginResult.profileUpdated
if isUserProfileUpdated {
let icDocumentType = settings.eligibilityInput.getSubscriberData()["idType"] ?? ""
return uploadImage(imageUrl: idCardPhoto.url)
.flatMap(curry(purchaseResponse)(data)(icDocumentType))
}
return Observable<PurchaseResponse>.error(NSError())
}