I'm building an app in which I want to show a couple of rows of data in parse.
I want to have freedom when it comes to setting up the cell UI, therefore I followed this tutorial.
I have a class CustomCell to link my labels and UIImage
import Foundation
import UIKit
import ParseUI
class CustomCell: PFTableViewCell {
#IBOutlet weak var nomePrato: UILabel!
#IBOutlet weak var precoPrato: UILabel!
#IBOutlet weak var imagemPrato: PFImageView!
}
And another class to set everything up
import UIKit
import Parse
import ParseUI
class TableViewControllerPratos2: 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 = "ProdutosVenda"
self.textKey = "Nome"
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: "ProdutosVenda")
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! CustomCell!
if cell == nil {
cell = CustomCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
// Extract values from the PFObject to display in the table cell
if let nome = object?["Nome"] as? String {
cell?.nomePrato.text = nome
}
if let preco = object?["Preco"] as? String {
cell?.precoPrato.text = preco
}
// Display flag image
var initialThumbnail = UIImage(named: "question")
cell.imagemPrato.image = initialThumbnail
if let thumbnail = object?["imagem1"] as? PFFile {
cell.imagemPrato.file = thumbnail
cell.imagemPrato.loadInBackground()
}
return cell
}
}
The outcome: no error, just a blank outline of the cells with no elements and a spinning loading animation.
Related
Im using PFQueryTableViewController to load all my data from parse.
Currently it loads all the data at once, so in the future if i have many data it will mess up the user experience of users. How do i load it 5 per 5 whenever I scrolled down?
Here's the code
import UIKit
import Parse
import ParseUI
class MainViewTable: 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)
self.parseClassName = "product"
self.textKey = "createdAt"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "product")
query.orderByDescending("createdAt")
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")
}
if let titleName = object?["title"] as? String {
cell.title.text = titleName
}
if let priceTitle = object?["price"] as? Int {
cell.price.text = String(priceTitle)
println(cell.price.text! + "Price")
}
return cell
}
override func viewDidAppear(animated: Bool) {
// Refresh the table to ensure any data changes are displayed
tableView.reloadData()
}
}
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.
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!
All,
I have got the cells working fine with a normal cell, but I am trying to create a custom cell with a nib etc and then link that into PARSE using PFQueryTableViewController.
Here is my code :
class CustomCell: PFTableViewCell
{
#IBOutlet var EventTypeImage: UIImageView!
#IBOutlet var titleLabel: UILabel!
}
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 = "Events_"
self.pullToRefreshEnabled = true
self.paginationEnabled = true
//self.objectsPerPage = 5
//self.textKey = "TypeOfVenue_"
}
override func viewDidLoad() {
var nib = UINib(nibName: "CustomTableViewCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "CustomCell")
}
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: self.parseClassName)
if (objects.count == 0)
{
query.cachePolicy = kPFCachePolicyNetworkOnly
}
return query
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject!) -> PFTableViewCell!
{
var custom = CustomCell()
var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as PFTableViewCell!
custom.titleLabel?.text = object["Title"] as NSString
return cell
}
So I have created a custom cell and linked it with the CustomCell Class at the top. In CellForRowatIndexPath. I have created a new instance of the CustomCell Class and got the titlelabel from it and then Casted it to NSstring and used PARSE to get the 'object'.
I don't have any errors. All I get on the tableview is a spinning wheel saying Loading.
Any advice would be brilliant.
Was having a similar problem, where the nib wasn't getting loaded. I then realized I could create the custom cell right in the prototype of the tableviewcontroller in the storyboard, which I did, and changed the class in the identity inspector as shown. Here QuestionCell would be your custom cell file.
I would separate CustomCell into a different and make sure you have that selected in the prototype identity inspector. As well, make sure the style is custom, and make sure any of the labels are connected in the storyboard with the iboutlets in the new CustomCell class.
Then, you can delete the
var nib = UINib(nibName: "CustomTableViewCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "CustomCell")
since you are using the prototype.
Then replace
var cell = tableView.dequeueReusableCellWithIdentifier("CustomCell") as PFTableViewCell!
with
var cell:CustomCell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as? CustomCell
and you should be good to go! Let me know if this works!
I also had a spinning loading wheel while adding initializer properties to this init method:
required init(coder aDecoder: NSCoder)
But doing this, instead, worked:
//class TableViewController: PFQueryTableViewController
override init!(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
self.parseClassName = "todo"
self.pullToRefreshEnabled = true
self.paginationEnabled = true
self.objectsPerPage = 30
self.tableView.estimatedRowHeight = 80
}
This is driving me bonkers,
I am trying to create an custom cell with a prototype cells within Parse API - I have been banging my head for a whole day.
I don't have any error, but it doesn't work - I think there is a problem with my classes and whats a UITableView and whats PFTableViewCell, can someone who knows PARSE have a look at this please.
class CustomCell: PFTableViewCell {
#IBOutlet weak var EventTitle: UILabel!
}
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 = "Events_"
self.pullToRefreshEnabled = true
self.paginationEnabled = true
}
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: self.parseClassName)
if (objects.count == 0)
{
query.cachePolicy = kPFCachePolicyNetworkOnly
}
return query
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject!) -> PFTableViewCell {
var cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as CustomCell
cell.EventTitle.text = object["Title"] as NSString
return cell
}
Any help would be brilliant, thanks