Add auto complete to UITextField inside UITableViewCell in Swift - swift

I followed the suggestion here
https://stackoverflow.com/a/32948918/5447089
But it seems to work when a Text Field is inside UIViewController. In my case the TF is inside UITableViewCell and table with suggestions doesn't appear when there is some data for auto completion.
Also cellForRowAtIndexPath is not called. Other delegate methods such as numberOfRowsInSection work normally.
What can be the reason for this?
import UIKit
import CoreData
class AddElemTableViewCell: UITableViewCell, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTextField: UITextField!
var autocompleteTableView = UITableView(frame: CGRectMake(0,80,320,120), style: UITableViewStyle.Plain)
var elements = [“Beer”, “Bear”, “Park”, “Pad”]
var autocompleteElements = [String]()
var currentElem: Elem!
override func awakeFromNib() {
super.awakeFromNib()
myTextField.delegate = self
autocompleteTableView.delegate = self
autocompleteTableView.dataSource = self
autocompleteTableView.scrollEnabled = true
autocompleteTableView.hidden = true
myTextField.addTarget(self, action: #selector(AddElemTableViewCell.didChangeText(_:)), forControlEvents: .EditingChanged)
}
func didChangeText(textField:UITextField) {
autocompleteTableView.hidden = false
let substring = (myTextField.text! as NSString)
searchAutocompleteEntriesWithSubstring(substring as String)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func searchAutocompleteEntriesWithSubstring(substring: String)
{
autocompleteElements.removeAll(keepCapacity: false)
for curString in elements
{
let myString:NSString! = curString as NSString
let substringRange :NSRange! = myString.rangeOfString(substring,options: [.CaseInsensitiveSearch])
if (substringRange.location == 0)
{
autocompleteElements.append(curString)
}
}
autocompleteTableView.reloadData()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if textField == myTextField {
if (textField.text!.characters.count > 0) {
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedObjectContext = appDelegate.managedObjectContext
let entityElement = NSEntityDescription.entityForName("element", inManagedObjectContext: managedObjectContext)
let element = element(entity: entityElement!, insertIntoManagedObjectContext: managedObjectContext)
element.name = textField.text!
do {
try managedObjectContext.save()
} catch {
let saveError = error as NSError
print(saveError)
}
textField.text! = ""
textField.placeholder = “add new element”
self.endEditing(true)
}
}
return true
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return autocompleteElements.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let autoCompleteRowIdentifier = "AutoCompleteRowIdentifier"
let cell = UITableViewCell(style: UITableViewCellStyle.Default , reuseIdentifier: autoCompleteRowIdentifier)
let index = indexPath.row as Int
cell.textLabel!.text = autocompleteElements[index]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
myTextField.text = selectedCell.textLabel!.text
}
}

Related

Search bar isn't working and selection is gray (I want to be None)

My search bar isn't working and I'm not sure why. I followed a tutorial online. There is a picture of my find friends view controller below and the code for the view controller.
Also even though in my storyboard selection is set to "None" it is gray on ios.
Not sure how to fix the selection part. Search bar fixed and solution is in comments below.
import UIKit
class FindFriendsViewController: UIViewController {
var users = [User]()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var searchItem = [String]()
var searching = false
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
tableView.rowHeight = 71
let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:)))
tap.cancelsTouchesInView = false
self.view.addGestureRecognizer(tap)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UserService.usersExcludingCurrentUser { [unowned self] (users) in
self.users = users
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
extension FindFriendsViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var usernamesArr = [String]()
for user in users {
usernamesArr.append(user.username)
}
if searching {
return searchItem.count
} else {
return usernamesArr.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FindFriendsCell") as! FindFriendsCell
let user = users[indexPath.row]
var usernamesArr = [String]()
for user in users {
usernamesArr.append(user.username)
}
if searching {
cell.usernameLabel?.text = searchItem[indexPath.row]
} else {
cell.usernameLabel?.text = usernamesArr[indexPath.row]
cell.delegate = self
configure(cell: cell, atIndexPath: indexPath)
}
return cell
}
func configure(cell: FindFriendsCell, atIndexPath indexPath: IndexPath) {
let user = users[indexPath.row]
cell.usernameLabel.text = user.username
cell.followButton.isSelected = user.isFollowed
}
}
extension FindFriendsViewController: FindFriendsCellDelegate {
func didTapFollowButton(_ followButton: UIButton, on cell: FindFriendsCell) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
followButton.isUserInteractionEnabled = false
let followee = users[indexPath.row]
FollowService.setIsFollowing(!followee.isFollowed, fromCurrentUserTo: followee) { (success) in
defer {
followButton.isUserInteractionEnabled = true
}
guard success else { return }
followee.isFollowed = !followee.isFollowed
self.tableView.reloadRows(at: [indexPath], with: .none)
}
}
}
extension FindFriendsViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
var usernamesArr = [String]()
for user in users {
usernamesArr.append(user.username)
}
searchItem = usernamesArr.filter({$0.lowercased().prefix(searchText.count) == searchText.lowercased()})
searching = true
tableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searching = false
searchBar.text = ""
tableView.reloadData()
}
}

