Swift Ios Parse SearchBar Complication - ios

I was recently following a tutorial which shows an early version of Swift being used to create a table of users from Parse with a search function. The following code has allowed me to display all users in a table as I would like, but does not update the table once search text has been put in the search bar. (There are two user arrays because I am relatively new to programming and was following two different tutorials to help make this table). Any help is greatly appreciated!!
var userArray: [String] = []
var userList:NSMutableArray = NSMutableArray()
#IBOutlet weak var searchBar: UISearchBar! = UISearchBar()
func loadUsers(name:String){
var findUsers:PFQuery = PFUser.query()
if !name.isEmpty {
findUsers.whereKey("name", containsString: name)
}
findUsers.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!) -> Void in
self.userList = NSMutableArray(array: objects)
self.tableView.reloadData()
}
}
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
loadUsers(searchText)
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
loadUsers("")
}
override func viewDidLoad() {
super.viewDidLoad()
loadUsers("")
searchBar.delegate = self
self.navigationItem.hidesBackButton = true
var query = PFUser.query()
query.whereKey("username", notEqualTo: PFUser.currentUser().username)
var users = query.findObjects()
for user in users {
userArray.append(user["name"] as String)
println(userArray)
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return userArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
if userArray.count >= 1 {
cell.textLabel?.text = userArray[indexPath.row]
}
return cell
}

You will have to create a new array which holds the data which hold's the results in the searchBar.
Besides, it's better to create a bool variable to handle what's the data showing in the screen (true for search results, false for loadUsers).
This article can help you: http://shrikar.com/blog/2015/02/16/swift-ios-tutorial-uisearchbar-and-uisearchbardelegate

Related

How can I connect the SearchBar to a different dataSource?

I have a View that has a searchBar and a corresponding TableView below it and I have it working correctly. My question is; is it possible to hook up the SearchBar to a different TableView ? I am new to swift and iOS development and can not find a way to get it done . This image will help illustrate . AS you can see I have a Search Table View Controller and it is working correctly with the Search Bar. What I would like to do now is connect that SearchBar to the Second TableView instead . I would like to do that because eventually i'll have a TableView that will not be connected to the SearchBar, however when a user clicks on the SearchBar a new TableView will cover the original TableView . Below I will show my code for the working TableView, again I would like to connect the SearchBar to the Second
class SearchTableViewController: UITableViewController,UISearchBarDelegate {
#IBOutlet weak var searchBar: UISearchBar!
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
struct ApplicationData {
var items: [String]
var filteredItems: [String] = []
init() {
items = ["John","Sam","Oliver"]
filterData(search: "")
}
mutating func filterData(search: String)
{
if search.characters.count>0 {
filteredItems = items.filter({ (item) in
let value1 = item.lowercased()
let value2 = search.lowercased()
let valid = value1.hasPrefix(value2)
return valid
})
}
filteredItems.sort(by: { (value1,value2) in value1 < value2 })
}
}
var AppData = ApplicationData()
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String){
if let text = searchBar.text {
let search = text.trimmingCharacters(in: .whitespaces)
AppData.filterData(search: search)
tableView.reloadData()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return AppData.filteredItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ZipSearch", for: indexPath)
let data = AppData.filteredItems[indexPath.row]
cell.textLabel?.text = data
return cell
}
}
I am thinking that maybe the tableView.reloadData() piece of code is defaulting to the original tableView but any help would be greatly appreciated .

Swift - Search Bar Initial Load

I am attempting to have a search functionality within my app. The search would basically search for user input in the Parse class in the backend.
So far the code below works very well for my case except that as soon as the view loads (prior to starting typing anything) it loads all the usernames in the backend in the table rows. As the user types letters, it filters. I want to have all the same functionality, except for showing all users in table rows as soon as view loads. How can this be achieved?
class FriendByUsernameTableViewController: UITableViewController, UISearchBarDelegate, UISearchDisplayDelegate {
var friendObject = FriendClass()
#IBOutlet weak var searchBar: UISearchBar!
var searchActive : Bool = false
var data:[PFObject]!
var filtered:[PFObject]!
override func viewDidLoad() {
super.viewDidLoad()
self.searchBar.delegate = self
search()
}
func search(searchText: String? = nil){
let query = PFQuery(className: "_User")
if(searchText != nil){
query.whereKey("appUsername", containsString: searchText)
}
query.findObjectsInBackgroundWithBlock { (results, error) -> Void in
self.data = results as? [PFObject]!
self.tableView.reloadData()
}
}
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 {
if(self.data != nil){
return self.data.count
}
return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
let obj = self.data[indexPath.row]
cell.textLabel!.text = obj["appUsername"] as? String
return cell
}
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) {
search(searchText)
}
}
The code is based on this tutorial: http://shrikar.com/parse-search-in-ios-8-with-swift/
try adding
if searchText!.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()) != "" {
query.findObjectsInBackgroundWithBlock()
}
in your search function along with the block of course.
This way you won't query if you click on the search bar or if you tap a bunch of spaces.
Also, if you don't want users to be displayed upon load, don't call search() in your viewDidLoad()

