0

I'm new to a company and trying to understand the used generics. The setup of a model contains

var selectedChannel: Driver<Channel> { get }

@available(*, deprecated, message: "Use driver selectedChannel")
var selectedChannelValue: Channel { get }

At some point in the code selectedChannelValue.id is used, but it shows up the warning message Use driver selectedChannel. I understand this. Okay it still does the job but one of the previous programmers deprecated this for a reason.

How to rewrite the code-line so that I get selectedChannel.id as the deprecation message suggests? When I use selectedChannel.id the error message Value of type 'Driver<Channel>' (aka 'SharedSequence<DriverSharingStrategy, Channel>') has no member 'id' appears. How to unwrap the SharedSequence?

EDIT: The channel struct looks like this:

public struct Channel: Codable {
    public let id: String    // e.g. "1111111"

The driver is setup in RxCocoa as:

public typealias Driver<Element> = SharedSequence<DriverSharingStrategy, Element>

public struct DriverSharingStrategy: SharingStrategyProtocol {
    public static var scheduler: SchedulerType { return SharingScheduler.make() }
    public static func share<Element>(_ source: Observable<Element>) -> Observable<Element> {
        return source.share(replay: 1, scope: .whileConnected)
    }
}
extension SharedSequenceConvertibleType where SharingStrategy == DriverSharingStrategy {
    /// Adds `asDriver` to `SharingSequence` with `DriverSharingStrategy`.
    public func asDriver() -> Driver<Element> {
        return self.asSharedSequence()
    }
}
FrugalResolution
  • 568
  • 4
  • 18
  • It is impossible to say without understanding what the Driver and Channel types look like. I would assume something like selectedChannel.channel.id but its a guess. – SacredGeometry Nov 25 '21 at 19:12

1 Answers1

1

By wrapping the Channel in a Driver, the code is telling you that it is asynchronous. So it might not yet exist when you query it, and it might change while you are observing it. You observe it with the drive method:

selectedChannel
    .drive(onNext: { channel in
        // you can use channel.id here.
    })
    .disposed(by: disposeBag)

But you can't just save that id in some var outside of the closure and expect everything to be okay. The code that needs the id will have to also been that closure (or in a function that is called from that closure.)

Note that you will likely need to create a dispose bag in the class that this code is in as well.

The Driver is a kind of Observable. You should read up on how to use these constructs, but for these purposes, you can think of it kind of like a callback closure encapsulated in an object.

Daniel T.
  • 32,821
  • 6
  • 50
  • 72
  • This was exactly what I needed! I started reading the raywenderlich tutorials but .drive was the key to solution to my question. Is it okay to nest a `.subscribe{ event in` inside the .driver closure? – FrugalResolution Nov 26 '21 at 03:11
  • 1
    It depends on the context but in general the answer is no. Embedding a drive/bind/subscribe inside another drive/bind/subscribe is a code smell that should be avoided. – Daniel T. Nov 26 '21 at 12:17