creating searchviewcontroller in parse.com table - swift

I have created a basic layout for searchViewcontroller in which I enter a data that I want to search inside parse table as a query and search is completed and the cell appears. I have tried searching but various errors are appearing. I have no clue to do this.
I'm trying to create an independent ViewController for search.
class SearchViewController: PFQueryTableViewController, UISearchBarDelegate {
// Table search bar
#IBOutlet weak var searchBar: UISearchBar!
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
// Configure the PFQueryTableView
self.parseClassName = "Countries"
self.textKey = "nameEnglish"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell!
if cell == nil {
cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CustomCell")
}
// Extract values from the PFObject to display in the table cell
if let nameEnglish = object?["nameEnglish"] as? String {
cell.customNameEnglish.text = nameEnglish
}
if let capital = object?["capital"] as? String {
cell.customCapital.text = capital
}
// Display flag image
var initialThumbnail = UIImage(named: "question")
cell.customFlag.image = initialThumbnail
if let thumbnail = object?["flag"] as? PFFile {
cell.customFlag.file = thumbnail
cell.customFlag.loadInBackground()
}
return cell
}
// 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].
var detailScene = segue.destinationViewController as! DetailViewController
// Pass the selected object to the destination view controller.
if let indexPath = self.tableView.indexPathForSelectedRow! {
let row = Int(indexPath.row)
detailScene.currentObject = objects?[row] as? PFObject
}
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
// Start the query object
let query = PFQuery(className: "Countries")
// Add a where clause if there is a search criteria
if searchBar.text != "" {
query.whereKey("searchText", containsString: searchBar.text!.lowercaseString)
}
// Order the results
query.orderByAscending("nameEnglish")
// Return the qwuery object
return query
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
// Dismiss the keyboard
searchBar.resignFirstResponder()
// Force reload of table data
self.loadObjects()
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// Dismiss the keyboard
searchBar.resignFirstResponder()
// Force reload of table data
self.loadObjects()
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
// Clear any search criteria
searchBar.text = ""
// Dismiss the keyboard
searchBar.resignFirstResponder()
// Force reload of table data
self.loadObjects()
}
override func viewDidAppear(animated: Bool) {
// Refresh the table to ensure any data changes are displayed
tableView.reloadData()
// Delegate the search bar to this table view class
searchBar.delegate = self
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
let objectToDelete = objects?[indexPath.row] as! PFObject
objectToDelete.deleteInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// Force a reload of the table - fetching fresh data from Parse platform
self.loadObjects()
} else {
// There was a problem, check error.description
}
}
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
}
If any clue is provided I'll be grateful.
This code is in reference with Bizzi-Body Parse Tutorial .

Related

Master View Cell Labels Blank When Starting In Landscape