Populating user image and text posts, compiles and runs but cells are empty. Parse Swift

I am trying to populate my feed of images and text users post. The code compiles and runs but I get empty cells.
var titles = [String]()
var locations = [String]()
var dates = [String]()
var imageFiles = [PFFile]()
override func viewDidLoad() {
super.viewDidLoad()
var privacySettingQuery = PFQuery(className: "Posts")
privacySettingQuery.whereKey("privacy", equalTo: true)
privacySettingQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.titles.append(object["name"] as! String)
self.dates.append(object["dateTime"] as! String)
self.locations.append(object["location"] as! String)
self.imageFiles.append(object["imageFile"] as! PFFile)
}
}
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return titles.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell {
let postsCell = tableView.dequeueReusableCellWithIdentifier("PostsCell", forIndexPath: indexPath) as! PostsCell
postsCell.postImage.image = UIImage(named: "Post-Image- Placeholder-1.png")
postsCell.postTitle.text = titles[indexPath.row]
postsCell.postLocation.text = locations[indexPath.row]
postsCell.postDate.text = dates[indexPath.row]
return postsCell
}
Any help would be appreciated. Also is there a better way to do this other than using arrays?
To solve the empty issue.You need call tableView.reloadData() after you got the objects.
Model class like
class Post: NSObject {
var title: String
var location: String
var date: NSDate
var imageFile: PFFile
}
And in viewController use
var posts: [Post]?
instead of the 4 arrays
When this code is being called
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return titles.count
}
The value for titles.count is still 0. After you finish fetching the info from parse and you have values for the arrays you must reload the UITableView. To do this make an outlet for the UITableView and call it tableView. Then call this code tableView.reloadData()
Hope this helps!!

Extra white space above table view swift Xcode

I had an error with Xcode where I needed to fix the size class. After I did that, I went back to one of my table views, and it added white space above the first prototype cells in the tableview. How can I get rid of that space? I added this picture below to better describe what I mean.
https://www.dropbox.com/s/7ebxipb0r2jakav/TableViewProblem.png?dl=0
#IBOutlet var schoolTable: UITableView!
var namesArray = [String]()
var locationsArray = [String]()
var currentUser = PFUser.currentUser()
var theSchoolName: String = "None Selected"
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
namesArray.removeAll(keepCapacity: false)
locationsArray.removeAll(keepCapacity: false)
var query = PFQuery(className: "Schools")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = query.findObjects() as? [PFObject] {
for object in objects {
self.namesArray.append(object.valueForKey("schoolName") as! String)
self.locationsArray.append(object.valueForKey("schoolLocation") as! String)
self.schoolTable.reloadData()
}
}
} else {
println("Oops, it didn't work...")
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.namesArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:ChangeSchoolListTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! ChangeSchoolListTableViewCell
if namesArray.count > 0 {
cell.nameLabel.text = namesArray[indexPath.row]
cell.locationLabel.text = locationsArray[indexPath.row]
}
return cell
}
I've seen this a lot with Xcode storyboards.
The solution is to move the UITableView so its not the first view on the screen.
Space at the top of UITableViews

Error displaying a prototype cell and its content

I'm doing Rob's UDEMY iOS8 Swift course and so far so good.
I use a Tab Bar Controller to separate tabs: Profile, Ask, Browse etc...
In the 'Ask' tab, I input a text and it is successfully uploaded to Parse and I want that text to be displayed in the 'Browse' tab. The Browse tab is a Table View with prototype cell, I added labels there to display username and the text.
My problem is that it doesn't display the text nor the username from Parse. Here is the code:
import UIKit
import Parse
class browseViewController: UITableViewController{
var postedQuestion = [String]()
var usernames = [String]()
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className:"Post")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error != nil {
if let objects = objects as? [PFObject] {
for object in objects {
self.postedQuestion.append(object["postedQuestion"] as! String)
self.usernames.append(object["username"] as! String)
self.tableView.reloadData()
}
}
} else {
println(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usernames.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 227
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var myCell:cell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! cell
myCell.postedQuestion.text = postedQuestion[indexPath.row]
myCell.username.text = usernames[indexPath.row]
myCell.sizeToFit()
return myCell
}
}
Error message:
nil
I can see it is loading the data (from Parse) but then it just gives me that error message. It doesn't crash tho.
Thanks!

Resources