Vyacheslav
Vyacheslav

Reputation: 27221

Unexpected nil value for RxSwift map > subscribe

This is just a sample.

But I can understand such behavior. Why in the first place a variable is not an optional but in the last is an optional.

let tapEvent: ControlEvent<UITapGestureRecognizer> = chargingView.rx.tapGesture()
            tapEvent.map { _ in
                return CGPoint()
                }.filter { $0 != nil }.map { $0 } // here Comparing non-optional value of type 'CGPoint' to nil always returns true
                .subscribe { point in
                    print(point.element) // Expression implicitly coerced from 'CGPoint?' to Any
                }.disposed(by: bag)

A screenshot to proof.

enter image description here

The same behavior for this similar code

let tapEvent: ControlEvent<UITapGestureRecognizer> = chargingView.rx.tapGesture()
            tapEvent.map { _ in
                return CGPoint()
                }.flatMap { Observable.from(optional: $0) }
                .subscribe { point in
                    print(point.element)

I'm not familiar with rx. Thanks.

Upvotes: 0

Views: 1640

Answers (2)

Farooq Zaman
Farooq Zaman

Reputation: 505

In the first case input param of filter operator is CGPoint non-optional. Since it's a non optional you cannot compare it with nil.

In second case .flatMap { Observable.from(optional: $0) } flattens Observable<Observable<CGPoint>> to Observable<CGPoint>

In Swift it's equivalent to this:

let arrayOfArrays = [[1,2,3,4]]
let array = arrayOfArrays.flatMap{$0} //Output: [1,2,3,4]

Upvotes: 0

rmaddy
rmaddy

Reputation: 318934

Let's break that up:

let pointArray = tapEvent.map { return CGPoint() }
let filteredArray = pointArray.filter { $0 != nil }
let newPointArray = filteredArray.map { $0 }
let subscribed = newPointArray.subscribe { point in
    print(point.element)
}
subscribed.disposed(by: bag)

That may not be 100% perfect but it's good enough for some clarification.

pointArray will be an array of non-optional, empty CGPoint values.

Since they are not optional, the filter to remove nil values is pointless and the cause of the first error. Simply eliminate the filter.

Then you map the objects in filteredArray to themselves. Again, this is pointless. Remove that second map.

The second error is related to point.element. I know nothing of RxSwift and this specific method based on the warning, the point parameter of the closure is optional. You probable need to add a ? before the ..

With all of this, your code becomes:

let pointArray = tapEvent.map { return CGPoint() }
let subscribed = pointArray.subscribe { point in
    print(point?.element)
}
subscribed.disposed(by: bag)

Or a written in your original format:

let tapEvent: ControlEvent<UITapGestureRecognizer> = chargingView.rx.tapGesture()
tapEvent.map { return CGPoint() }
    .subscribe { point in
        print(point?.element)
    }.disposed(by: bag)

Whether it makes sense to perform the remaining map as it is, I have no idea. Seems odd but again, I don't know RxSwift.

Upvotes: 1

Related Questions