I add a search bar by adding subview into a UIView. When I tap the search bar, cancel button shows up, however the keyboard disappear immediately. I have to tap the search bar again so that I can input some text for searching.
Any thoughts?
Use the following code:
import UIKit
class ViewController: UIViewController,UISearchDisplayDelegate, UISearchBarDelegate,UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var headingLabel: UILabel!
#IBOutlet weak var countriesTableView: UITableView!
#IBOutlet weak var countrySerachBar: UISearchBar!
var marrCountryList = [String]()
var marrFilteredCountryList = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.countriesTableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
marrCountryList = ["USA", "Bahamas", "Brazil", "Canada", "Republic of China", "Cuba", "Egypt", "Fiji", "France", "Germany", "Iceland", "India", "Indonesia", "Jamaica", "Kenya", "Madagascar", "Mexico", "Nepal", "Oman", "Pakistan", "Poland", "Singapore", "Somalia", "Switzerland", "Turkey", "UAE", "Vatican City"]
self.countriesTableView.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.countrySerachBar.becomeFirstResponder()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if tableView == self.searchDisplayController!.searchResultsTableView {
return self.marrFilteredCountryList.count
} else {
return self.marrCountryList.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cellCountry = self.countriesTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
var countryName : String!
if tableView == self.searchDisplayController!.searchResultsTableView {
countryName = marrFilteredCountryList[(indexPath as NSIndexPath).row]
} else {
countryName = marrCountryList[(indexPath as NSIndexPath).row]
}
cellCountry.textLabel?.text = countryName
return cellCountry
}
func filterTableViewForEnterText(_ searchText: String) {
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchText)
let array = (self.marrCountryList as NSArray).filtered(using: searchPredicate)
self.marrFilteredCountryList = array as! [String]
self.countriesTableView.reloadData()
}
func searchDisplayController(_ controller: UISearchDisplayController, shouldReloadTableForSearch searchString: String?) -> Bool {
self.filterTableViewForEnterText(searchString!)
return true
}
func searchDisplayController(_ controller: UISearchDisplayController,
shouldReloadTableForSearchScope searchOption: Int) -> Bool {
self.filterTableViewForEnterText(self.searchDisplayController!.searchBar.text!)
return true
}
}
Storyboard screenshot:
Output:
Please check my GitHub link to test sample project:
https://github.com/k-sathireddy/SearchDisplayControllerSample
Related
import UIKit
let country = ["Argentina", "Australia", "Belgium", "Brazil", "Colombia", "Costa Rica", "Croatia", "Denmark", "Egypt", "England", "France", "Germany", "Iceland", "Iran", "Japan", "Mexico", "Morocco", "Nigeria", "Panama", "Peru", "Poland", "Portugal", "Republic of Korea", "Russia", "Saudi Arabia", "Senegal", "Serbia", "Spain", "Sweden", "Switzerland", "Tunis", "Uruguay"]
let country2 = ["Argentina2", "Australia2", "Belgium2", "Brazil2", "Colombia2", "Costa Rica2", "Croatia2", "Denmark2", "Egypt2", "England2", "France2", "Germany2", "Iceland2", "Iran2", "Japan2", "Mexico2", "Morocco2", "Nigeria2", "Panama2", "Peru2", "Poland2", "Portugal2", "Republic of Korea2", "Russia2", "Saudi Arabia2", "Senegal2", "Serbia2", "Spain2", "Sweden2", "Switzerland2", "Tunis2", "Uruguay2"]
let country3 = ["Argentina3", "Australia3", "Belgium3", "Brazil3", "Colombia3", "Costa Rica3", "Croatia3", "Denmark3", "Egypt3", "England3", "France3", "Germany3", "Iceland3", "Iran3", "Japan3", "Mexico3", "Morocco3", "Nigeria3", "Panama3", "Peru3", "Poland3", "Portugal3", "Republic of Korea3", "Russia3", "Saudi Arabia3", "Senegal3", "Serbia3", "Spain3", "Sweden3", "Switzerland3", "Tunis3", "Uruguay3"]
var myIndex = 0
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredArray = country.filter({$0.lowercased().contains(searchText.lowercased())})
if searchText == "" {
filteredArray = country
}
self.tableView.reloadData()
}
var filteredArray = [String]()
var searchController = UISearchController()
var searchBar = UISearchBar()
var resultController = UITableViewController()
let country = ["Argentina", "Australia", "Belgium", "Brazil", "Colombia", "Costa Rica", "Croatia", "Denmark", "Egypt", "England", "France", "Germany", "Iceland", "Iran", "Japan", "Mexico", "Morocco", "Nigeria", "Panama", "Peru", "Poland", "Portugal", "Republic of Korea", "Russia", "Saudi Arabia", "Senegal", "Serbia", "Spain", "Sweden", "Switzerland", "Tunis", "Uruguay"]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
filteredArray = country
searchBar.frame = CGRect(x: 0, y: 0, width: 400, height: 50)
self.tableView.tableHeaderView = searchBar
self.searchBar.delegate = self
definesPresentationContext = true
}
// MARK: - Table view data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.filteredArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
cell.accessoryType = .disclosureIndicator
cell.textLabel?.font = UIFont.systemFont(ofSize: 18.0)
cell.textLabel?.text = self.filteredArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "seque", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "seque" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let viewController: ViewController = segue.destination as! ViewController
viewController.myIndex = indexPath
}
}
}
}
There are some problem in your code:
In cellForRow you are dequeuing your Table View, Not the tableView given by delegate method. self.tableView.dequeueReusableCell(withIdentifier: Here do not use self.
You are using resultController which does not have any prototype cell to display data. Here your app will crash.
I do not understand what you have done in prepareForSegue
Do not use any global variable. If you want to use myIndex, make a property in destinationVC and pass it prepareForSegue.
You are displaying filteredArray on table view and on selection getting value from country array, that's why you are getting wrong value.
What I found is, you do not need a SearchViewController because you are using a single View controller to display your filtered data.
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredArray = country.filter({$0.lowercased().contains(searchText.lowercased())})
if searchText == "" {
filteredArray = country
}
self.tableView.reloadData()
}
var filteredArray = [String]()
var searchController = UISearchController()
var searchBar = UISearchBar()
var resultController = UITableViewController()
let country = ["Argentina", "Australia", "Belgium", "Brazil", "Colombia", "Costa Rica", "Croatia", "Denmark", "Egypt", "England", "France", "Germany", "Iceland", "Iran", "Japan", "Mexico", "Morocco", "Nigeria", "Panama", "Peru", "Poland", "Portugal", "Republic of Korea", "Russia", "Saudi Arabia", "Senegal", "Serbia", "Spain", "Sweden", "Switzerland", "Tunis", "Uruguay"]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
filteredArray = country
searchBar.frame = CGRect(x: 0, y: 0, width: 400, height: 50)
self.tableView.tableHeaderView = searchBar
self.searchBar.delegate = self
definesPresentationContext = true
}
// MARK: - Table view data source
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.filteredArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
cell.accessoryType = .disclosureIndicator
cell.textLabel?.font = UIFont.systemFont(ofSize: 18.0)
cell.textLabel?.text = self.filteredArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "seque", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "seque" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let viewController: ViewController = segue.destination as! ViewController
let newIndex: Int = country.index(of: filteredArray[indexPath.row])!
viewController.myIndex = newIndex
}
}
}
}
Please let me know if this worked.
EDIT
Your class ViewController should look like:
class ViewController: UIViewController {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myImageView2: UIImageView!
#IBOutlet weak var myImageView3: UIImageView!
var myIndex: Int!
override func viewDidLoad() {
super.viewDidLoad()
myImageView.image = UIImage(named: country[myIndex])
myImageView2.image = UIImage(named:country2[myIndex])
myImageView3.image = UIImage(named: country3[myIndex])
}
// Other methods
}
I'm trying to load the items of an array into a UITableView in a Swift iOS App.
ViewController.swift
import UIKit
class ViewController: UIViewController {
let website = MyWebsite()
let authenticated = ViewAuthenticated()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func getData(_ sender: Any) {
var arrayTEST = self.website.getArray() //["red", "green", "blue"]
self.authenticated.data = arrayTEST //["red", "green", "blue"]
let viewAuth = self.storyboard?.instantiateViewController(withIdentifier: "ViewAuthenticated") as! ViewAuthenticated
self.present(viewAuth, animated: true)
}
}
ViewAuthenticated.swift
import UIKit
class ViewAuthenticated: UIViewController, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
public var data: [String] = ["123", "456", "789"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier")!
let text = data[indexPath.row]
cell.textLabel?.text = text
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
What I would like to do is creating a UITableView containing the items sent by ViewController.
I think the problem is that in ViewAuthenticated the UITableView is created before ViewController sends his new array (["red", "green", "blue"]).
How can I solve this?
You should set the array of values to data property of ViewAuthenticated View, before presenting the view.
#IBAction func getData(_ sender: Any) {
var arrayTEST = self.website.getArray() //["red", "green", "blue"]
self.authenticated.data = arrayTEST //["red", "green", "blue"]
let viewAuth = self.storyboard?.instantiateViewController(withIdentifier: "ViewAuthenticated") as! ViewAuthenticated
viewAuth.data = self.authenticated.data
self.present(viewAuth, animated: true)
}
And remove the hardcoded data array value. Change it to :
var data: [String] = []
Simple solution, the authenticated controller is not needed at all:
let authenticated = ViewAuthenticated()
...
#IBAction func getData(_ sender: Any) {
let viewAuth = self.storyboard?.instantiateViewController(withIdentifier: "ViewAuthenticated") as! ViewAuthenticated
viewAuth.data = self.website.getArray() //["red", "green", "blue"]
self.present(viewAuth, animated: true)
}
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var filteredStates = [State]()
var states = [
State(stateName: "Alabama", abbreviation: "AL" ),
State(stateName: "Alaska", abbreviation: "AK" ),
State(stateName: "Arizona", abbreviation: "AZ"),
State(stateName: "Arkansas", abbreviation: "AR"),
State(stateName: "California", abbreviation: "CA"),
State(stateName: "Colorado", abbreviation: "CO"),
State(stateName: "Connecticut", abbreviation: "CT"),
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
searchBar.delegate = self
filteredStates = states
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tableView.addGestureRecognizer(tap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as UITableViewCell
let state = states[indexPath.row]
cell.textLabel?.text = state.stateName
cell.detailTextLabel?.text = state.abbreviation
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredStates.count
}
// This method updates filteredData based on the text in the Search Box
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredStates = searchText.isEmpty ? states : states.filter { (item: State) -> Bool in
return item.stateName.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
}
print(filteredStates)
tableView.reloadData()
}
// Wehn search bar being editing, cancel button pops up
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
}
// When search bar cancel button clicked
// Cancel button dismiss, search text is empty, keyboard dismiss
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = false
searchBar.text = ""
searchBar.resignFirstResponder()
}
// when click outside of keyboard
// Keyboard dismiss
func handleTap() {
self.view.endEditing(true)
}
// When clicked search button
// keyboard dismiss
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
}
}
My filter is not working correctly. Not sure where I did wrong. I think it might be something wrong with function searchBar function.
The filter is not working correct
The filter is not working correct2
I have slightly changed your code, and with filter used contains and made some changes in delegate method of UISearchBar and used filteredStates with all the method of UITableViewDataSource.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
var filteredStates = [State]()
var states = [
State(stateName: "Alabama", abbreviation: "AL" ),
State(stateName: "Alaska", abbreviation: "AK" ),
State(stateName: "Arizona", abbreviation: "AZ"),
State(stateName: "Arkansas", abbreviation: "AR"),
State(stateName: "California", abbreviation: "CA"),
State(stateName: "Colorado", abbreviation: "CO"),
State(stateName: "Connecticut", abbreviation: "CT"),
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
filteredStates = states
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredStates.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell")!
//Access data from filteredStates array not from states array
cell.textLabel?.text = self.filteredStates[indexPath.row].stateName
cell.detailTextLabel?.text = self.filteredStates[indexPath.row].abbreviation
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(self.filteredStates[indexPath.row].stateName)
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.showsCancelButton = true
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.filteredStates = searchText.isEmpty ? states : states.filter( { $0.stateName.localizedCaseInsensitiveContains(searchText) })
self.tableView.reloadData()
}
func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.showsCancelButton = false
searchBar.text = ""
self.filteredStates = states
self.tableView.reloadData()
}
}
Note: I haven't added code that you are using with TapGesture so don't forgot to add that.
Create another array to store the searched value
Implement filter logic on your searchBar: textDidChange method
Create a Bool (eg. isActive) to indicate if the search happened or cancelled on searchBarShouldBeginEditing and searchBarCancelButtonClicked
On your cellForRow, you can check for the Bool isActive to switch the let state = states[indexPath.row] to let state = filteredStates[indexPath.row]
I want to display the details of one one table row onto another viewController. But it shows an error saying ' fatal error: unexpectedly found nil while unwrapping an Optional value'
The code for my VC is as follows:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate, UITableViewDelegate,UITableViewDataSource, UICollectionViewDataSource, UICollectionViewDelegate {
#IBOutlet var nameForUser: UITextField!
#IBOutlet var loginButton: UIButton!
#IBOutlet var tableView: UITableView!
let allEvents = Events.allEvents
var nextScreenRow: Events!
override func viewDidLoad() {
super.viewDidLoad()
//nameForUser.text! = "Please Enter Name Here"
// Do any additional setup after loading the view, typically from a nib.
}
func textFieldDidBeginEditing(textField: UITextField) {
textField.text = ""
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.allEvents.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("eventsCell")!
let event = self.allEvents[indexPath.row]
cell.textLabel?.text = event.eventName
cell.imageView?.image = UIImage(named: event.imageName)
cell.detailTextLabel?.text = event.entryType
//cell.textLabel?.text = allEvents[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
nextScreenRow = allEvents[indexPath.row]
performSegueWithIdentifier("tryToConnect", sender:self)
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.allEvents.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let sec = collectionView.dequeueReusableCellWithReuseIdentifier("eventsSec", forIndexPath: indexPath) as! GridCollectionViewCell
let event = self.allEvents[indexPath.row]
sec.imageView.image = UIImage(named: event.imageName)
sec.caption.text = event.entryType
return sec
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("tryToConnect2", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "successfulLogin"){
segue.destinationViewController as! TabController
//let userName = nameForUser.text
//controller.userName = userName
}
else if (segue.identifier == "tryToConnect"){
let dest = segue.destinationViewController as! DetailedEventViewController
dest.deatiledEvent.text = nextScreenRow.eventName
dest.eventType.text = nextScreenRow.entryType
dest.imageView.image = UIImage(named: nextScreenRow.imageName)
}
}
#IBAction func loginButtonWhenPressed(sender: UIButton) {
let userName = nameForUser.text
if userName == "" {
let nextController = UIAlertController()
nextController.title = "Error!"
nextController.message = "Please enter a name"
let okAction = UIAlertAction(title: "okay", style: UIAlertActionStyle.Default) {
action in self.dismissViewControllerAnimated(true, completion: nil)
}
nextController.addAction(okAction)
self.presentViewController(nextController, animated: true, completion: nil)
}
}
}
When I run this, it shows the error. I have also assigned the delegates for the table view. The code for 'DetailedEventVC' is:
import UIKit
class DetailedEventViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var deatiledEvent: UILabel!
#IBOutlet weak var eventType: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Why does it show that the values are nil?
Help would be greatly appreciated.
Thanks in advance.
The 'EventsDetails.swift' file which has the details of events are a structure. Is there anything wrong in the way I'm calling the values?
import Foundation
import UIKit
struct Events {
let eventName: String
let entryType: String
let imageName: String
static let EventKey = "NameKey"
static let EntryTypeKey = "EntryType"
static let ImageNameKey = "ImageNameKey"
init(dictionary:[String : String]) {
self.eventName = dictionary[Events.EventKey]!
self.entryType = dictionary[Events.EntryTypeKey]!
self.imageName = dictionary[Events.ImageNameKey]!
}
}
extension Events {
static var allEvents: [Events] {
var eventsArray = [Events]()
for d in Events.localEventsData(){
eventsArray.append(Events(dictionary: d))
}
return eventsArray
}
static func localEventsData()-> [[String: String]] {
return [
[Events.EventKey:"Metallica Concert in Palace Grounds", Events.EntryTypeKey: "Paid Entry", Events.ImageNameKey:"Metallica"],
[Events.EventKey:"Saree Exhibition in Malleswaram Grounds", Events.EntryTypeKey: "Free Entry", Events.ImageNameKey:"SareeExhibition"],
[Events.EventKey:"Wine tasting event in Links Brewery", Events.EntryTypeKey: "Paid Entry", Events.ImageNameKey:"WineTasting"],
[Events.EventKey:"Startups Meet in Kanteerava Stadium", Events.EntryTypeKey: "Paid Entry", Events.ImageNameKey:"StartupMeet"],
[Events.EventKey:"Summer Noon Party in Kumara Park", Events.EntryTypeKey: "Paid Entry", Events.ImageNameKey:"SummerNoonParty"],
[Events.EventKey:"Rock and Roll nights in Sarjapur Road", Events.EntryTypeKey: "Paid Entry", Events.ImageNameKey:"RockNRollNight"],
[Events.EventKey:"Barbecue Fridays in Whitefield", Events.EntryTypeKey: "Paid Entry", Events.ImageNameKey:"BBQFriday"],
[Events.EventKey:"Summer workshop in Indiranagar", Events.EntryTypeKey: "Free Entry", Events.ImageNameKey:"SummerWorkshop"],
[Events.EventKey:"Impressions & Expressions in MG Road", Events.EntryTypeKey: "Free Entry", Events.ImageNameKey:"ImpressionAndExpression"],
[Events.EventKey:"Italian carnival in Electronic City", Events.EntryTypeKey: "Free Entry", Events.ImageNameKey:"ItalianCarnival"]
]
}
}
Create properties in your destination viewController and use them like below
import UIKit
class DetailedEventViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var deatiledEvent: UILabel!
#IBOutlet weak var eventType: UILabel!
var myImage = UIImage?
var eventDetails = ""
var typeOfEvent = ""
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = myImage
deatiledEvent.text = eventDetails
eventType.text = typeOfEvent
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
and then in your first viewController you can access them like
let dest = segue.destinationViewController as! DetailedEventViewController
dest.eventDetails = nextScreenRow.eventName
dest.typeOfEvent = nextScreenRow.entryType
dest.myImage = UIImage(named: nextScreenRow.imageName)
I've been at this for a while and I can not figure out how to pass data from the table view cell to a new "detail" controller. I understand the segue that connects it to a new controller but setting variables in that class to some values fails (doesn't show the values). This is what I currently have:
import UIKit
class BuyTreeViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
var products : [Product] = []
var filteredProducts = [Product]()
override func viewDidLoad() {
self.products = [
Product(name:"Chocolate", price: 11, description: "i"),
Product(name:"Candy", price: 12, description: "h"),
Product(name:"Break", price: 13, description: "g"),
Product(name:"Apple", price: 14, description: "f"),
Product(name:"Computer", price: 15, description: "e"),
Product(name:"Laptop", price: 16, description: "d"),
Product(name:"Cup", price: 17, description: "c"),
Product(name:"Table", price: 18, description: "b"),
Product(name:"Chair", price: 19, description: "a")
]
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.searchDisplayController!.searchResultsTableView {
return self.filteredProducts.count
} else {
return self.products.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//ask for a reusable cell from the tableview, the tableview will create a new one if it doesn't have any
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
var product : Product
// Check to see whether the normal table or search results table is being displayed and set the Candy object from the appropriate array
if tableView == self.searchDisplayController!.searchResultsTableView {
product = filteredProducts[indexPath.row]
} else {
product = products[indexPath.row]
}
// Configure the cell
cell.textLabel!.text = product.name
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
return cell
}
func filterContentForSearchText(searchText: String, scope: String = "All") {
self.filteredProducts = self.products.filter(
{
( product : Product) -> Bool in
var categoryMatch = (scope == "All") || (product.category == scope)
var stringMatch = product.name.rangeOfString(searchText)
return categoryMatch && (stringMatch != nil)
})
}
func searchDisplayController(controller: UISearchDisplayController!, shouldReloadTableForSearchString searchString: String!) -> Bool {
let scopes = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
let selectedScope = scopes[self.searchDisplayController!.searchBar.selectedScopeButtonIndex] as String
self.filterContentForSearchText(searchString, scope: selectedScope)
return true
}
func searchDisplayController(controller: UISearchDisplayController!,
shouldReloadTableForSearchScope searchOption: Int) -> Bool {
let scope = self.searchDisplayController!.searchBar.scopeButtonTitles as [String]
self.filterContentForSearchText(self.searchDisplayController!.searchBar.text, scope: scope[searchOption])
return true
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("productDetail", sender: tableView)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "productDetail" {
// let productDetailViewController = segue.destinationViewController as UIViewController
let productDetailViewController = segue.destinationViewController as ProductDetailViewController
productDetailViewController.testLabel.text = "123345"
if sender as UITableView == self.searchDisplayController!.searchResultsTableView {
let indexPath = self.searchDisplayController!.searchResultsTableView.indexPathForSelectedRow()!
let destinationTitle = self.filteredProducts[indexPath.row].name
productDetailViewController.title = destinationTitle
} else {
let indexPath = self.tableView.indexPathForSelectedRow()!
let destinationTitle = self.products[indexPath.row].name
productDetailViewController.title = destinationTitle
}
productDetailViewController.productPriceText = "10"
productDetailViewController.productTitleText = "100"
productDetailViewController.productDescriptionText = "100"
}
}
And this is what I have in the ProductDetailViewController:
import UIKit
class ProductDetailViewController: UIViewController {
#IBOutlet weak var productDescription: UITextView!
#IBOutlet weak var productPrice: UITextField!
#IBOutlet weak var productTitle: UITextField!
#IBOutlet weak var connectUserButton: UIButton!
#IBOutlet weak var testLabel: UILabel!
// var productDescriptionText: String
// var productPriceText: String
// var productTitleText: String
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// productDescription.text = productDescriptionText
// productPrice.text = productPriceText
// productTitle.text = productTitleText
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func contactUserClicked(sender: AnyObject) {
println("conentUserButton clicked")
}
For your prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "productDetail" {
let indexPath = self.tableView.indexPathForSelectedRow()
let theSelectedRow = filteredProducts[indexPath!.row]
let theDestination = segue.destinationViewController as ProductDetailViewController
theDestination.productPriceText = "10"
theDestination.productTitleText = "100"
theDestination.productDescriptionText = "100"
} else
//only needed if more than one segue
}
}
Your detailViewController looked good to me. If you still have issues, I will post a more complete example.