New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UISearchBar.text is emptied upon cancel, but UISearchBar.rx.text is not. #1714

Closed
pepasflo opened this Issue Aug 8, 2018 · 9 comments

Comments

Projects
None yet
4 participants
@pepasflo

pepasflo commented Aug 8, 2018

Short description of the issue:

I created a search controller recently and noticed that when the user taps "cancel", the search text gets emptied out, but this isn't reflected via UISearchBar.rx.text.

Expected outcome:

Here's what I ended up with as a work-around, which I think describes the behavior I was expecting:

Observable.combineLatest(
    self.searchBar.rx.text,
    self.searchBar.rx.textDidEndEditing.startWith(())
)
    .map { _ in return self.searchBar.text ?? "" }
    .distinctUntilChanged()
    .subscribe(onNext: { (text) in
        print("searchbar text: \(text)")
    })
    .disposed(by: self.disposeBag)

What actually happens:

When the user hits "cancel", the text is visually gone from the search bar. I was a bit surprised that this update isn't reflected in rx.cancelButtonClicked, but the text update is reflected by the time .rx.textDidEndEditing gets hit.

Self contained code example that reproduces the issue:

self.searchBar.rx.text
    .subscribe(onNext: { (text) in
        print("searchBar.rx.text.onNext: \(String(describing: text))")
    })
    .disposed(by: self.disposeBag)

self.searchBar.rx.cancelButtonClicked
    .subscribe(onNext: { () in
        print("searchBar.rx.cancelButtonClicked.onNext: text: \(String(describing: self.searchBar.text))")
    })
    .disposed(by: self.disposeBag)

self.searchBar.rx.textDidEndEditing
    .subscribe(onNext: { () in
        print("searchBar.rx.textDidEndEditing.onNext: text: \(String(describing: self.searchBar.text))")
    })
    .disposed(by: self.disposeBag)

Observable.combineLatest(
    self.searchBar.rx.text,
    self.searchBar.rx.textDidEndEditing.startWith(())
)
    .map { _ in return self.searchBar.text ?? "" }
    .distinctUntilChanged()
    .subscribe(onNext: { (text) in
        print("combineLatest: text: \(text)")
    })
    .disposed(by: self.disposeBag)

RxSwift/RxCocoa/RxBlocking/RxTest version/commit

$ cat Podfile.lock 
PODS:
  - RxCocoa (4.2.0):
    - RxSwift (~> 4.0)
  - RxSwift (4.2.0)
  - RxSwiftExt (3.2.0):
    - RxSwiftExt/Core (= 3.2.0)
  - RxSwiftExt/Core (3.2.0):
    - RxSwift (~> 4.0)

Platform/Environment

  • [😜] iOS
  • macOS
  • tvOS
  • watchOS
  • playgrounds

How easy is to reproduce? (chances of successful reproduce after running the self contained code)

  • [👻] easy, 100% repro
  • sometimes, 10%-100%
  • hard, 2% - 10%
  • extremely hard, %0 - 2%

Xcode version:

9.4.1

⚠️ Fields below are optional for general issues or in case those questions aren't related to your issue, but filling them out will increase the chances of getting your issue resolved. ⚠️

Installation method:

  • [🤪] CocoaPods
  • Carthage
  • Git submodules

I have multiple versions of Xcode installed:
(so we can know if this is a potential cause of your issue)

  • [🤯] yes (10.0 beta 5)
  • no

Level of RxSwift knowledge:
(this is so we can understand your level of knowledge
and formulate the response in an appropriate manner)

  • just starting
  • [🤡] I have a small code base
  • I have a significant code base

@pepasflo pepasflo changed the title from `UISearchBar.text` is emptied upon cancel, but `UISearchBar.rx.text` is not. to UISearchBar.text is emptied upon cancel, but UISearchBar.rx.text is not. Aug 8, 2018

@kzaher

This comment has been minimized.

Member

