Display data from class subcategory in tableview Parse - ios

I have two classes in the Parse backend.
Classes:
- Category->Kategorien (image, name)
- Subcategory->Unterkategorien (image, name, category(pointer))
I want a TableView for each class. It should be like, I choose a Category in the first TableView and come to the next TableView with all Subcategories of the chosen Category.
With the following code I show the data from the Category class:
import UIKit
class KategorienTableViewController: PFQueryTableViewController {
// 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 = "Kategorien"
self.textKey = "name"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "Kategorien")
query.orderByAscending("name")
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("KategorienTableCell") as KategorienTableCell!
if cell == nil {
cell = KategorienTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "KategorienTableCell")
}
// Extract values from the PFObject to display in the table cell
cell.name.text = object["name"] as String!
var thumbnail = object["bild"] as PFFile
var initialThumbnail = UIImage(named: "Kategorien")
cell.bild.image = initialThumbnail
cell.bild.file = thumbnail
cell.bild.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 unterkategorienScene = segue.destinationViewController as UnterkategorienTableViewController
// Pass the selected object to the unterkategorien view controller.
if let indexPath = self.tableView.indexPathForSelectedRow() {
let row = Int(indexPath.row)
unterkategorienScene.aktuellesObject = objects[row] as? PFObject
//println(unterkategorienScene.aktuellesObject)
}
}
}
Now I have the problem that I don't know how to display all subcategories (unterkategorien) of the chosen Category in the second TableViewController. The Subcategories have a Parse pointer to the Categories but how should I use that in this case?
At the moment it displays all Subcategories in the second Tableview when I first choose a Category in the first TableView.
My code of the second TableViewController actually looks like this:
import UIKit
class UnterkategorienTableViewController: PFQueryTableViewController {
var aktuellesObject : PFObject?
// 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 = "Unterkategorien"
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("UnterkategorienTableCell") as UnterkategorienTableCell!
if cell == nil {
cell = UnterkategorienTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: "UnterkategorienTableCell")
}
if let objecti = aktuellesObject?{
// Extract values from the PFObject to display in the table cell
cell.unterkategorienName.text = object["name"] as String!
//println(object["name"].objectId)
var thumbnail = object["bild"] as PFFile
var initialThumbnail = UIImage(named: "Kategorien")
cell.unterkategorienBild.image = initialThumbnail
cell.unterkategorienBild.file = thumbnail
cell.unterkategorienBild.loadInBackground()
}
return cell
}
}

Why don't you create the void which you created in the main (KategorienTableViewController) called queryForTable()?
But then you need the current category which you have to pass via the prepareForSegue (what you already did) but you need to pass the Category and not the subcategory.
It would look something like this:
KategorienTableViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
var unterkategorienScene = segue.destinationViewController as UnterkategorienTableViewController
// Pass the selected object to the unterkategorien view controller.
if let indexPath = self.tableView.indexPathForSelectedRow() {
let row = Int(indexPath.row)
unterkategorienScene.aktuellesObject = objects[row] as? PFObject
//println(unterkategorienScene.aktuellesObject)
}
}
UnterkategorienTableViewController:
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: self.parseClassName)
query.whereKey("category", equalTo: aktuellesObject)
return query
}
ps. Wie ich sehe sprichst du Deutsch, probier nicht Deutsch und Englisch während dem Programmieren zu vermischen das sorgt für Chaos.

Related

Is there any way to delete a row from a PFQuery if a condition is met?

I'm trying to remove a row if the condition retrieved from var cellStatus = object["active"] as! Bool is false. I've tried a couple of different things and cant seems to get anything to work. Hiding the cell just leaves a large gap in the tableView.
class TableViewController: PFQueryTableViewController {
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.parseClassName = "specials"
self.pullToRefreshEnabled = true
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
var query = PFQuery(className: parseClassName!)
query.limit = 6
query.orderByAscending("specialRank")
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFTableViewCell {
var cellStatus = object["active"] as! Bool
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! PFTableViewCell!
if cell == nil {
cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
if let locationName = object["locName"] as? String {
cell?.textLabel?.text = locationName
}
if let spec = object["special"] as? String {
cell?.detailTextLabel?.text = spec
}
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
var detailScene = segue.destinationViewController as! DrinkInfoViewController
// 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!
}
}
override func viewWillAppear(animated: Bool)
{
self.navigationController?.navigationBarHidden = false
}
}

