Solution : https://stackoverflow.com/a/39638032/1106035
I am new to Swift, I need to reload my records when I click on the UIButton action. For me reload method is stop working. I tried in all the possible ways as following:
Here is the function that I call when I tap the button
#IBAction func refresh(sender: AnyObject) {
// I tried this one but doesn't works
dispatch_async(dispatch_get_main_queue()) {
self.tblNotes.reloadData()
}
// This one too doesn't works for me
self.tblNotes.reloadData()
//Neither this
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tblNotes.reloadData()
})
}
Below one is my entire Class
class ListaTrmTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate , UISearchDisplayDelegate, EditNoteViewControllerDelegate {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet var tblNotes: UITableView!
var arrNotes: Array<CKRecord> = []
var editedNoteRecord: CKRecord!
var selectedNoteIndex: Int!
var searchActive : Bool = false
var filtered:Array<CKRecord> = []
var notesArray = [ListaTrmTableViewController]()
override func viewDidLoad() {
super.viewDidLoad()
tblNotes.delegate = self
tblNotes.dataSource = self
searchBar.delegate = self
fetchNotes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
if(searchActive) {
return filtered.count
}
return arrNotes.count
}
//Cell height size
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 50.0
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedNoteIndex = indexPath.row
performSegueWithIdentifier("viewControllerSg", sender: self)
}
//Segue to other ViewController
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "viewControllerSg" {
let editNoteViewController = segue.destinationViewController as! ViewController
if let index = selectedNoteIndex {
editNoteViewController.editedNoteRecord = arrNotes[index]
}
if(searchActive){
editNoteViewController.editedNoteRecord = filtered[selectedNoteIndex]
}
}
}
// Retrive data from CloudKit
func fetchNotes() {
let container = CKContainer.defaultContainer()
let privateDatabase = container.publicCloudDatabase
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "Notes", predicate: predicate)
query.sortDescriptors = [NSSortDescriptor(key: "Title", ascending: true)]
privateDatabase.performQuery(query, inZoneWithID: nil) { (results, error) -> Void in
if error != nil {
println(error)
}
else {
println(results)
for result in results {
self.arrNotes.append(result as! CKRecord)
}
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.tblNotes.reloadData()
self.tblNotes.hidden = false
})
}
}
}
func didSaveNote(noteRecord: CKRecord, wasEditingNote: Bool) {
if !wasEditingNote {
arrNotes.append(noteRecord)
}
else {
arrNotes.insert(noteRecord, atIndex: selectedNoteIndex)
arrNotes.removeAtIndex(selectedNoteIndex + 1)
selectedNoteIndex = nil
}
if tblNotes.hidden {
tblNotes.hidden = false
}
tblNotes.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("idCellNote", forIndexPath: indexPath) as! UITableViewCell
if(searchActive){
let noteRecord: CKRecord = filtered[indexPath.row]
cell.textLabel?.text = noteRecord.valueForKey("Atitulo") as? String
} else {
let noteRecord: CKRecord = arrNotes[indexPath.row]
cell.textLabel?.text = noteRecord.valueForKey("Atitulo") as? String
}
return cell
}
// Search functions
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
filtered = arrNotes.filter ({ (note) -> Bool in
let titles = note.objectForKey("Atitulo") as? String
//proceed as per normal
let range = titles!.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
// I returned false to isolated the problem
if let range = range { return true} else { return false}
})
if(filtered.count == 0){
searchActive = false;
} else {
searchActive = true;
}
self.tblNotes.reloadData()
}
// The big problem is here
#IBAction func refresh(sender: AnyObject) {
// I tried this one but don't works
dispatch_async(dispatch_get_main_queue()) {
self.tblNotes.reloadData()
}
// This one don't works too
self.tblNotes.reloadData()
//Neither this
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tblNotes.reloadData()
})
}
First, you need to make sure that you have set the delegate and datasource from Storyboard where your TableView exists.
Second, I think you are trying to reload data that if you don't get successfully from cloudkit because of network problem. So,tableView.reloadData() wont bring you anything until you fetch data from cloud. So, try to insert fetchNotes() inside main thread so your view will refresh.
#IBAction func refresh(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.fetchNotes()
}
}
You need to make sure the View Controller is the delegate and data source for the UITable. This can be done through the Storyboard.
Related
Referring to shrikar's work - ://shrikar.com/swift-ios-tutorial-uisearchbar-and-uisearchbardelegate/, I try to build a searchbar in table view. The tableview works fine when no adding search text. The problem is no response and error message when add search text.
I wonder something wrong. Could anybody help us? Thanks.
import UIKit
import SDWebImage
class ArticleListViewController: UITableViewController, UISearchBarDelegate{
#IBOutlet weak var searchBar: UISearchBar!
var searchActive : Bool = false
var filtered = [Article]()
var articles = [Article](){
didSet{
DispatchQueue.main.async{
self.tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
downLoadLatestArticles()
}
func downLoadLatestArticles(){
Article.downLoadItem { (articles, error) in
if let error = error {
print("fail \(error)")
return
}
if let articles = articles {
self.articles = articles
}
}
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if(searchText == " "){
searchActive = false
}else{
filtered = articles.filter ({ (article_f) -> Bool in
let tmp: String = article_f.name
let range = tmp.range(of:searchText, options: String.CompareOptions.caseInsensitive)
return range != nil
})
if(filtered.count == 0){
searchActive = false;
} else {
searchActive = true;
}
}
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(searchActive) {
return filtered.count
}
return articles.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ListTableCell", for: indexPath) as! ListTableCell
var article : Article
if(searchActive){
article = filtered[indexPath.row]
}
else{
article = articles[indexPath.row]
}
cell.nameLabel?.text = article.name
cell.locationLabel?.text = article.location
cell.photoView?.sd_setImage(with: article.image_URL)
return cell
}
}
I have made a tableview where you can select a cell, and then the viewcontroller will perform a segue to the next view, which works perfectly fine when you are not using the searchcontroller.
Then when you are using the searchcontroller, it filters the tableview as it should, and the segue is called in didSelectRowAtIndexPath, and the prepareForSegue is called. The problem then is that the view it should segue to is not presented? I can see that the code in the class connected to the view is running, so the segue is performed, it is just the view that does not follow. What am i missing
class CompanyListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
#IBOutlet weak var tableView: UITableView!
let objectMapper = AWSDynamoDBObjectMapper.defaultDynamoDBObjectMapper()
var activityIndicatorView: SWActivityIndicatorView!
var resultSearchController: UISearchController!
var allCompanies: [Company] = []
var filteredCompanies = [Company]()
override func viewDidLoad() {
super.viewDidLoad()
// set delegates
tableView.delegate = self
tableView.dataSource = self
configureSearchController()
// initialize activity indicator view
self.activityIndicatorView = SWActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
activityIndicatorView.hidesWhenStopped = true
activityIndicatorView.color = UIColor.lightGrayColor()
self.view.addSubview(activityIndicatorView)
self.activityIndicatorView.center = self.view.center
activityIndicatorView.startAnimating()
// fetch all records from backend
fetchAllRecords({(errors: [NSError]?) -> Void in if errors != nil {print(errors)}})
}
func configureSearchController() {
// Initialize and perform a minimum configuration to the search controller.
// Search Bar
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController?.searchBar.autocapitalizationType = .None
self.tableView.tableHeaderView = self.resultSearchController?.searchBar
resultSearchController?.dimsBackgroundDuringPresentation = false
self.resultSearchController?.searchResultsUpdater = self
definesPresentationContext = true
}
// search delegate method
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.filterContentForSearchText(searchController.searchBar.text!)
}
// Filter method, which filters by companyName, and reloads tableview
func filterContentForSearchText(searchText: String, scope: String = "All") {
filteredCompanies = allCompanies.filter { company in
return company._companyName!.lowercaseString.containsString(searchText.lowercaseString)
}
tableView.reloadData()
}
// fetch all records from backend
func fetchAllRecords(completionHandler: (errors: [NSError]?) -> Void) {
let scanExpression = AWSDynamoDBScanExpression()
objectMapper.scan(Company.self, expression: scanExpression) { (response: AWSDynamoDBPaginatedOutput?, error: NSError?) in
dispatch_async(dispatch_get_main_queue(), {
// if error
if let error = error {
completionHandler(errors: [error]);
}
//if success
else {
self.allCompanies = response!.items as! [Company]
self.tableView.reloadData()
self.activityIndicatorView.stopAnimating()
}
})
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if resultSearchController.active && resultSearchController.searchBar.text != "" {
return filteredCompanies.count
}
return allCompanies.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// create a new cell if needed or reuse an old one
let cell:CompanyListTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("companyCell") as! CompanyListTableViewCell
// set the text from the data model
let company:Company?
if resultSearchController.active && resultSearchController.searchBar.text != "" {
company = self.filteredCompanies[indexPath.row]
} else {
company = self.allCompanies[indexPath.row]
}
cell.titleLabel.text = company!._companyName
cell.imageview?.image = UIImage(named: "placeholder")
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("segueToProfile", sender: self)
}
// send selected company with segue to profile
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "segueToProfile"){
let indexPath = tableView.indexPathForSelectedRow
//tableView.deselectRowAtIndexPath(indexPath!, animated: true)
let selectedRow = indexPath!.row
let profileVC = segue.destinationViewController as! ProfileViewController
if resultSearchController.active{
print(filteredCompanies[selectedRow])
profileVC.company = filteredCompanies[selectedRow]
} else {
profileVC.company = allCompanies[selectedRow]
}
}
}
}
The console is saying this, but i dont know if that has anything to do with this?
2016-11-26 15:54:07.300 Lostandfound[949:2474251] Warning: Attempt to present on which is already presenting
Here is the example of TableView with SearchBar control.You should remove didSelectRowAtIndexPath method and use prepareForSegue method for Determine the selected row in TableView.Like this...
Example:
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate
{
#IBOutlet weak var SerchBar: UISearchBar!
#IBOutlet weak var TableView: UITableView!
var searchActive : Bool = false
var data = ["San Francisco","New York","San Jose","Chicago","Los Angeles","Austin","Seattle"]
var filtered:[String] = []
override func viewDidLoad()
{
super.viewDidLoad()
}
private func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if(searchActive)
{
return filtered.count
}
return data.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.TableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
if(searchActive)
{
cell.Label.text = filtered[indexPath.row]
}
else
{
cell.Label.text = data[indexPath.row]
}
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any!)
{
if let cell = sender as? TableViewCell
{
let i = TableView.indexPath(for: cell)!.row
if segue.identifier == "segue1"
{
if(searchActive)
{
let name1 = segue.destination as! SecondView
name1.str = self.filtered[i]
}
else
{
let name1 = segue.destination as! SecondView
name1.str = self.data[i]
}
}
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
{
filtered = data.filter({ (text) -> Bool in
let tmp: NSString = text as NSString
let range = tmp.range(of: searchText, options: .caseInsensitive)
return range.location != NSNotFound
})
if(filtered.count == 0)
{
searchActive = false;
}
else
{
searchActive = true;
}
self.TableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar)
{
searchActive = true;
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar)
{
searchActive = false;
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
{
searchActive = false;
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
{
searchActive = false;
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
Your SecondView class is:
import UIKit
class SecondView: UIViewController
{
#IBOutlet weak var label: UILabel!
var str:String!
override func viewDidLoad()
{
super.viewDidLoad()
self.label.text = str
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}
And your TableViewCell is:
import UIKit
class TableViewCell: UITableViewCell
{
#IBOutlet weak var Label: UILabel!
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
}
I have tried to solve this for a couple of hours. I am a newbie in IOS and want to develop a bucket list with a search bar. The codes have no problem in compilation but when i make input in the search bar, it won't show any search result. I don't know where the problem is.
btw: I have two suspects:
1. I tried to print the status, and it seems the searchBar is never active. How to open it?
2. Does it have anything to do with var missions' data
type as Mission? It is something I am not familiar with.
Please see the following codes:
import UIKit
class BucketListViewController:UITableViewController, MissionDetailsViewControllerDelegate, MissionEditViewControllerDelegate, UISearchBarDelegate{
var searchController = UISearchController(searchResultsController: nil)
#IBOutlet weak var searchBar: UISearchBar!
var searchActive : Bool = false
var filtered:[String] = []
var missions:[String] = ["Sky diving", "Live in Hawaii"]
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
self.searchDisplayController!.searchResultsTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
filtered = missions.filter({ (text) -> Bool in
let tmp: NSString = text
let range = tmp.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch)
return range.location != NSNotFound
})
if(filtered.count == 0){
searchActive = false;
} else {
searchActive = true;
}
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// dequeue the cell from our storyboard
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell")!
if(searchActive){
print("search active!")
cell.textLabel?.text = filtered[indexPath.row]
} else {
cell.textLabel?.text = missions[indexPath.row]
}
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(searchActive){
return filtered.count
} else {
return missions.count
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "AddNewMission" {
let navigationController = segue.destinationViewController as! UINavigationController
let controller = navigationController.topViewController as! MissionDetailsViewController
controller.delegate = self
}
if segue.identifier == "EditMission" {
let navigationController = segue.destinationViewController as! UINavigationController
let controller = navigationController.topViewController as! MissionEditViewController
controller.delegate = self
}
}
func missionDetailsViewController(controller: MissionDetailsViewController, didFinishAddingMission mission: String) {
dismissViewControllerAnimated(true, completion: nil)
missions.append(mission)
tableView.reloadData()}
func missionEditViewController(controller: MissionEditViewController, didFinishEditingMission mission: String, atIndexPath indexPath: Int) {
dismissViewControllerAnimated(true, completion: nil)
missions[indexPath] = mission
tableView.reloadData()
}
}
From the project you have shared there is a problem in your cellForRowAtIndexPath method.
replace
cell.textLabel?.text = filtered[indexPath.row] as? String
with
cell.textLabel?.text = filtered[indexPath.row].details
And it will work fine.
Your complete code will be:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// dequeue the cell from our storyboard
let cell = tableView.dequeueReusableCellWithIdentifier("MissionCell")!
// if the cell has a text label, set it to the model that is corresponding to the row in array
if(searchActive){
print("search active!")
cell.textLabel?.text = filtered[indexPath.row].details
} else {
cell.textLabel?.text = missions[indexPath.row].details
}
return cell
}
import UIKit
class MasterTableViewController: UITableViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate, UISearchBarDelegate, UISearchDisplayDelegate {
#IBOutlet var searchBar: UISearchBar!
// creating array for holding ojects
var noteObjects: NSMutableArray! = NSMutableArray()
var v = 0
var searchActive : Bool = false
var data:[PFObject]!
var filtered:[PFObject]!
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if v == 0 {
self.fetchAllObjectsFromLocalDataStore()
//self.fetchAllObjects()
}
}
// fetching data from local datastrore and from parse
func fetchAllObjectsFromLocalDataStore(){
let query: PFQuery = PFQuery(className: "className")
query.orderByDescending("createdAt")
query.fromLocalDatastore()
query.findObjectsInBackgroundWithBlock { (var objects, error) -> Void in
self.search()
if (error == nil) {
let temp: NSArray = objects as! NSArray
self.noteObjects = temp.mutableCopy() as! NSMutableArray
self.search()
self.tableView.reloadData()
}else {
print(error!.userInfo)
}
}
}
func fetchAllObjects(){
let query: PFQuery = PFQuery(className: "className")
query.orderByDescending("createdAt")
search()
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
PFObject.pinAllInBackground(objects, block: nil )
self.fetchAllObjectsFromLocalDataStore()
// self.tableView.reloadData()
} else {
print(error?.userInfo)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.noteObjects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MasterTableViewCell
let object : PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
cell.MasterTitleLabel?.text = object["Title"] as? String
cell.MasterTextLabel.text = object["Fstory"] as? String
cell.MasterTimeLabel.text = object["Time"] as? String
cell.MasterLocationLabel.text = object["Location"] as? String
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("openStory", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let upcoming: AddNoteTableViewController = segue.destinationViewController as! AddNoteTableViewController
if (segue.identifier == "openStory"){
let indexPath = self.tableView.indexPathForSelectedRow!
let object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
upcoming.object = object
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
#IBAction func btnReload(sender: AnyObject) {
fetchAllObjects()
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete ){
let object : PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
// the below for deleting the selected cell's object from server's database
// object.deleteInBackground()
//the below for deleting the selected cell's object from localstorage
object.unpinInBackground()
self.noteObjects.removeObjectAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
func search(searchText: String? = nil){
let query = PFQuery(className: "className")
if(searchText != nil){
query.whereKey("Title", containsString: searchText)
}
query.findObjectsInBackgroundWithBlock { (results, error) -> Void in
self.data = results! as [PFObject]
self.tableView.reloadData()
}
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
searchActive = true;
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
searchActive = false;
}
}
the above code is for retrieving parse's objects and for implementing the search bar so that i can search my objects via search function but i don't what am missing or how to it properly if anybody knows than please help me
you can try something like this using UIsearchBar
class TableViewController: UITableViewController, UISearchBarDelegate {
#IBOutlet var searchBar: UISearchBar!
var userList:NSMutableArray = NSMutableArray()
var noteObjects: NSMutableArray = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
self.fetchAllObjectsFromLocalDataStore()
}
func loadUsers(name:String){
var findUsers:PFQuery = PFUser.query()!
if !name.isEmpty{
findUsers.whereKey("username", containsString: name)
findUsers.whereKey("username", containsString: name .lowercaseString)
let user = PFUser.currentUser()
if let user = PFUser.currentUser() {
findUsers.whereKey("institute", equalTo: user["institute"])
}
}
findUsers.fromLocalDatastore()
findUsers.findObjectsInBackgroundWithBlock { ( objects, error) -> Void in
if (error == nil) {
self.userList = NSMutableArray(array: objects!)
self.tableView.reloadData()
}else {
print(error!.userInfo)
}
}}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
loadUsers(searchText)
self.searchBar.setShowsCancelButton(true, animated: true)
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
loadUsers("")
self.searchBar.setShowsCancelButton(false, animated: true)
self.searchBar.endEditing(true)
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if searchBar.text == "" {
return noteObjects.count
} else {
return userList.count }
//self.noteObjects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UsersTableViewCell
if searchBar.text == "" {
let object : PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
let photo: PFFile = object["photo"] as! PFFile
photo.getDataInBackgroundWithBlock{
(imageData:NSData?, error:NSError?)-> Void in
if (error == nil){
let image:UIImage = UIImage(data: imageData!)!
cell.imgViewUser.image = image
}
else if error != nil{
print("error")
}
}
cell.lblUserInterest.text = object["interest"] as? String
//cell.imgViewUser.image = object["photo"] as? PFFile
cell.lblUsername.text = object["username"] as? String
return cell
} else {
let object : PFObject = self.userList.objectAtIndex(indexPath.row) as! PFObject
let photo: PFFile = object["photo"] as! PFFile
photo.getDataInBackgroundWithBlock{
(imageData:NSData?, error:NSError?)-> Void in
if (error == nil){
let image:UIImage = UIImage(data: imageData!)!
cell.imgViewUser.image = image
}
else if error != nil{
print("error")
}}
cell.lblUserInterest.text = object["interest"] as? String
//cell.imgViewUser.image = object["photo"] as? PFFile
cell.lblUsername.text = object["username"] as? String
return cell
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var object :AnyObject?
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if (editingStyle == UITableViewCellEditingStyle.Delete ){
}
My UITableView can't scroll, I tried everything I could have possibly done.
Getting a little desperate here.
the tableview implementation here is actually pretty simple, but can't make it work...
Will post the code below:
class RepresentableViewController: DynamicBackgroundViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
// MARK: - Properties
var representables: Array<TableCellRepresentable>? {
didSet{
if !self.isAnimatingTable {
self.tableView.reloadData()
}
if self.representables != nil {
self.stopAnimatingIndicator()
}
else {
self.startAnimatingIndicator()
}
}
}
var cellReuseId: String {
return RepresentableTableViewCell.reuseId
}
var isAnimatingTable: Bool = false
private(set) var isSearching: Bool = false
private(set) var searchResults: Array<TableCellRepresentable>? {
didSet {
self.tableView.reloadData()
}
}
var searchResultsCount: Int {
return self.searchResults != nil ? self.searchResults!.count : 0
}
var activeRepresentables: Array<TableCellRepresentable>? {
return self.isSearching ? self.searchResults : self.representables
}
var activeRepresentablesCount: Int {
return self.activeRepresentables != nil ? self.activeRepresentables!.count : 0
}
private(set) var lastSelectedIndex: NSIndexPath?
// MARK: Outlets
#IBOutlet weak var tableView: UITableView!
weak var activityIndicator: UIActivityIndicatorView?
#IBOutlet weak var searchBar: UISearchBar!
// MARK: - Methods
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.setupCell()
self.startAnimatingIndicator()
}
private func setupCell() {
let nib = UINib(nibName: "RepresentableTableViewCell", bundle: nil)
self.tableView.registerNib(nib, forCellReuseIdentifier: RepresentableTableViewCell.reuseId)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if self.representables == nil {
self.postRequestRepresentablesNotification()
}
}
private func postRequestRepresentablesNotification() {
NSNotificationCenter.defaultCenter().postNotificationName(RepresentableViewController.requestRepresentablesNotificationName, object: self, userInfo: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
self.clearRepresentablesIfNotVisible()
}
func insertToTable(item: TableCellRepresentable) {
self.isAnimatingTable = true
if self.representables == nil {
self.self.representables = []
}
self.representables!.append(item)
self.tableView.reloadData()
self.isAnimatingTable = false
}
func removeFromTable(atIndexPath index: NSIndexPath) {
self.isAnimatingTable = true
self.representables!.removeAtIndex(index.row)
self.tableView.deleteRowsAtIndexPaths([index], withRowAnimation: .Automatic)
self.isAnimatingTable = false
}
private func clearRepresentablesIfNotVisible() {
if !self.isViewLoaded() && !(self.view.window != nil) {
self.representables = nil
}
}
private func startAnimatingIndicator() {
if self.activityIndicator == nil {
let indicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
indicator.hidesWhenStopped = true
indicator.color = RGBColor(r: 35, g: 131, b: 250, alpha: 1.0)
indicator.center = self.view.center
self.activityIndicator = indicator
self.view.addSubview(indicator)
self.shouldBringToFront?.append(indicator)
indicator.startAnimating()
}
}
private func stopAnimatingIndicator() {
if let indicator = self.activityIndicator {
if let shouldBring = self.shouldBringToFront, index = find(shouldBring, indicator) {
self.shouldBringToFront!.removeAtIndex(index)
}
indicator.stopAnimating()
indicator.removeFromSuperview()
self.activityIndicator = nil
}
}
/*
// 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.
}*/
// MARK: - Protocols
// MARK: UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.activeRepresentables != nil ? self.activeRepresentables!.count : 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(self.cellReuseId, forIndexPath: indexPath) as! RepresentableTableViewCell
cell.object = self.activeRepresentables![indexPath.row]
return cell
}
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.lastSelectedIndex = indexPath
NSNotificationCenter.defaultCenter().postNotificationName(RepresentableViewController.didSelectARepresentableNotificationName, object: self, userInfo: [RepresentableViewController.representableKey: self.activeRepresentables![indexPath.row]])
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 60.0
}
// MARK: SearchBarDelegate
private func filterProducts(searchText: String) {
if searchText != "" {
self.searchResults = self.representables?.filter({ (cur: TableCellRepresentable) -> Bool in
let lowerCase: String = searchText.lowercaseString
let titleMatch: Bool = cur.title.lowercaseString.rangeOfString(lowerCase) != nil
let subtitleMatch: Bool = cur.subtitle.lowercaseString.rangeOfString(lowerCase) != nil
let detailMatch: Bool = cur.detail?.lowercaseString.rangeOfString(lowerCase) != nil
return titleMatch || subtitleMatch || detailMatch
})
}
else {
self.searchResults = self.representables
}
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
self.filterProducts(searchText)
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
self.isSearching = false
self.searchBar.text = ""
self.searchResults = nil
}
func searchBarTextDidBeginEditing(searchBar: UISearchBar) {
self.isSearching = true
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
searchBar.endEditing(true)
}
// MARK: - Static Properties and Methods
class var didSelectARepresentableNotificationName: String {
return "RepresentableViewController-didSelectARepresentableNotification"
}
class var requestRepresentablesNotificationName: String {
return "RepresentableViewController-RequestRepresentablesNotification"
}
class var representableKey: String {
return "Representable"
}
}
can't figure it out, can someone help me?
thanks.
EDITED
This issue is being caused by a PanGesture at the UITableViewCells, how can I solve this? I still need this pan gesture to move content at the cell.
Fixed with this piece of code at the UITableViewCell
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer
{
let translation = panGestureRecognizer.translationInView(superview!)
if fabs(translation.x) > fabs(translation.y)
{
return true
}
return false
}
return false
}