kzaher commented Aug 14, 2018

This sounds like a potential bug to me, I think we might want to add self.searchBar.rx.textDidEndEditing or self.searchBar.rx.didCancel to the text trigger if that is a problem.

@freak4pc

This comment has been minimized.

Collaborator

freak4pc commented Aug 15, 2018

@pepasflo

From my quick test I don't see any issues.

Tapping the cancel button triggers cancelButtonClicked (by the way would be better to call this tapped, no biggie)
Tapping the clear button clears the textfields, and properly emits a "" text from rx.text.

Are you sure you're not confused with "clear" vs. "cancel" buttons?

image

The last "" emission is after I tap the clear button.

@pepasflo

This comment has been minimized.

pepasflo commented Aug 15, 2018

@freak4pc here is a more complete example:

import UIKit
import RxSwift
import RxCocoa

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

        let window = UIWindow(frame: UIScreen.main.bounds)
        window.makeKeyAndVisible()
        window.rootViewController = UINavigationController(rootViewController: ViewController())
        self.window = window

        return true
    }
}

class ViewController: UIViewController {

    private let searchController: UISearchController = {
        let controller = UISearchController(searchResultsController: nil)
        controller.dimsBackgroundDuringPresentation = false
        return controller
    }()

    private var searchBar: UISearchBar {
        return self.searchController.searchBar
    }

    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white

        self.navigationItem.searchController = self.searchController

        let observable1 = self.searchBar.rx.text

        let observable2 = Observable.combineLatest(
            self.searchBar.rx.text,
            self.searchBar.rx.textDidEndEditing.startWith(())
        )

        observable1
            .debug("debug:", trimOutput: false)
            .takeUntil(self.rx.deallocated)
            .map { [unowned self] _ in return self.searchBar.text ?? "" }
            .distinctUntilChanged()
            .subscribe(onNext: { (text) in
                print("onNext: '\(text)'")
            })
            .disposed(by: self.disposeBag)

    }
}

In the above example, if I tap in the search box, then type "A", the following is printed to the console:

2018-08-15 12:50:53.546: debug: -> Event next(Optional("A"))
onNext: 'A'

If I hit the "Cancel" button, nothing is printed to the console (but visually, the text is gone from the search bar).

If we modify the above example so that we subscribe to observable2 rather than observable1, and I tap into the search bar and tap 'A', I see this:

2018-08-15 12:53:02.268: debug: -> Event next((Optional("A"), ()))
onNext: 'A'

If I then hit "Cancel", I see this:

2018-08-15 12:53:08.139: debug: -> Event next((Optional("A"), ()))
onNext: ''
@freak4pc

This comment has been minimized.

Collaborator

freak4pc commented Aug 24, 2018

@pepasflo Mind making a self-reproducible example to make things easier to just run and try? :)
Highly appreciate it.

@reteps

This comment has been minimized.

reteps commented Oct 7, 2018

This issue still exists. .text does not emit anything after the cancel button is clicked. My current workaround:

let cancelTextObservable = searchController.searchBar.rx.textDidEndEditing.map({ _ in
    return ""
})
let searchTextObservable = searchController.searchBar.rx.text.orEmpty.asObservable()
Observable.of(cancelTextObservable, searchTextObservable).merge()

@kzaher kzaher closed this in 78c500c Nov 2, 2018

@pepasflo

This comment has been minimized.

pepasflo commented Nov 2, 2018

@kzaher was this issue fixed, or was it closed with a recommendation for the above work-around?

(don't want this comment to sound critical -- I am very grateful for your work on RxSwift! 👍)

@kzaher

This comment has been minimized.

Member

kzaher commented Nov 3, 2018

It was fixed in the latest release.

@kzaher

This comment has been minimized.

Member

kzaher commented Nov 3, 2018

There is a commit that references this issue just above.

@pepasflo

This comment has been minimized.

pepasflo commented Nov 5, 2018

😍😍😍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment