В RxJS вы можете использовать значение из наблюдаемого для нового наблюдаемого. Например:

this.authService.login(username, password).pipe(
  switchMap((success: boolean) => {
    if(success) {
      return this.contactService.getLoggedInContact()
    } else {
      return of(null)
    }
  })
).subscribe(contact => {
  this.contact = contact
})

Но теперь мне нужно сделать проект на Swift, и я хочу добиться того же. Я могу заставить работать два метода, но использование результата первой наблюдаемой для второй наблюдаемой - это то, с чем я не могу работать. Канал switchMap - это то, чего нет в RxSwift, и я не могу найти эквивалент.

Я попытался сопоставить результат функции входа в систему с наблюдаемым, а затем сопоставить его, но, к сожалению, это не сработало.

Как лучше всего сделать это в Swift без подписки в подписке?

ИЗМЕНИТЬ Я пробовал плоскую карту:

APIService.login(email: "username", password: "password")
  .flatMapLatest { result -> Observable<Contact> in
    if result {
      return APIService.getLoggedInContact()
    } else {
      return .of()
    }
  }.subscribe(onNext: {result in
    print("Logged in contact: \(result)")
  }, onError: {Error in
    print(Error)
  }).disposed(by: disposeBag)

Но, к сожалению, это не сработало, я получаю сообщение об ошибке Thread 1: EXC_BAD_ACCESS (code=1, address=0x13eff328c)

EDIT2 :

Это функция входа в систему

static func login(email: String, password: String) -> Observable<Bool> {
        return Observable<String>.create { (observer) -> Disposable in
            Alamofire.request(self.APIBASEURL + "/contact/login", method: .post, parameters: [
                "email": email,
                "password": password
            ], encoding: JSONEncoding.default).validate().responseJSON(completionHandler: {response in
                if (response.result.isSuccess) {
                    guard let jsonData = response.data else {

                        return observer.onError(CustomError.api)
                    }
                    let decoder = JSONDecoder()

                    let apiResult = try? decoder.decode(ApiLogin.self, from: jsonData)
                    return observer.onNext(apiResult!.jwt)
                } else {
                    return self.returnError(response: response, observer: observer)
                }
            })

            return Disposables.create()
        }.map{token in
            return KeychainWrapper.standard.set(token, forKey: "authToken")
        }
    }

Это функция getLoggedInContact

static func getLoggedInContact() -> Observable<Contact> {
        return Observable.create { observer -> Disposable in
            Alamofire.request(self.APIBASEURL + "/contact/me", method: .get, headers: self.getAuthHeader())
              .validate().responseJSON(completionHandler: {response in
                if (response.result.isSuccess) {
                    guard let jsonData = response.data else {

                        return observer.onError(CustomError.api)
                    }

                    let decoder = JSONDecoder()
                    decoder.dateDecodingStrategy = .formatted(.apiNewsDateResult)

                    let apiResult = try? decoder.decode(Contact.self, from: jsonData)
                    return observer.onNext(apiResult!)
                } else {
                    return self.returnError(response: response, observer: observer)
                }
            })

            return Disposables.create()
        }
    }
1
Bas 19 Ноя 2019 в 20:59
1
Попробуйте почистить и перестроить. То, что у вас есть в вашей редакции, должно работать ... Кстати, использование .empty() вместо .of() было бы более идиоматичным.
 – 
Daniel T.
20 Ноя 2019 в 15:56
@DanielT. Очистка и перестройка не сработали: / Вылетает в методе run класса FlatMapLatest с той же ошибкой.
 – 
Bas
22 Ноя 2019 в 10:40
Тогда должно быть что-то происходит в вашей функции get... или где-то еще в коде. Я скопировал код в проект песочницы, и он отлично сработал.
 – 
Daniel T.
22 Ноя 2019 в 16:04
@DanielT. Хмммм, ладно, спасибо! Я изучу это, я просто представил, что это будут не те функции, потому что как автономные функции они работают так, как должны.
 – 
Bas
22 Ноя 2019 в 19:05
@DanielT. После долгого тестирования я не смог найти проблему. Я добавил функции, вы видите что-нибудь необычное?
 – 
Bas
23 Ноя 2019 в 14:05

1 ответ

Лучший ответ

Есть оператор flatMapLatest, который делает то же самое, что и switchMap в RxJS.

Вы можете найти пример использования здесь

2
Oles Savluk 19 Ноя 2019 в 21:06
Спасибо, я только что попробовал, но, к сожалению, он вылетает при достижении flatMap. Даже если я поставлю печать перед оператором if. : /
 – 
Bas
19 Ноя 2019 в 21:21