I have AllOrganizacionUIView class, I used UISearchBarDelegate delegate, on workink
class AllOrganizacionUIView: UIView , UISearchBarDelegate {
#IBOutlet var SearchBar: UISearchBar!
var searchActive : Bool = false
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchActive = false;
aa.SearchBar.endEditing(true)
print("hajox")
}
}
I Have use UISearchBarDelegate delegate in ViewController class,
class ViewController: UIViewController{
#IBOutlet var SearchBar: UISearchBar!
// not working
func searchBarShouldBeginEditing(searchBar: UISearchBar) -> Bool {
self.CircleImageView_3.image = UIImage(named: "FullCircle")
self.CircleImageView_2.image = UIImage(named: "Circle")
self.CircleImageView_1.image = UIImage(named: "Circle")
self.mMainCategory.hidden = true
self.mAllCategores.hidden = true
self.mAllOrganizations.hidden = false
self.FooterViewController.text = "Основные категории"
return true
}
}
Help me please with this problem.
You have to set delegate for your search bar, possibly in viewDidLoad():
override func viewDidLoad() {
super.viewDidLoad()
self.SearchBar.delegate = self
}
But it will be much better if you point the delegate on storyboard instead of code.
So, I see two problems in your code. First, you mean that your delegate is an UIView subclass. But then you mean that you want to use delegate which is implemented in UIViewController subclass.
You're able to have only one delegate at the same time. Choose one (view controller is preferred), and implement all delegate methods there. Then just set delegate as I said at the beginning of my answer.
Actually, I suggest you to read about protocols and delegates at the official Apple's documentation website. It is really necessary to read documentation carefully, because there are a lot of unique things in iOS that are different to another platforms.
override func viewDidLoad() {
super.viewDidLoad()
self.SearchBar.delegate = self
}
or set your delegate in storyboard .
Related
I am implementing a search feature in my app. The app consists of a view controller and a custom class that handles the search logic. This custom class is called SearchController.
My goal is to make the searchBar notify the view controller when the user is about to begin searching (exactly the same behaviour as the UISearchBarDelegate method searchBarShouldBeginEditing).
Normally, you would just declare searchBarShouldBeginEditing inside SearchController but I am trying to call this method from inside the viewController because I want something in my view to change when this event happens (and thus the viewController should be handling it, not the searchController).
SearchController class:
class SearchController: NSObject, UISearchBarDelegate {
let searchBar = UISearchBar()
var searchButton = UIBarButtonItem? = nil
/* Other irrelevant class properties */
func setup() {
searchBar.delegate = self
/* other setup */
}
}
ViewController class:
class ViewController: UIViewController {
private let searchController = SearchController()
override func viewDidLoad() {
super.viewDidLoad()
searchController.delegate = self
searchController.setup()
}
/* setup a tableview to display results... this part of the implementation works fine */
}
I omitted the majority of these two classes because the search feature already works. The only thing I am struggling with is finding a way to let viewController know when the user is about to begin typing into the search field.
I tried making viewController implement UISearchBarDelegate but I am already making SearchController implement UISearchBarDelegate so why can't I access the delegate methods inside viewController?
I hope I made myself clear, I can clarify this post further if necessary. I have been tearing my hair out trying to figure this out on my own.
Ok, a searchBar cannot have 2 delegates, so you're gonna have to find a way to work around that.
One way to go about this is this:
protocol SearchControllerDelegate: class{
func searchBarDidBeginEditing()
}
class SearchController: NSObject, UISearchBarDelegate {
weak var delegate: SearchControllerDelegate?
private let searchBar = UISearchBar()
func setup() {
searchBar.delegate = self
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
delegate?.searchBarDidBeginEditing()
}
}
class ViewController: UIViewController, SearchControllerDelegate{
var searchController = SearchController()
func setUP(){
self.searchController.delegate = self
}
func searchBarDidBeginEditing() {
/// perform some action here
}
}
You can use UISearchController as rmaddy suggested, implement UISearchResultsUpdating
ViewController class:
class ViewController: UIViewController, UISearchResultsUpdating {
private let searchController = UISearchController(searchResultsController: nil)
override func viewDidLoad() {
super.viewDidLoad()
searchController.searchResultsUpdater = self
searchController.delegate = self
....
}
// Called when the search bar's text or scope has changed or when the search bar becomes first responder.
func updateSearchResults(for searchController: UISearchController) {
//Do something...
}
}
Or if you really want to implement the search bar logic yourself, you can go with the closure:
SearchController class:
class SearchController: NSObject, UISearchBarDelegate {
let searchBar = UISearchBar()
var searchButton = UIBarButtonItem? = nil
var didBeginSearching: (() -> ())?
/* Other irrelevant class properties */
func setup() {
searchBar.delegate = self
/* other setup */
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
didBeginSearching?()
}
}
ViewController class:
class ViewController: UIViewController {
private let searchController = SearchController()
override func viewDidLoad() {
super.viewDidLoad()
searchController.setup()
searchController.didBeginSearching = { [weak self] in
//Do something...
}
}
}
I have a view controller that is responsible for adding a new object, say a new contact. This view controller (AddContactViewController) has the following UIBarButtonItem on a UINavigationBar, which is starts of disabled until enough information is provided to enable it. Then when this button is pressed a method (doneButtonPressed) is called.
The layout is as follows:
class AddContactViewController: UIViewController {
#IBOutlet weak var doneButton: UIBarButtonItem! {
didSet {
doneButton.isEnabled = false
doneButton.target = self
doneButton.action = #selector(self.doneButtonPressed)
}
}
#objc fileprivate func doneButtonPressed() {
// do some stuff ...
self.dismiss(animated: false, completion: nil)
}
}
As this is quite a common thing to have and there's a lot of boiler plate code, I've been working on a protocol AddingHandler but haven't quite worked out how to have UIBarButtonItem as a weak variable which hooks up to a storboard or if this is even the right way to go.
protocol AddingHandler {
var doneButton: UIBarButtonItem? { get set }
func doneButtonPressed()
}
extension protocol where Self: UIViewController {
func configureDoneButton() {
doneButton.isEnabled = false
doneButton.target = self
doneButton.action = #selector(self.doneButtonPressed)
}
}
Any help or comments in making this work would be much appreciated.
The problem How is best to add a weak UIButton to a protocol which can then be hooked up in a story board where UIViewController implements it? As there is a lot of repetitive code here should I wish to have another AddSomethingViewController I was wondering if there was a neater way of only writing this once (in a protocol with an extension) then calling the protocol in any view controller that is adding something new ...
You can simply configure the doneButton in viewDidLoad()
override func viewDidLoad()
{
super.viewDidLoad()
doneButton.isEnabled = false
doneButton.target = self
doneButton.action = #selector(self.doneButtonPressed)
}
Edit 1:
#objc protocol AddingHandler
{
var doneButton: UIBarButtonItem? { get }
#objc func doneButtonPressed()
}
extension AddingHandler where Self: UIViewController
{
func configureDoneButton()
{
doneButton?.isEnabled = false
doneButton?.target = self
doneButton?.action = #selector(doneButtonPressed)
}
}
class AddContactViewController: UIViewController, AddingHandler
{
#IBOutlet weak var doneButton: UIBarButtonItem!
override func viewDidLoad()
{
super.viewDidLoad()
configureDoneButton()
}
func doneButtonPressed()
{
// do some stuff ...
self.dismiss(animated: false, completion: nil)
}
}
I've used ObjC runtime to resolve the issue. Try implementing it at your end and check if it works for you.
How can I fix the search controller animate UI screen when adding to navigation item to the search bar in IOS 11?
I have tested it for iPhone X and its working fine. Make sure your navigation controller isn't nil in viewcontroller.
class ViewController: UIViewController {
var searchController: UISearchController!
override func viewDidLoad() {
super.viewDidLoad()
self.searchController = UISearchController(searchResultsController: nil)
self.searchController.hidesNavigationBarDuringPresentation = false
self.searchController.searchBar.delegate = self
self.searchController.dimsBackgroundDuringPresentation = true
navigationItem.titleView = searchController.searchBar
definesPresentationContext = true
// Do any additional setup after loading the view, typically from a nib.
}
}
extension ViewController: UISearchBarDelegate {
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
// self.dismiss(animated: true, completion: nil)
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
search(sender: searchBar)
}
}
class PlaceSelectorViewController: UIViewController, GMSAutocompleteResultsViewControllerDelegate, UISearchBarDelegate {
I have included searchbar delegate
searchController?.searchBar.delegate = self
and I have set the delegate.
But method
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
stopHighlight()
}
doesn't happen.
Delegate has set properly and stopHighlight() is a real function
Make delegate of searchbar in viewdidload method.
override func viewDidLoad() {
super.viewDidLoad()
searchBarCustom.delegate = self
}
or you can set it in storyboard as
-hence delegates will call as
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
print("searchBarCancelButtonClicked")
}
EDIT:
For UISearchController
var searchController: UISearchController!
func configureSearchController() {
// Initialize and perform a minimum configuration to the search controller.
searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false
searchController.searchBar.placeholder = "Search here..."
searchController.searchBar.delegate = self
searchController.searchBar.sizeToFit()
// Place the search bar view to the tableview headerview.
tblSearchResults.tableHeaderView = searchController.searchBar
}
In my case, it was a spelling error.
Make sure your #IBOutlet name is similar with your delegate name.
Example,
#IBOutlet weak var SearchBar: UISearchBar!
Set the delegate in viewDidLoad():
override func viewDidLoad() {
super.viewDidLoad()
SearchBar.delegate = self
I am trying to implement the search in my SWIFT code. I want it to wait until the search button is clicked before it does anything. What I have so far.
func updateSearchResultsForSearchController(searchController: UISearchController)
{
self.filteredCats.removeAll(keepCapacity: false)
filteredCats = art.filter{
$0.sarticleTitle.lowercaseString.rangeOfString(searchController.searchBar.text!.lowercaseString) != nil
}
print(searchController.searchBar.text)
self.tableView.reloadData()
}
It prints out all the information once the user types something. I want it to wait till the search button is clicked or when the user has finished typing everything.
You should set delegate like this your view controller.
var resultSearchController = UISearchController()
resultSearchController.searchBar.delegate = self
extension ViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print("search button click")
}
}
Use the UISearchBarDelegate method searchBarSearchButtonClicked(_:) Reference
class MySearchController:UISearchController, UISearchBarDelegate {
override init(searchResultsController: UIViewController?) {
super.init(searchResultsController: searchResultsController)
// Set the searchbar delegate
self.searchBar.delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// Start the search
}
}
Importantly, make sure you tell the UISearchBar that you want the UISearchController to be it's delegate, the above is an un-tested example, your exact initialisation may differ.
implement "searchController.searchBar.delegate" & "searchBarSearchButtonClicked" method
self.searchController.searchBar.delegate = self;
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
//enter your search code
}