Show/hide table view cell using UISwitch

I want to use UISwitch to show/hide a tableViewCell in a dynamic table view.
UISwitch is defined in a class of `UITableViewCell.
#IBOutlet weak var switchState: UISwitch!
And in the another file I want say if this switch is ON, the number of rows will be 5 otherwise it should be 4
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let test = PopupViewCell()
if test.switchState?.isOn == true {
detailsTableView.reloadData()
return 5
} else {
return 4
}
}
But it's not working, and it always read `return 4.
I also test it:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let test = PopupViewCell()
if test.switchState.isOn {
detailsTableView.reloadData()
return 5
} else {
return 4
}
}
But I will get this error:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I am not sure that I have to use some action function before this process or not, I will be appreciated if someone can help me on that.
The most beginner friendly way to do it is with a delegate. When the Switch cell detects a .valueChanged event it should forward this to the delegate. The delegate in turn updates its model of whether or not to show the switch and then reloads the tableView.
Here is a Playground example:
import UIKit
import PlaygroundSupport
protocol SwitchDelegate: class {
func toggle(isOn: Bool)
}
class SwitchCell: UITableViewCell {
private lazy var switchControl: UISwitch = {
let switchControl = UISwitch()
contentView.addSubview(switchControl)
switchControl.translatesAutoresizingMaskIntoConstraints = false
switchControl.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12).isActive = true
switchControl.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
switchControl.addTarget(self, action: #selector(toggleSwitch(_:)), for: .valueChanged)
return switchControl
}()
private weak var delegate: SwitchDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
func configure(isOn: Bool, delegate: SwitchDelegate) {
switchControl.isOn = isOn
self.delegate = delegate
}
#objc private func toggleSwitch(_ sender: UISwitch) {
delegate?.toggle(isOn: sender.isOn)
}
}
class ViewController: UITableViewController {
private let data = (0..<5).map { $0 + 1 }
private var isOn = true
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: String(describing: UITableViewCell.self))
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count + (isOn ? 1 : 0)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if isOn && indexPath.row == 0 {
let switchCell = SwitchCell(style: .default, reuseIdentifier: String(describing: SwitchCell.self))
switchCell.configure(isOn: isOn, delegate: self)
return switchCell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UITableViewCell.self), for: indexPath)
let dataIndex = indexPath.row - (isOn ? 1 : 0)
cell.textLabel?.text = String(describing: data[dataIndex])
return cell
}
}
}
extension ViewController: SwitchDelegate {
func toggle(isOn: Bool) {
self.isOn = isOn
tableView.reloadData()
}
}
PlaygroundPage.current.liveView = ViewController()

TableView Swift with dynamic and fixed cells

