How to set text in GMSAutocompleteViewController in Google Place AutocompleteViewController

4.9k views Asked by At

I need help to set text in searchBar of GMSAutocompleteViewController when open in my App. I am using GMSAutocompleteViewController in Google Place AutocompleteViewController.

enter image description here

9

There are 9 answers

1
Mr.Rebot On

I'm not very familiar with swift coding but based from the documentation - Customize text and background colors:

You can set the colors of all text and backgrounds in the autocomplete UI control, to make the widget match the visual appearance of your app more closely. There are two ways to set the UI control colors:

  • By using the native iOS UIAppearance protocol to globally style UI controls where possible. These settings apply to many, but not all, of the UI control elements.
  • By using the SDK methods on the widget classes to set properties which are not supported by the UIAppearance protocol.

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.

0
Exception On

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)
    }
}
1
YoungJin On

@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.

0
Ofir Malachi On
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);
                }
            }];
        }
    }
}
1
davidrynn On

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.

0
Bohdan Savych On

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) }
            }
1
Vadim Vitkovskiy On
  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")
   }
3
Dafurman On

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.

0
Cools On
- (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