The cell labels are blank in the master view of a default Master Detail View when starting in landscape orientation of an iPad 2 simulation. If I reload the master view in its controller's viewWillAppear function, everything is as it should be only after turning into portrait and back into landscape. I can't figure out what I am missing despite several hours of searching for help and trying to tableView.reloadData() in various places.
This is a UIDocument app and I have not yet implemented iCloud, although I have the code ready to go. Thus far, it just needs to fetch the local document URLs, file names, and display names (?) into an array from which the master view cell labels are created.
Here is most of the MasterViewController class:
class MasterViewController: UITableViewController, DetailViewControllerDelegate {
private var detailViewController: DetailViewController? = nil
// var objects = [AnyObject]()
internal lazy var notesController = NotesController()
internal override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("viewDidLoad")
// determine preferred storage location for documents
notesController.documentsInCloud = false
// discover documents
notesController.discoverDocuments()
// tableView.reloadData()
navigationItem.leftBarButtonItem = editButtonItem()
if let split = splitViewController {
let controllers = split.viewControllers
detailViewController =
(controllers[controllers.count-1] as! UINavigationController
).topViewController as? DetailViewController
detailViewController!.delegate = self
}
}
internal override func viewWillAppear(animated: Bool) {
print("viewWillAppear")
clearsSelectionOnViewWillAppear = splitViewController!.collapsed
super.viewWillAppear(animated)
tableView.reloadData()
}
// MARK: - Segues
internal override func prepareForSegue(segue: UIStoryboardSegue,
sender: AnyObject?) {
print("prepareForSegue")
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let controller =
(segue.destinationViewController as! UINavigationController
).topViewController as! DetailViewController
let URL = notesController.notes.array[indexPath.row].URL
controller.delegate = self
controller.detailItem = Note(fileURL: URL)
controller.selectedItemIndex = indexPath.row
controller.navigationItem.leftBarButtonItem =
splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
splitViewController?.toggleMasterView()
} else {
let controller =
(segue.destinationViewController as! UINavigationController
).topViewController as! DetailViewController
controller.delegate = self
controller.configureView()
controller.navigationItem.leftBarButtonItem =
splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
internal override func numberOfSectionsInTableView(tableView: UITableView)
-> Int {
return 1
}
internal override func tableView(tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return notesController.notes.array.count
}
internal override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
print("cellForRowAtIndexPath")
let cell =
tableView.dequeueReusableCellWithIdentifier(
"Cell",
forIndexPath: indexPath)
let fileRepresentation = notesController.notes.array[indexPath.row]
if let title = fileRepresentation.displayName {
cell.textLabel?.text = title
} else {
cell.textLabel?.text = fileRepresentation.fileName
}
return cell
}
internal override func tableView(tableView: UITableView,
canEditRowAtIndexPath indexPath: NSIndexPath)
-> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
internal override func tableView(
tableView: UITableView,
commitEditingStyle
editingStyle: UITableViewCellEditingStyle,
forRowAtIndexPath indexPath: NSIndexPath) {
print("commitEditingStyle")
if editingStyle == .Delete {
let fileManager = NSFileManager.defaultManager()
let fileRepresentation = notesController.notes.array[indexPath.row]
let URL = fileRepresentation.URL
do {
try fileManager.removeItemAtURL(URL);
notesController.notes.delete(fileRepresentation);
tableView.deleteRowsAtIndexPaths([indexPath],
withRowAnimation: .Fade);
performSegueWithIdentifier("showDetail", sender: self)
} catch let error as NSError {
print(error.localizedDescription)
}
} // else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into
// the array, and add a new row to the table view.
// }
}
// MARK: - Delegate Functions
internal func reloadMasterViewData(sender: DetailViewController) {
tableView.reloadData()
}
}
For those who, like me, are new to the default Xcode Master-Detail view setup, yes, the Master view does start in landscape orientation populated with whatever labels it is set up to display. My problem was that the array I am using to populate the labels is constructed asynchronously from the views, and that array wasn't ready when the view loaded. I fixed this by setting up an NSNotification that told my master view when the array was finished discovering my UIDocuments. Andrew Bancroft's blog (https://www.andrewcbancroft.com/2014/10/08/fundamentals-of-nsnotificationcenter-in-swift/) was very helpful in that regard.

XML Parser not organizing data into tables

I'm creating an app that involves parsing XML files of a website and putting the information into a table view. Currently the storyboard stands as a tabbed view application with 4 table view controllers connecting to it. I have developed the accompanying class file and set one of the controllers to run off of it. However, the class, while it gives no error, is not returning and creating any tables. The screen is blank just as before there were any swift files. The file is shown below
import UIKit
class Newspage: UITableViewController, NSXMLParserDelegate
{
var parser: NSXMLParser = NSXMLParser()
var info: [newsarticle] = []
var postTitle: String = String()
var postDesc: String = String()
var eName: String = String()
override func viewDidLoad() {
super.viewDidLoad()
super.viewDidLoad()
let url:NSURL = NSURL(string: "http://brrsd.k12.nj.us/rss/News.xml")!
parser = NSXMLParser(contentsOfURL: url)!
parser.delegate = self
parser.parse()
// 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 didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI namespaceURI: String?, qualifiedName qualifiedName: String?, attributes attributeDict: [String : String])
{
eName = elementName
if elementName == "item" {
postTitle = String()
postDesc = String()
}
}
func parser(parser: NSXMLParser!, foundCharacters string: String!) {
let data = string.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
if (!data.isEmpty) {
if eName == "title" {
postTitle += data
} else if eName == "description" {
postDesc += data
}
}
}
func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!) {
if elementName == "item" {
let newsart: newsarticle = newsarticle()
newsart.title = postTitle
newsart.description = postDesc
info.append(newsart)
}
}
// 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 info.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let news: newsarticle = info[indexPath.row]
cell.textLabel!.text = news.title
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// 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.
}
*/
}
Where is the error?
Note: the newsarticle class just contains 2 variables, title and description.
I think your problem is you do not ask your table to refresh itself when you're done parsing the XML.
you need to tell the table to refresh itself when you want it to, by using tableView.reloadData().
You can do this at the end of each element or when the parse is ended by calling reloaData in the delegate function parserDidEndDocument(_ parser: NSXMLParser).
Also, you should not need to call two times super.viewDidLoad() in viewDidLoad.
I'd be you I also would separate the viewController class and the parser delegate in two independent classes.
your cellForRowAtIndexPath is also bothering me:
I don't think you need the second argument (indexPath) to get the cell. You don't want to get the cell a IndexPath but to return a cell to put at IndexPath.
tableView.dequeueReusableCellWithIdentifier("Cell") should get you a cell with the 'Cell' identifier that is available for reuse. For exemple when you scroll down the cell on the top that are not displayed anymore get reused for display on the bottom.
here is how I would implement this function
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell
if let reusedCell = tableView.dequeueReusableCellWithIdentifier("Cell") {
cell = reusedCell
} else {
cell = UITableViewCell(style: .Default, reuseIdentifier: "Cell")
}
if let label = cell.textLabel {
let news = info[indexPath.row]
label.text = news.title
}
return cell
}

