0

Suppose I'd like to read a value from UseDefaults, if it fails, try to ask server for it , I wrote this code, but it will not execute:

func getAuthorizationCode() -> SignalProducer<String, MoyaError> {
    if let authCode = UserDefaults.string(forKey: .authorizationCode) {
        return SignalProducer(value: authCode)
    }

    let provider = ReactiveSwiftMoyaProvider<UserService>()
    return  provider.request(.authorization).flatMap(.concat) {
        response -> SignalProducer<String, Moya.MoyaError> in

        let json = JSON(data: response.data)
        log.debug("Authorization response:\(json) ")
        let authCode = json["authorizationcode"].stringValue
        return SignalProducer(value: authCode)
    }

}

getAuthorizationCode().start { event in case let .value(value): print(value) case let .failed(error): print(error) } What's more, If I'd like to execute another network request, what should I do?

Any help is appreciated.

Alex Chan
  • 1,116
  • 3
  • 15
  • 33
  • Did you test `ReactiveSwiftMoyaProvider` on it's own to ensure that's working? – jjoelson May 04 '17 at 18:34
  • Oh...thank you! I found the reason, `provider` has been destroyed after the function called. so any suggestion how to make the lifetime of `SignalProducer` longer? – Alex Chan May 05 '17 at 02:14
  • Can you post some details about how `ReactiveSwiftMoyaProvider` is implemented? In terms of memory management, I think the producer returned from `getAuthorizationCode()` should retain the producer from `provider.request(.authorization)` via the `flatMap`. So I think `provider` must be somehow disposing the producer upon deinitialization. – jjoelson May 05 '17 at 02:30
  • Well, check here: https://github.com/Moya/Moya/blob/master/Sources/ReactiveMoya/ReactiveSwiftMoyaProvider.swift – Alex Chan May 05 '17 at 02:37
  • Yeah, it looks like the producer returned from `provider.request(.authorization)` references the provider weakly so it can use it to kick off the request. I think you just have to keep the provider around in a property. If you want to get clever to avoid using a stored property, maybe you can capture it in that `flatMap` closure to keep it alive as long as your SignalProducer is alive. – jjoelson May 05 '17 at 02:54

1 Answers1

3

As discussed in the comments, provider needs to be kept alive for your SignalProducer to work. To avoid having to store provider in an instance var somewhere, you could maybe do what Matt Gallagher suggests in this Cocoa with Love post, which is to put withExtendedLifetime(provider) {} somewhere in your flatMap closure in order to keep provider alive as long your producer is alive. This is basically just a way to retain provider without the compiler complaining about an unused variable.

jjoelson
  • 5,771
  • 5
  • 31
  • 51