I'm making an app that displays data from Firebase , I have a TV that has to show one fixed cell (to choose the type of data to display) and the other cell to display data from server this is the code:
import UIKit
import Firebase
import SwiftDate
class EventiTVC: UITableViewController {
let userID = FIRAuth.auth()?.currentUser?.uid
let ref = FIRDatabase.database().reference()
let utente = UserDefaults.standard
#IBOutlet weak var Menu_button: UIBarButtonItem!
var Eventi:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
if self.revealViewController() != nil {
Menu_button.target = self.revealViewController()
Menu_button.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
let imageView = UIImageView(image: #imageLiteral(resourceName: "Hangover_Background"))
imageView.contentMode = .scaleAspectFill
self.tableView.backgroundView = imageView
self.tableView.tableFooterView = UIView()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white,NSFontAttributeName: UIFont(name: "HelveticaNeue-Bold", size: 19)!]
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if self.revealViewController() != nil {
Menu_button.target = self.revealViewController()
Menu_button.action = #selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
self.navigationController?.navigationBar.barTintColor = UIColor.orange
self.navigationController?.navigationBar.tintColor = UIColor.white
self.navigationController?.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "HelveticaNeue-Bold", size: 19)!,NSForegroundColorAttributeName : UIColor.white]
DeterminaInfoProprietario()
DeterminoLocali()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if section == 0{
return 1
}
else {
return Eventi.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0{
let cell = Bundle.main.loadNibNamed("Event_Type", owner: self, options: nil)?.first as! Event_Type
return cell
}
else {
let cell = Bundle.main.loadNibNamed("Evento", owner: self, options: nil)?.first as! Evento
let EventoCorrente = Eventi[indexPath.row]
// scarico info Evento corrente ref.child("Eventi").child(EventoCorrente).observeSingleEvent(of: .value, with: { (snap) in
if snap.childrenCount != 0 {
let DatiEvento = snap.value as? NSDictionary
cell.Nome.text = DatiEvento?.value(forKey: "Nome") as! String!
cell.Locale.text = DatiEvento?.value(forKey: "Locale") as! String!
let urlcopertina = DatiEvento?.value(forKey: "Immagine Copertina") as! String!
cell.Copertina.aail_load(url: NSURL(string: urlcopertina!)!)
// per scaricare il colore , devo scaricare il locale
let locale = DatiEvento?.value(forKey: "Locale") as! String!
var Colore:UIColor? = nil
var Ombra:UIColor? = nil
self.ref.child("Locali").child(locale!).observeSingleEvent(of: .value, with: { (snap2) in
if snap2.childrenCount != 0 {
let DatiLocale = snap2.value as? NSDictionary
Colore = ColoriDaStringa(Colore: (DatiLocale?.value(forKey: "Colore Pagina"))! as! String)[0]
Ombra = ColoriDaStringa(Colore: (DatiLocale?.value(forKey: "Colore Pagina"))! as! String)[1]
cell.ViewC.backgroundColor = Colore!
cell.View_ombra.backgroundColor = Ombra!
}
})
}
else {
// Evento Cancellato? // gestire situazione
}
})
return cell
}
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat{
if indexPath.row == 0{
return 44
}else {
return 190
}
}
#IBAction func ritornaHome (Segue:UIStoryboardSegue){
}
}
I got 2 static cell and 1 dynamic cell, it should be the other way around, any idea why?
In your cellForRowAtIndexPath() method you should change your if statement from:
if (indexPath.row == 0)
to
if (indexPath.section == 0)
Modify these two functions to:
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Eventi.count+1
}
As we should go with latest features. You should go with Auto layout. Auto layout has in built feature for showing dynamic height of UITableView Cell. Refer below link if you want to learn.
Dynamic cell height UITableview
Otherwise here we have answer of issue in your code.
In numberOfSections() you have set wrong condition. Just replace
return 2
to
return 1
And
in numberOfRowsInSection() replace
if section == 0{
return 1
}
else {
return Eventi.count
}
to
return Eventi.count+1

How do you change a fetchRequest to an Array to use in a UITableView