What identifier should I add for this optional?

I want to add this optional
var mapRegion : MKCoordinateRegion
It gives me an error that I need an identifier next to class:
class TableViewController: UITableViewController, NSFetchedResultsControllerDelegate,
What's that identifier?
The file looks like this:
import UIKit
import CoreData
import MapKit
class TableViewController: UITableViewController, NSFetchedResultsControllerDelegate, {
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
var frc : NSFetchedResultsController = NSFetchedResultsController()
var mapRegion : MKCoordinateRegion
func fetchRequest() -> NSFetchRequest {
let fetchRequest = NSFetchRequest(entityName: "Item")
let sortDescriptor = NSSortDescriptor(key: "name",
ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
return fetchRequest
}
func getFRC() -> NSFetchedResultsController {
frc = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
return frc
}
override func viewDidLoad() {
super.viewDidLoad()
frc = getFRC()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("Failed to perform initial fetch.")
return
}
self.tableView.rowHeight = 480
self.tableView.backgroundView = UIImageView( image: UIImage(named: "flatgrey2"))
self .tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
frc = getFRC()
frc.delegate = self
do {
try frc.performFetch()
} catch {
print("Failed to perform initial fetch.")
return
}
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
let numberOfSections = frc.sections?.count
return numberOfSections!
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
let numberofRowsInSection = frc.sections?[section].numberOfObjects
return numberofRowsInSection!
//return 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.clearColor()
} else {
cell.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.2)
cell.textLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
cell.detailTextLabel?.backgroundColor = UIColor.whiteColor().colorWithAlphaComponent(0.0)
}
// Configure the cell...
cell.textLabel?.textColor = UIColor.darkGrayColor()
cell.detailTextLabel?.textColor = UIColor.darkGrayColor()
let item = frc.objectAtIndexPath(indexPath) as! Item
cell.textLabel?.text = item.name
cell.imageView?.image = UIImage(data: (item.image)!)
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
let managedObject : NSManagedObject = frc.objectAtIndexPath(indexPath) as! NSManagedObject
moc.deleteObject(managedObject)
do {
try moc.save()
} catch {
print ("Failed to save.")
return
}
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
tableView.reloadData()
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
// 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.
if segue.identifier == "edit" {
let cell = sender as! UITableViewCell
let indexPath = tableView.indexPathForCell(cell)
let itemController : AddEditVC = segue.destinationViewController as! AddEditVC
let item : Item = frc.objectAtIndexPath(indexPath!) as! Item
itemController.item = item
}
}
}
The variable should have a value when it is declared otherwise it will show this error. Assign a value to your variable var mapRegion : MKCoordinateRegion. If the value is given at a later stage i.e., if it depends on any calculations then make it an optional like this var mapRegion : MKCoordinateRegion? But you have to unwrap the variable whenever you want to use mapRegion value by placing an exclamation mark at the end of the variable name.
You have declared var mapRegion : MKCoordinateRegion but don't have any initializers or default value. To make it an optional, just add ? to it, so declare:
var mapRegion : MKCoordinateRegion?

