Programmatically add a UISearchController to a UITableView header in swift 2 - ios

In the previous version of my view controller (based on storyboard) the search bar was working good.
In the 100% programmatically defined current version (I removed all storyboard references) the search bar has disappeared.
I am trying to understand where the problem lies, without success. Any idea?
Here is the faulty code snippet:
let resultSearchController = UISearchController()
override public func viewDidLoad() {
super.viewDidLoad()
// No nav bar
navigationController?.navigationBar.hidden = true
// — Add table view
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.leftAnchor.constraintEqualToAnchor(view.leftAnchor, constant: 0).active = true
tableView.rightAnchor.constraintEqualToAnchor(view.rightAnchor, constant: 0).active = true
tableView.bottomAnchor.constraintEqualToAnchor(view.bottomAnchor, constant: 0).active = true
// Add search bar as a the table header
resultSearchController.dimsBackgroundDuringPresentation = false
resultSearchController.definesPresentationContext = true
resultSearchController.hidesNavigationBarDuringPresentation = false
resultSearchController.searchResultsUpdater = self
resultSearchController.searchBar.sizeToFit()
resultSearchController.searchBar.delegate = self
tableView.tableHeaderView = resultSearchController.searchBar
/// Add refresh control
refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh")
refreshControl.addTarget(self, action: #selector(BigHeadViewController.refreshTable), forControlEvents: UIControlEvents.ValueChanged)
tableView.addSubview(refreshControl)
}

I think the problem might be the first line. You have to specify the "searchResultsController" as part of the initialisation - even if it's nil (to search in place). Try
let resultSearchController = UISearchController(searchResultsController:nil)

Related

UIPasteboard retrieving previous item

I've got the following code:
[[UIApplication sharedApplication] sendAction:#selector(copy:) to:nil from:self forEvent:nil];
NSString *string = [UIPasteboard generalPasteboard].string;
The problem is that the pasteboard is returning what I've copied previously, not currently. Somehow it's hanging onto the previous item I've copied and returning that, and then next time around I get the item that I wanted and copied... strange behaviour.. any ideas?
Edit
I've got a solution using an observer, but not sure how elegant it is.. there seems to be some delay between copy and setting an item.. enough for it not to be set and for the previous one to be still on the UIPasteBoard.
I have composed a little sample to your code for copy/paste behavior and it works as expected: selected text is printed to console after tapping on the button.
class ViewController: UIViewController {
let textField = UITextField()
let copyButton = UIButton(type: .roundedRect)
#objc func copySelectedText() {
UIApplication.shared.sendAction(#selector(UIResponder.copy(_:)), to: nil, from: self, for: nil)
let copiedString = UIPasteboard.general.string
print(copiedString)
}
override func viewDidLoad() {
super.viewDidLoad()
textField.borderStyle = .roundedRect
view.backgroundColor = .darkGray
display(textField, copyButton)
copyButton.setTitle("tap to copy selected text", for: .normal)
copyButton.addTarget(self, action: #selector(copySelectedText), for: .touchUpInside)
}
private func display(_ textField: UITextField, _ copyButton: UIButton) {
copyButton.translatesAutoresizingMaskIntoConstraints = false
textField.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(copyButton)
view.addSubview(textField)
textField.backgroundColor = .white
textField.widthAnchor.constraint(greaterThanOrEqualToConstant: 200).isActive = true
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
textField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
copyButton.topAnchor.constraint(equalTo: textField.bottomAnchor, constant: 20).isActive = true
copyButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
}

UIActivityIndicatorView not showing up in iOS UIViewController

I want to display a gray UIViewIndicatorView in a view controller at the center of the view but this piece of code isn't showing anything:
class MyViewController: UIViewController {
var activityIndicatorView = UIActivityIndicatorView()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
displayActivityIndicator()
}
func displayActivityIndicator() {
view.addSubview(activityIndicatorView)
activityIndicatorView.style = .gray
activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false
activityIndicatorView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
activityIndicatorView.widthAnchor.constraint(equalToConstant: 40).isActive = true
activityIndicatorView.heightAnchor.constraint(equalToConstant: 40).isActive = true
activityIndicatorView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
activityIndicatorView.startAnimating()
}
}
This only shows up the activity indicator view when I set the view controller's view to a color like white (excluding black).
How can I make it show up?
Change background to
view.backgroundColor = .green // for example
or
activityIndicatorView.style = .white
then you' ll see it , as it's nearly a color match between the indicator and the background view

How do I avoid the weird gap between search bar and the table view while search results displaying?

Check: Screenshot
I tried solutions to all relevant questions. However none of them helped really.
I am getting a weird gap between table view and search bar when search bar shows results.
Help me find out what's wrong with my code:
the view controller subclasses from UITableViewController, UISearchBarDelegate, UISearchResultsUpdating
var searchController = UISearchController()
var resultsController = UITableViewController()
var refreshController = UIRefreshControl()
in override :
configureSearchController()
resultsController.tableView.delegate = self
resultsController.tableView.dataSource = self
refreshController.attributedTitle = NSAttributedString(string: "")
refreshController.addTarget(self, action: #selector(refreshSelector), for: .valueChanged)
tableView.addSubview(refreshController)
searchController.searchBar.delegate = self
automaticallyAdjustsScrollViewInsets = false
definesPresentationContext = true
#objc func refreshSelector()
{
if(!searchLoaded)
{
searchLoaded = true
self.tableView.tableHeaderView = searchController.searchBar
self.navigationItem.rightBarButtonItem = nil
print( "Got ya")
}
refreshController.endRefreshing()
}
func configureSearchController ()
{
searchController = UISearchController(searchResultsController: resultsController)
searchController.searchResultsUpdater = self
searchController.searchBar.layer.borderWidth = 1;
searchController.searchBar.barTintColor = UIColor.searchBarBackgroundGrey()
searchController.searchBar.layer.borderColor = UIColor.searchBarBackgroundGrey().cgColor
self.navigationController?.navigationBar.shadowImage = UIImage()
}
deployment target has been set as 9.3

Eureka Form in UITableView programmatically?

I am using Eureka Forms in my Swift 4 app and I do not use storyboards. Setting up the form programmatically is working fine, however I am using a popoverPresentationController to display a UIViewController with a NavBar in and using the form as a FormViewController means the top of the form is hidden underneath the NavBar.
I'd like make the Class as UIViewController and then add the Eureka form as a Subview so I can using constraints as normal. I understand this is achieved by using UITableView, so I have set it up as follows but I'm not sure how to wire in the Eureka Form and I can't find anything in the documentation about it.
import UIKit
import Eureka
class TestForm: UIViewController, UITableViewDelegate {
let navBar: UINavigationBar = {
let nav = UINavigationBar(frame: .zero)
nav.translatesAutoresizingMaskIntoConstraints = false
return nav
}()
let formTable: UITableView = {
let table = UITableView(frame: .zero, style: .grouped)
table.translatesAutoresizingMaskIntoConstraints = false
table.backgroundColor = .red
return table
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(navBar)
view.addSubview(formTable)
formTable.delegate = self
navBar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
navBar.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
navBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
navBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
formTable.translatesAutoresizingMaskIntoConstraints = false
formTable.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
formTable.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
formTable.topAnchor.constraint(equalTo: navBar.bottomAnchor).isActive = true
formTable.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
let navItem = UINavigationItem(title: "Add Event")
let cancelItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.cancel, target: nil, action: #selector(dismissView))
navItem.leftBarButtonItem = cancelItem
navBar.setItems([navItem], animated: false)
Form +++ Section("First Section")
<<< TextRow("Section 1 Text"){ row in
row.title = "Text Row"
row.placeholder = "Enter text here"
}
<<< PhoneRow("Section 1 Phone"){
$0.title = "Phone Row"
$0.placeholder = "And numbers here"
}
.onCellSelection({ (cell, row) in
self.saveForm()
})
}
}
Any pointers?

UISearchBar in Navigation Bar cannot enter text

I'm having a weird problem, when my app first loads you cannot enter text in the search bar no matter how many times you tap it, the search bar is nested in the navigation bar.
My app also use a tab bar, and when you switch tabs then go back to the tab with the search bar it allows you enter text... any ideas what's causing this?
Heres the code for the searchBar:
func setupSearchBar(){
let locationSearchTable = storyboard!.instantiateViewController(withIdentifier: "LocationSearchTable") as! LocationSearchTableViewController
resultSearchController = UISearchController(searchResultsController: locationSearchTable)
resultSearchController?.searchResultsUpdater = locationSearchTable
searchBar = resultSearchController!.searchBar
searchBar.sizeToFit()
searchBar.placeholder = "Location"
searchBar.isTranslucent = true
searchBar.isUserInteractionEnabled = true
for subView in searchBar.subviews{
for subsubView in subView.subviews{
if let textField = subsubView as? UITextField{
var currentTextFieldBounds = textField.bounds
currentTextFieldBounds.size.height = 40.0
textField.bounds = currentTextFieldBounds
textField.borderStyle = UITextBorderStyle.none
textField.textAlignment = NSTextAlignment.left
textField.font = UIFont(name: "System", size: 25.0)
textField.textColor = theme?.textColour
}
}
}
self.navigationController?.navigationBar.setBarColour(colour: (theme?.tabBarColour)!, tint: (theme?.textColour)!)
navigationItem.titleView = resultSearchController?.searchBar
navigationItem.titleView?.bringSubview(toFront: (resultSearchController?.searchBar)!)
searchBar.delegate = self
searchBar.showsSearchResultsButton = true
searchBar.setImage(#imageLiteral(resourceName: "location_icon.png"), for: UISearchBarIcon.resultsList, state: UIControlState.normal)
resultSearchController?.hidesNavigationBarDuringPresentation = false
resultSearchController?.dimsBackgroundDuringPresentation = true
definesPresentationContext = true
locationSearchTable.mapView = mapView
locationSearchTable.handleMapSearchDelegate = self
}
Ok after a lot messing around, I discovered that in my custom UITabBarController I had used override func viewWillAppear(_ animated: Bool) without adding super.viewWillAppear() and that caused the problem! I assume because of that subviews weren't being laid out correctly. Hope that helps anyone who has a similar problem to mine.

Resources