I need help to set text in searchBar of GMSAutocompleteViewController
when open in my App. I am using GMSAutocompleteViewController
in Google Place AutocompleteViewController.
How to set text in GMSAutocompleteViewController in Google Place AutocompleteViewController
4.9k views Asked by Nalawala Murtaza AtThere are 9 answers
You can inject text in this search bar using something like
func injectTextInSearchView(_ text: String, _ view: UIView) {
if let view = view as? UISearchBar {
view.text = text
view.delegate?.searchBar!(view, textDidChange: text)
return
}
for subview in view.subviews {
injectTextInSearchView(text, subview)
}
}
@Cools
In Swift 3, it seems to have different hierarchy. I've digged into VC and got the place.
func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
let views = viewController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
let searchBar = subOfContentView[0] as! UISearchBar
searchBar.text = "YOUR_TEXT"
}
However, it has one fault that it does not search automatically. After I'v e got the solution, I will edit again.
typedef void (^TTSearchBarHandler)(UISearchBar * searchbar);
__weak UIViewController *weaks = self;
[self searchSubviews:viewController.view completion:^(UISearchBar *searchbar) {
if(searchbar){
[searchbar.delegate searchBar:searchbar textDidChange:@"Your Text"];
}
}];
-(void)searchSubviews:(UIView*)view completion:(TTSearchBarHandler)completion{
if([view isKindOfClass:[UISearchBar class]]){
UISearchBar *searchBar = (UISearchBar*)view;
if(completion){
completion(searchBar);
}
}
else{
for(UIView * subview in view.subviews){
[self searchSubviews:subview completion:^(UISearchBar *searchbar) {
if(completion){
completion(searchbar);
}
}];
}
}
}
Well, I don't necessarily recommend this course of action because if you want more control you should use the UISearchResults Controller. However, here's a swifty-er version:
//Where viewController is the GMSAutocompleteViewController
if let searchBar = (viewController.view.subviews
.flatMap { $0.subviews }
.flatMap { $0.subviews }
.flatMap { $0.subviews }
.filter { $0 == $0 as? UISearchBar}).first as? UISearchBar {
searchBar.text = "YOUR_TEXT_HERE"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "YOUR_TEXT_HERE") // to get the autoComplete Response
}
The benefit of this approach is that you don't have to know exactly where the SearchBar is located. It's basically trying to flatten all the subviews into one array and filter out the SearchBar from the array. If Google decides to change up where the SearchBar is hidden, this approach may still find it. The problem is that you still need to know how many levels of subviews there are. There may be a recursive function that you could set up to deal with this.
I have found out that solutions here are not working for iOS 10. So I have written recursive method for finding concrete view - UISearchBar
, in our case:
extension UIView {
func getViewWithConcreteType<T: UIView>()-> T? {
if let concreteSubview = self as? T {
return concreteSubview
}
for subview in subviews {
let concreteView: T? = subview.getViewWithConcreteType()
if concreteView != nil {
return concreteView!
}
}
return nil
}
}
Made some modification to original solution:
let views = autocompleteController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
if let searchBar = subOfContentView[0] as? UISearchBar {
searchBar.text = text
searchBar.delegate?.searchBar?(searchBar, textDidChange: text)
} else {
let searchBar: UISearchBar? = autocompleteController.view.getViewWithConcreteType()
searchBar?.text = text
searchBar.map { $0.delegate?.searchBar?($0, textDidChange: text) }
}
func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
guard let searchBar = (viewController.view.subviews.first?.subviews.last?.subviews[1].subviews.first as? UISearchBar)
else { return }
searchBar.text = "your_text"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "your_text")
}
I got a working solution by combining @Youngjin and @Exception's answers for Swift 4 and Google Places 2.6.0
To access the GMSAutocompleteViewController searchbar:
let views = gmsAutoCompleteViewController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
let searchBar = subOfContentView[0] as! UISearchBar
Then to set the text and also search automatically:
searchBar.text = "Your address"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "Your address") // This performs the automatic searching.
I found that I received a EXC_BAD_ACCESS error when attempting to set the text from within didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController).
So I instead put this code in the completion block where I present the autoCompleteController, which works without issue.
Combining it all together:
let gmsAutoCompleteViewController = GMSAutocompleteViewController()
gmsAutoCompleteViewController.delegate = self
present(gmsAutoCompleteViewController, animated: true) {
let views = gmsAutoCompleteViewController.view.subviews
let subviewsOfSubview = views.first!.subviews
let subOfNavTransitionView = subviewsOfSubview[1].subviews
let subOfContentView = subOfNavTransitionView[2].subviews
let searchBar = subOfContentView[0] as! UISearchBar
searchBar.text = "Your address"
searchBar.delegate?.searchBar?(searchBar, textDidChange: "Your address")
}
EDIT: I found that this solution only seems to work on iOS 11.
let searchBar = subOfContentView[0] as! UISearchBar
will fail on iOS 10, and possibly lower versions.
- (void)viewDidLoad {
[super viewDidLoad];
acController = [[GMSAutocompleteViewController alloc] init];
acController.delegate = self;
}
- (IBAction)btnSearch1:(id)sender {
[self presentViewController:acController animated:YES completion:nil];
}
- (void)didRequestAutocompletePredictions:(GMSAutocompleteViewController *)viewController {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
UIView *Views = viewController.view;
NSArray *Aar2 = [[Views subviews][0] subviews];
UIView *View2 = Aar2[1];
UIView *View3 = [View2 subviews][2];
UISearchBar *Search = [[View3 subviews] firstObject];
Search.text = @"Your text";
[Search.delegate searchBar:Search textDidChange:txtAddress.text];
}
// Cools enjoy man
I'm not very familiar with swift coding but based from the documentation - Customize text and background colors:
The documentation states Search Bar text color, Search bar tint color and Search bar placeholder text color (default search text) can be styled using (UIAppearance protocol or SDK method).
Hope this info helps.