Swift Parse Searchbar isnt working

I have a parse class of country names, and have a swift tableview controller that pulls the list of countries from Parse and allows you to search for country name. For example:
Canada
China
Iraq
etc
If I search for "Canada" nothing comes up, but if I search "anada" I get results. For some reason it is ignoring the first character, any idea why this is happening?
import UIKit
class TableViewController: PFQueryTableViewController, UISearchBarDelegate {
// Sign the user out
#IBAction func signOut(sender: AnyObject) {
PFUser.logOut()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("SignUpInViewController") as! UIViewController
self.presentViewController(vc, animated: true, completion: nil)
}
#IBAction func add(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.performSegueWithIdentifier("TableViewToDetailView", sender: self)
}
}
// Table search bar
#IBOutlet weak var searchBar: UISearchBar!
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Configure the PFQueryTableView
self.parseClassName = "Countries"
self.textKey = "nameEnglish"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as! CustomTableViewCell!
if cell == nil {
cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CustomCell")
}
// Extract values from the PFObject to display in the table cell
if let nameEnglish = object?["nameEnglish"] as? String {
cell.customNameEnglish.text = nameEnglish
}
if let capital = object?["capital"] as? String {
cell.customCapital.text = capital
}
// Display flag image
var initialThumbnail = UIImage(named: "question")
cell.customFlag.image = initialThumbnail
if let thumbnail = object?["flag"] as? PFFile {
cell.customFlag.file = thumbnail
cell.customFlag.loadInBackground()
}
return cell
}
// 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].
var detailScene = segue.destinationViewController as! DetailViewController
// Pass the selected object to the destination view controller.
if let indexPath = self.tableView.indexPathForSelectedRow() {
let row = Int(indexPath.row)
detailScene.currentObject = objects?[row] as? PFObject
}
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
// Start the query object
var query = PFQuery(className: "Countries")
// Add a where clause if there is a search criteria
if searchBar.text != "" {
query.whereKey("nameEnglish", containsString: searchBar.text.lowercaseString)
}
// Order the results
query.orderByAscending("nameEnglish")
// Return the qwuery object
return query
}
func searchBarTextDidEndEditing(searchBar: UISearchBar) {
// Dismiss the keyboard
searchBar.resignFirstResponder()
// Force reload of table data
self.loadObjects()
}
func searchBarSearchButtonClicked(searchBar: UISearchBar) {
// Dismiss the keyboard
searchBar.resignFirstResponder()
// Force reload of table data
self.loadObjects()
}
func searchBarCancelButtonClicked(searchBar: UISearchBar) {
// Clear any search criteria
searchBar.text = ""
// Dismiss the keyboard
searchBar.resignFirstResponder()
// Force reload of table data
self.loadObjects()
}
override func viewDidAppear(animated: Bool) {
// Refresh the table to ensure any data changes are displayed
tableView.reloadData()
// Delegate the search bar to this table view class
searchBar.delegate = self
}
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
let objectToDelete = objects?[indexPath.row] as! PFObject
objectToDelete.deleteInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// Force a reload of the table - fetching fresh data from Parse platform
self.loadObjects()
} else {
// There was a problem, check error.description
}
}
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
}
Just realized the query.wherekey function is not case sensitive, fixed the problem

Saving values to UserDefults from Textfield in TableView : Swift