I am tying to put fetched data from coredata in a UITableView but I get this "EXC_BAD_INSTRUCTION" .
Using the let swiftBlogs Array works just fine, so can someone show my how to convert the fetch to an Array or is that not the correct way?
import UIKit
import CoreData
class MainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var timeStampTextField: UITextField!
#IBOutlet var quickQuoteTextField: UITextField!
#IBOutlet var tableViewQuickQuote: UITableView!
let swiftBlogs = ["Ray Wenderlich", "NSHipster", "iOS Developer Tips", "Jameson Quave", "Natasha The Robot", "Coding Explorer", "That Thing In Swift", "Andrew Bancroft", "iAchieved.it", "Airspeed Velocity"]
var tableViewCellArray : Array<AnyObject> = []
var quickQuoteArray : Array<AnyObject> = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
var appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "QuickQuote" )
request.returnsObjectsAsFaults = false
tableViewCellArray = context.executeFetchRequest(request, error: nil)!
}
override func viewWillAppear(animated: Bool) {
quickQuoteTextField.text = ""
timeStampTextField.text = ""
}
#IBAction func clearButton(sender: AnyObject) {
quickQuoteTextField.text = ""
timeStampTextField.text = ""
}
#IBAction func addToQuickQuoteButton(sender: AnyObject) {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let ent = NSEntityDescription.entityForName("QuickQuote", inManagedObjectContext: context)
var newQuickQuote = QuickQuote(entity: ent!, insertIntoManagedObjectContext: context)
newQuickQuote.quickQuote = quickQuoteTextField.text
context.save(nil)
}
#IBAction func timeStampButton(sender: AnyObject) {
timeStamp()
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let ent = NSEntityDescription.entityForName("Time", inManagedObjectContext: context)
var newTime = Time(entity: ent!, insertIntoManagedObjectContext: context)
newTime.time = timeStampTextField.text
newTime.quote = quickQuoteTextField.text
context.save(nil)
}
func timeStamp (){
timeStampTextField.text = NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: NSDateFormatterStyle.FullStyle,
timeStyle: NSDateFormatterStyle.ShortStyle)
}
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return swiftBlogs.count // return quickQuoteArray.count
}
private let stampCellID: NSString = "cell" //This is the cell itself's identifier.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(stampCellID as String, forIndexPath: indexPath) as! UITableViewCell
var data: NSManagedObject = quickQuoteArray[indexPath.row] as! NSManagedObject
cell.textLabel?.text = data.valueForKey("quickQuote") as? String
// let row = indexPath.row
// cell.textLabel?.text = swiftBlogs[row]
return cell
}
/*
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
var appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var context:NSManagedObjectContext = appDel.managedObjectContext!
if editingStyle == UITableViewCellEditingStyle.Delete {
let tv = tableView
context.deleteObject(quickQuoteArray.self[indexPath.row] as! NSManagedObject)
tv.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
context.save(nil)
}
*/
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
You're mixing up your arrays swiftBlogs and quickQuoteArray. Whether or not the table view tries to access an array element quickQuoteArray[indexpath.row] is dependent on if it thinks that index is populated, based on the result from numberOfRowsInSection. In the numberOfRowsInSection method, you are returning the count of swiftBlogs, which is always the 10 or so strings you hand-typed in. So before your request is ever even executed, or the view even has a chance to populate anything else, it's trying to show elements that aren't present in the array you're using in cellForRowAtIndexPath.
In short:
Always use the same array in cellForRowAtIndexPath as you are using in numberOfRowsInSection. Here, you've mixed two different arrays, quickQuoteArray and swiftBlogs.

Search bar at the top of a UIPickerView in Swift