UIImageVIew keep coming forward in TableViewCell (using swift, Xcode)

I'm trying to build an app using UITableViewController. I set a UIImageView inside the UITableViewCell.
I've managed to show the image. But, I still can't manage the image to stay at back.
I already use command Editor >> Arrange >> Send to Back, in storyboard, but it's not working.
I also tried this code : cell.sendSubviewToBack(cell.photo)
, but still got the same problem.
can someone help me with this?
FYI, I used ParseUI SDK from parse.com
here is my whole code :
import UIKit
class TableViewController: PFQueryTableViewController, UISearchBarDelegate {
#IBOutlet 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.pullToRefreshEnabled = true
self.paginationEnabled = true
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery {
// Start the query object
var query = PFQuery(className: "Places")
// query with pointer
query.includeKey("mainPhoto")
// Add a where clause if there is a search criteria
if searchBar.text != "" {
query.whereKey("name", containsString: searchBar.text)
}
// Order the results
query.orderByAscending("name")
// Return the qwuery object
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell? {
var cell = tableView.dequeueReusableCellWithIdentifier("tableCell") as! CustomTableViewCell!
if cell == nil {
cell = CustomTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "tableCell")
}
// Extract values from the PFObject to display in the table cell
if let name = object["name"] as? String{
cell.name.text = name
}
if let detail = object["address"] as? String{
cell.detail.text = detail
}
// display initial image
var initialThumbnail = UIImage(named: "question")
cell.photo.image = initialThumbnail
cell.photo.contentMode = UIViewContentMode.Center
// extract image from pointer
if let pointer = object["mainPhoto"] as? PFObject {
if let thumbnail = pointer["photo"] as? PFFile {
cell.photo.file = thumbnail
cell.photo.loadInBackground()
cell.photo.contentMode = UIViewContentMode.ScaleAspectFill
cell.sendSubviewToBack(cell.photo)
}
}
// return the cell
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
}
}
override func viewDidLoad(){
super.viewDidLoad()
let tapGesture = UITapGestureRecognizer(target:self, action:Selector("hideKeyboard"))
tapGesture.cancelsTouchesInView = true
// tableView.addGestureRecognizer(tapGesture)
}
func hideKeyboard(){
tableView.endEditing(true)
}
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
}
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()
}
}

Querying an array to populate a table view in Swift using Parse