I am trying to save values from a tableview that users will input into the textfield, the problem is that I do not know how to access the new value and replace the string in the array.
So basically the app will display fields based on what the user wants and then the user can edit those values to their liking. Once the textfields have been updated, the values are stored again in userdefaults so that the next time the tableview is opened, the update values will appear.
This is what the tableviewcontroller looks like at the moment:
//
// Asset1TableViewController.swift
// Net Calc 2
//
// Created by Joshua Peterson on 30/06/2015.
// Copyright © 2015 Peterson Productions. All rights reserved.
//
import UIKit
class Asset1TableViewController: UITableViewController {
var dataHolder: [NSString] = [NSString]()
var finalDataHolder: [NSString] = [NSString]()
var acountAmountHolder: [NSString] = [NSString]()
var finalAccountAmountHolder: [NSString] = [NSString]()
let defaults = NSUserDefaults.standardUserDefaults()
let key1 = "keySave1"
let key2 = "keySave2"
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let storedTitleValue : NSArray? = self.defaults.arrayForKey(self.key1) {
if storedTitleValue == nil {
self.dataHolder = [NSString]()
} else {
let readArray : [NSString] = storedTitleValue as! [NSString]
for element in readArray {
self.dataHolder.append(element as String)
self.finalDataHolder.append(element as String)
}
}
}
if let storedAmountValue : NSArray? = self.defaults.arrayForKey(self.key2) {
if storedAmountValue == nil {
self.acountAmountHolder = [NSString]()
} else {
let readArray : [NSString] = storedAmountValue as! [NSString]
for element in readArray {
self.acountAmountHolder.append(element as String)
self.finalAccountAmountHolder.append(element as String)
}
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataHolder.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell
cell.AccountLabel.text = dataHolder[indexPath.row] as String
cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
return cell
}
#IBAction func addButtonTapped(sender: AnyObject) {
let newAccounTitle = "Account Name"
let newAccountAmount = "R0.00"
dataHolder.append(newAccounTitle)
acountAmountHolder.append(newAccountAmount)
tableView.reloadData()
}
#IBAction func saveButtonTapped(sender: AnyObject) {
// Save
defaults.setObject(dataHolder as Array, forKey: key1)
defaults.setObject(acountAmountHolder as Array, forKey: key2)
defaults.synchronize()
}
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 {
dataHolder.removeAtIndex(indexPath.row)
acountAmountHolder.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
}
I have tried to apply some of the code that i have found on the website but the problem is that I cant actually connect to the cell.
Ok so after some research I have added a few functions to the custom cell class so that it looks like this:
import UIKit
protocol TableViewCellDelegate {
// Indicates that the edit process has begun for the given cell
func cellDidBeginEditing(editingCell: Account1Cell)
// Indicates that the edit process has committed for the given cell
func cellDidEndEditing(editingCell: Account1Cell)
}
class Account1Cell: UITableViewCell, UITextFieldDelegate {
#IBOutlet weak var AccountLabel: UITextField!
#IBOutlet weak var AccountAmount: UITextField!
var delegate: TableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
AccountLabel.delegate = self
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
// close the keyboard on Enter
AccountLabel.resignFirstResponder()
return false
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
// disable editing of completed to-do items
return true
}
func textFieldDidEndEditing(textField: UITextField) {
if AccountLabel != nil {
let newAccountLabel = AccountLabel.text
print(newAccountLabel) // Prints out the new edited text!!!!!!!!
}
if delegate != nil {
delegate!.cellDidEndEditing(self)
}
}
func textFieldDidBeginEditing(textField: UITextField) {
if delegate != nil {
delegate!.cellDidBeginEditing(self)
}
}
}
Now what I need to do is either replace that value in the Array at the index (which i think is going to be rather complicated) or create some sort of loop that will read ALL the values and simply store all of the new values to UserDefaults. Maybe there is something else?
Any help is appreciated!!
You should have a protocol in your custom cell like this, and call it when the text field in the cell gets modified:
protocol TableViewCellToTVController{
func cellCurrentlyEditing(editingCell: Account1Cell) -> Int
}
....
func textFieldShouldReturn(textField: UITextField) -> Bool {
// close the keyboard on Enter
let myrow: Int? = self.delegate_special?.cellCurrentlyEditing(self)
println("cellCurrentlyEditing got called from delegate" , myrow)
AccountLabel.resignFirstResponder()
return false
}
implement this function in tableviewcontroller to know which row got selected :
func cellCurrentlyEditing(editingCell: Account1Cell) -> Int{
var rowNum = 0
let indexP: NSIndexPath = tableView.indexPathForCell(editingCell)!
rowNum = indexP.row
return rowNum
}
also make your tableviewcontroller the delegate for each cell:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell
cell.AccountLabel.text = dataHolder[indexPath.row] as String
cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
cell.delegate_special = self;
return cell
}