So I have a textField, which when the user presses, it shows a UIPickerView, which is populated from an array.
Is it possible for there to be search bar at the top of the pickerView, so the user can search for something in the pickerView?
I've not seen this done before so have no idea if it's possible?
Thanks in advance.
UIPickerView is really meant for a few options - if you need to present something that has a lot more options, I would suggest a table view with a search bar. Search Bar Tutorial is a good start.
Here is an easy solution which I have used on my recent project. First of all you need to concentrate on the following points.
Try to use UITextfield for better customization
Use table view to populate data easily inside your main viewController class.
Avoid using segue thing which is little bit annoying and old fashioned.
Try to make your code more realistic and hassle-free.
First things first :-
I am using Xcode 7.2.2 with Swift 2.1
Using native filter method to filter form the array and reuse that.
Using Array of Array type Dictionary(Swift)
Concentrating on the above points.. :)
Here is my class file. Go through the code and you will understand...
import UIKit
class ComposeMessageClass: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
var filtered = [[String : String]]()
let customerNameForSearch: [[String : String]] = [["name": "Tuhin"], ["name": "Superman"], ["name" : "Rahul"], ["name": "Batman"], ["name": "Spiderman"]]
let customerNameToSearchTemp = ["Tuhin", "Superman", "Rahul", "Batman", "Spiderman"]
var searchActive: Bool = false
#IBOutlet weak var autofillTable: UITableView!
#IBOutlet weak var autofillTableView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.autofillTableView.hidden = true
self.autofillTable.delegate = self
self.autofillTable.dataSource = self
self.autofillTable.backgroundColor = tableViewBackGroundColor
self.autofillTable.separatorColor = tableViewSeperatorColor
self.autofillTable.layer.borderColor = tableViewBorderColor
}
}
override func viewWillAppear(animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
}
func textFieldDidBeginEditing(textField: UITextField) {
}
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
var updatedTextString : NSString = textField.text! as NSString
updatedTextString = updatedTextString.stringByReplacingCharactersInRange(range, withString: string)
self.filtered.removeAll()
self.customerNameToSearchTemp.filter({ (text) -> Bool in
let tmp: NSString = text
let range = tmp.rangeOfString(updatedTextString as String, options: NSStringCompareOptions.CaseInsensitiveSearch)
if range.location != NSNotFound{
let dataArr = ["name": tmp as String]
filtered.append(dataArr)
}
return false
}
})
if(filtered.count == 0){
filtered = [["name" : "No results found"]]
searchActive = true
} else {
searchActive = true;
}
self.autofillTable.reloadData()
return true
}
func textFieldDidEndEditing(textField: UITextField) {
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(searchActive) {
return self.filtered.count
}
return self.customerNameForSearch.count
}
internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.autofillTable.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.backgroundColor = UIColor.clearColor()
cell.textLabel!.textColor = tableViewCellTextColorGreen
cell.textLabel!.textAlignment = .Center
cell.selectionStyle = .None
cell.textLabel!.font = UIFont(name: "System", size:17)
if(searchActive){
if filtered[indexPath.row]["name"]! == "No results found"{
cell.textLabel!.text = self.filtered[indexPath.row]["name"]!
cell.userInteractionEnabled = false
}else{
cell.userInteractionEnabled = true
cell.textLabel?.text = self.filtered[indexPath.row]["name"]!
}
} else {
cell.userInteractionEnabled = true
cell.textLabel?.text = self.appDelegateObjForThisClass.customerNameForSearch[indexPath.row]["name"]!
}
return cell
}
internal func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
if(self.autofillTable.respondsToSelector(Selector("setSeparatorInset:"))){
self.autofillTable.separatorInset = UIEdgeInsetsZero
}
if(self.autofillTable.respondsToSelector(Selector("setLayoutMargins:"))){
self.autofillTable.layoutMargins = UIEdgeInsetsZero
}
if(cell.respondsToSelector(Selector("setLayoutMargins:"))){
cell.layoutMargins = UIEdgeInsetsZero
}
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.backgroundColor = UIColor.clearColor()
cell?.textLabel?.textColor = tableViewCellTextColorGreen
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell?.backgroundColor = UIColor.blackColor()
cell?.textLabel?.textColor = tableViewCellTextColorWhite
self.selectedCustomerId.removeAll()
if(searchActive){
self.contactNameTxtFld.text = self.filtered[indexPath.row]["name]!
}else{
self.contactNameTxtFld.text = self.appDelegateObjForThisClass.customerNameForSearch[indexPath.row]["name"]!
}
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
self.view.endEditing(true)
}
}
Example to set over the storyboard.
Thanks.
Hope this helped.
Any Modification or suggestion our questions would be appreciated.
I added a custom header view for the table with a textField insted of searcontroller(searchbar) and cancel button programmatically with little custmization to the tableView.
I added the following code to filter and get the updated search results
class ViewController: UIViewController,UITextFieldDelegate,UITableViewDelegate,UITableViewDataSource{
let speciality=["Andhra","Bhihar","uttharPradesh","kerala","karnataka","kashmir","thamilnadu","assam","jarkhand","dolapure","manjil","udaypoor","sholapoor","Atthapure","Barampure","Khasi"]
var filteredArray = [String]()
var shouldShowSearchResults = false
var tableView:UITableView!
var yaxis:CGFloat=10
var txtdateOfOperation:UITextField!
var searchTextField:UITextField!
var cancelButton:UIButton!
override func viewDidLoad() {
let dateOfOperationLabel=UILabel(frame:CGRectMake(8,100,200,16))
dateOfOperationLabel.text="State"
dateOfOperationLabel.textColor=UIColor.blackColor()
dateOfOperationLabel.textAlignment=NSTextAlignment.Left
dateOfOperationLabel.font = UIFont.systemFontOfSize(13.0)
dateOfOperationLabel.numberOfLines = 0;
self.view.addSubview(dateOfOperationLabel)
txtdateOfOperation=UITextField(frame: CGRectMake(8,130,300,28))
txtdateOfOperation.borderStyle=UITextBorderStyle.RoundedRect
txtdateOfOperation.returnKeyType=UIReturnKeyType.Done
txtdateOfOperation.userInteractionEnabled=true
txtdateOfOperation.keyboardType=UIKeyboardType.NumberPad
self.view.addSubview(txtdateOfOperation)
tableView=UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain)
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate=self
tableView.dataSource=self
tableView.reloadData()
let view=UIView(frame:CGRectMake(0,0,UIScreen.mainScreen().bounds.width,35))
view.backgroundColor=UIColor.lightGrayColor()
searchTextField=UITextField(frame:CGRectMake(8,3,view.bounds.width-70,28))
searchTextField.borderStyle=UITextBorderStyle.RoundedRect
searchTextField.returnKeyType=UIReturnKeyType.Done
searchTextField.userInteractionEnabled=true
searchTextField.delegate=self
searchTextField.placeholder="Search Here..."
searchTextField.clearButtonMode = .WhileEditing
searchTextField.leftViewMode = UITextFieldViewMode.Always
searchTextField.leftView = UIImageView(image: UIImage(named: "search-icon"))
searchTextField.addTarget(self, action: #selector(searchTextFieldDidBeginEdit), forControlEvents: UIControlEvents.EditingChanged)
view.addSubview(searchTextField)
cancelButton=UIButton(frame:CGRectMake(view.bounds.width-65,3,70,28))
cancelButton.setTitle("Cancel", forState: UIControlState.Normal)
cancelButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Normal)
cancelButton.addTarget(self, action: #selector(searchBarCancelButton_Click), forControlEvents: UIControlEvents.TouchUpInside)
cancelButton.userInteractionEnabled=false
view.addSubview(cancelButton)
tableView.tableHeaderView = view
txtdateOfOperation.inputView=tableView
searchTextField.inputView=tableView
self.tableView.reloadData()
}
func textFieldDidBeginEditing(textField: UITextField) {
shouldShowSearchResults = true
cancelButton.userInteractionEnabled=true
cancelButton.setTitleColor(UIColor(red: 51/255, green: 153/255, blue: 255/255, alpha: 1.0), forState: UIControlState.Normal)
tableView.reloadData()
}
func textFieldDidEndEditing(textField: UITextField) {
cancelButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Normal)
}
func searchTextFieldDidBeginEdit(textField:UITextField) {
if let searchText=textField.text{
filteredArray = speciality.filter({ (country) -> Bool in
let countryText: NSString = country
return (countryText.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch).location) != NSNotFound
})
tableView.reloadData()
}
}
func searchBarCancelButton_Click(){
searchTextField.text=nil
searchTextField.resignFirstResponder()
shouldShowSearchResults = false
tableView.reloadData()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if shouldShowSearchResults {
return filteredArray.count
}
else {
return speciality.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if shouldShowSearchResults {
cell.textLabel?.text = filteredArray[indexPath.row]
}
else {
cell.textLabel?.text = speciality[indexPath.row]
}
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60.0
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if shouldShowSearchResults{
txtdateOfOperation.text=filteredArray[indexPath.row]
searchTextField.text=nil
searchTextField.resignFirstResponder()
txtdateOfOperation.resignFirstResponder()
shouldShowSearchResults=false
filteredArray=[String]()
tableView.reloadData()
}
else{
txtdateOfOperation.text=speciality[indexPath.row]
searchTextField.resignFirstResponder()
tableView.resignFirstResponder()
txtdateOfOperation.resignFirstResponder()
}
}
}
i tested it and its working perfectly