I'm querying a Parse class for the current user's username. The class column is named Attendants and the array definitely contains the username. When the code is ran, the table isn't populated and no errors are thrown.
Would anybody be able to point out what I'm doing wrong?
Necessary code is shown below:
class EventsViewController: PFQueryTableViewController{
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.
}
// 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 = "Event"
self.textKey = "username"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "Event")
var tempname = PFUser.currentUser().username
NSLog(tempname)
query.whereKey("Attendants", equalTo: tempname)
return query
}
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! PFTableViewCell!
if cell == nil {
cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell.selectionStyle = UITableViewCellSelectionStyle.None
}
// Extract values from the PFObject to display in the table cell
cell?.textLabel?.text = object["EventName"] as! String!
cell?.detailTextLabel?.text = object["EventName"] as! String!
cell.selectionStyle = UITableViewCellSelectionStyle.None
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! EventDetailViewController
// 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
}
}
override func viewDidAppear(animated: Bool) {
// Refresh the table to ensure any data changes are displayed
tableView.reloadData()
}
}
All you need to do is write the queryForTable() function.
All your tableView functions are never called.
So something about this would be solution:
class EventsViewController: PFQueryTableViewController {
override init(style: UITableViewStyle, className: String?) {
super.init(style: style, className: className)
self.textKey = "YOUR_PARSE_COLOMN_YOU_WANT_TO_SHOW"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
required init!(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Event")
var tempname = PFUser.currentUser()!.username
NSLog(tempname!)
// This is really ugly.. Please do this via Pointer and not via String.
query.whereKey("Attendants", equalTo: tempname!)
return query
}
}
If you want to use custom cells, you need to create your own TableViewController and implement the logic on the TableViewController itself.
This code is tested in Xcode 6.3 (swift 1.2)
Please keep in mind that you need to init the tableViewController out of the code, like:
var eventsvc = EventsViewController(style: .Plain, className: "Event")
to present it out of a viewcontroller:
self.presentViewController(eventsvc, animated: true, completion: nil)
If you want to use is it in a storyboard see this

Pulling date into subtitle for tableview controller PFTableView

The following is successful at pulling the "category" into the main Title until I start trying get createdAt into the subtitle.
When I start to override func tableView to import the createdAt into the subtitle, the app crashes.
Any thoughts?
import UIKit; import Parse
class UserRecordsTableViewController: PFQueryTableViewController {
// 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 = "Event"
self.textKey = "category"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "event")
query.orderByAscending("createdAt")
query.whereKey("user", equalTo: PFUser.currentUser())
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as PFTableViewCell!
if cell == nil {
cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
//Date for cell subtitle
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateForText = object["createdAt"] as? NSDate
cell.detailTextLabel?.text = dateFormatter.stringFromDate(dateForText!)
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].
}
}
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
detailTextLabel will be nil in a cell of the default type. If you made the cell in the storyboard, set its type to "Subtitle". If you didn't make it in the storyboard, then change the line where you create the cell to,
cell = PFTableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
Heres what I ended up going with and this works so far. The problem was that PFTableViewCell is only intended to work with default not subtitle. So I had to create a custom cell. Next finally found the solution to the date fix on another post.
import UIKit; import Parse
class UserRecordsTableViewController: PFQueryTableViewController {
// 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 = "Event"
self.textKey = "category"
self.title = "createdAt"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "event")
query.orderByAscending("createdAt")
query.whereKey("user", equalTo: PFUser.currentUser())
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as UserRecordsTableViewCell!
if cell == nil {
cell = UserRecordsTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
var dateUpdated = object.createdAt as NSDate
var dateFormat = NSDateFormatter()
dateFormat.dateFormat = "EEE, MMM d, h:mm a"
cell.catDate.text = NSString(format: "%#", dateFormat.stringFromDate(dateUpdated))
cell.catTitle.text = object["category"] as String!
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 YourDetailViewController*/
// 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
}*/
}
}

in Parse.com, how to use query.includeKey in PFQueryTableViewController with swift?

I'm trying to populate a table using PFQueryTableViewController.
I want to use data from two class, which is Places and Details.
In Places, I have two column, which is placeText as string, and pointerToDetails as pointer.
In Details, I have one column, which is detailText.
I want to show the placeText and detailText in the same CustomCell which I already defined as PFTableViewCell.
Unfortunately, after I run the code, I only got the placeText inside the CustomCell.
import UIKit
class TableViewController: PFQueryTableViewController {
// 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.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "Places")
query.includeKey("pointerToDetails")
return query
}
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
cell.name.text = object["placeText"] as String!
cell.detail.text = object["detailText"] as String!
return cell
}
}
After I got an inspiration from #deadbeef (see answer 1), here is the solution I got :
query.includeKey("pointerToDetails") is querying an object which can be accessed via object["pointerToDetails"].
to extract data from column detailText which already included in object["pointerToDetails"], just do this :
if let pointer = object["pointerToDetails"] as? PFObject {
cell.detail.text = object["detailText"] as String!
}
here is the whole code :
import UIKit
class TableViewController: PFQueryTableViewController {
// 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.pullToRefreshEnabled = true
self.paginationEnabled = false
}
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: "Places")
query.includeKey("pointerToDetails")
return query
}
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
cell.name.text = object["placeText"] as String!
if let pointer = object["pointerToDetails"] as? PFObject {
cell.detail.text = object["detailText"] as String!
}
return cell
}
}
The detailtext property will not be included in your object as the includeKey() might suggest, but the Details object pointed by pointerToDetails will be queried along with you Places object.
So in order to get the value of detailText, you have to go through the pointer. In other words, try this :
cell.name.text = object["placeText"] as String!
cell.detail.text = object["pointerToDetails"]["detailText"] as String!

Resources