PFQueryTable Parse - ios

I am trying to get videos that i saved to parse to show up in my tableview cell when i load the data but for some reason when i run the program the table view is blank. I have tried using UITableViewController instead of parse's but i couldn't get it to work that way either. Is there any way i can get the video to show up in the tableview cell?
Code:
import UIKit
import MediaPlayer
class TableViewController: PFQueryTableViewController {
var song: NSURL!
var player:MPMoviePlayerController!
override init!(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.parseClassName = "Videos"
self.pullToRefreshEnabled = true
self.objectsPerPage = 10
self.paginationEnabled = true
}
override func queryForTable() -> PFQuery! {
var query = PFQuery(className: self.parseClassName)
if (objects.count == 0)
{
query.cachePolicy = kPFCachePolicyNetworkOnly
}
return query
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func objectAtIndexPath(indexPath: NSIndexPath!) -> PFObject! {
var obj : PFObject? = nil
if(indexPath.row < self.objects.count){
obj = self.objects[indexPath.row] as PFObject
}
return obj
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject!) -> PFTableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as PFTableViewCell
let video:PFFile = object["musicVideo"] as PFFile
let url: NSURL = NSURL(string: video.url)!
println(video)
player = MPMoviePlayerController(contentURL: url)
player.controlStyle = MPMovieControlStyle.None
player.scalingMode = MPMovieScalingMode.AspectFit
player.view.frame = cell.contentView.bounds
cell.contentView.addSubview(player.view)
player.view.hidden = false
player.prepareToPlay()
player.play()
return cell
}
}

NB the correct code for setting the objects in a PFQueryTableViewController in Swift 1.2 appears to have changed slightly (force unwrapping to PFObject! will cause a crash when the last cell in the table is loaded, if it is not the "load more" cell, as will counting objects! instead of objects?).
override func objectAtIndexPath(indexPath: NSIndexPath!) -> PFObject? {
var obj : PFObject? = nil
if(indexPath.row < self.objects!.count){
obj = self.objects?[indexPath.row] as? PFObject
}
return obj
}

Related

Retrieving User Profile Image and Username in TableView from Parse - Swift

I am able to fetch users and their profile pictures however, I'd like to return just the current user in the table and it doesn't seem possible since I'm using NSMutableArray to hold the user value.
UPDATE: I've edited to show my complete class
var userArray : NSMutableArray = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadParseData()
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
// Do any additional setup after loading the view.
}
func loadParseData() {
var query : PFQuery = PFUser.query()!
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
self.userArray.addObject(object)
}
self.tableView.reloadData()
}
} else {
println("There is an error")
}
}
}
// 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 PFQueryTableView
self.parseClassName = "User"
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: "User")
return query
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//How can I return PFUser.currentUser() here?
return self.userArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
var userProfileImage = userArray[row] as! PFUser
var username = userProfileImage.username as String!
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! ProfileTableViewCell
//Display Profile Image
PFUser.currentUser()?["profile_picture"]
if let pfimage = PFUser.currentUser()?["profile_picture"] as? PFFile{
pfimage.getDataInBackgroundWithBlock({
(result, error) in
cell.profileImage.image = UIImage(data: result!)
cell.userName.text = username
})
}
return cell
}
You may declare your array as an AnyObject array. Try this:
var userArray : AnyObject = []
Try using some breakpoints to take a look on the variables and understand whats going on.
Also, if you have only one section on your Table View there is no need on calling numberOfSectionsInTableView since the defaul is 1.

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
}
}

How do i load item 5 per 5? in PFQueryTableViewController

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()
}
}

Reverse order from query.whereKey("column", nearGeoPoint) in UITableView

I'm trying to get location data(PFGeoPoint) from parse.com, show it in UITableView, and sort it by nearest one from user location.
I already use the code same with shown in parse documentation :
findPlaceData.whereKey("position", nearGeoPoint:SearchLocationGeoPoint)
I managed to get the data. I also managed to show it in my UITableView. The problem is, the order is reversed. I got the farthest in my first cell. Could anyone explain why this happen, and how to fix it?
import UIKit
class SearchTableViewController: UITableViewController {
#IBOutlet var SearchTitle: UILabel!
var userLocationToPass:CLLocation!
var categoryToPass:String!
var categoryIdToPass:String!
var placeData:NSMutableArray! = NSMutableArray()
override init(style: UITableViewStyle) {
super.init(style: style)
// Custom initialization
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func loadData(){
placeData.removeAllObjects()
let searchLocationGeoPoint = PFGeoPoint(location: userLocationToPass)
var findPlaceData:PFQuery = PFQuery(className: "Places")
findPlaceData.whereKey("category", equalTo: categoryIdToPass)
findPlaceData.whereKey("position", nearGeoPoint:searchLocationGeoPoint)
findPlaceData.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects{
let place:PFObject = object as PFObject
self.placeData.addObject(place)
}
let array:NSArray = self.placeData.reverseObjectEnumerator().allObjects
self.placeData = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
override func viewWillAppear(animated: Bool) {
loadData()
}
override func viewDidLoad() {
super.viewDidLoad()
SearchTitle.text = categoryToPass
println(userLocationToPass)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
return placeData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:SearchTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as SearchTableViewCell
let place:PFObject = self.placeData.objectAtIndex(indexPath.row) as PFObject
cell.placeName.text = place.objectForKey("name") as? String
cell.placeOpenHour.text = place.objectForKey("openhour") as? String
return cell
}
}
Are you intentionally using the reverseObjectEnumerator? Because that could account for your results being reversed... The clue is in the method name ;-)
If you drop the following two lines from your code, it might not be reversed anymore.
let array:NSArray = self.placeData.reverseObjectEnumerator().allObjects
self.placeData = NSMutableArray(array: array)

UITableViewCell in Swift

This is a sample code with UITableViewController and CoreData. Main file MainTableViewController.swift:
import UIKit
import CoreData
class MainTableViewController: UITableViewController {
var results:AddrBook[]=[]
init(style: UITableViewStyle) {
super.init(style: style)
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidAppear(animated: Bool) {
let request = NSFetchRequest(entityName: "Person")
request.returnsObjectsAsFaults = false
let appDelegate:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
let context:NSManagedObjectContext = appDelegate.managedObjectContext
results = context.executeFetchRequest(request, error: nil) as AddrBook[]
self.tableView.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
return results.count
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell! {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
if !cell {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
cell!.textLabel.text = results[indexPath.row].lastname + " " + results[indexPath.row].firstname
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject?) {
var indexPath = self.tableView.indexPathForSelectedRow()
let destViewController:DetailViewController! = segue.destinationViewController as DetailViewController
if segue.identifier == "editPerson" {
destViewController.receivedPerson = results
destViewController.indexPath = indexPath
}
}
}
If in cellForRowAtIndexPath I use this:
cell!.textLabel.text = results[indexPath.row].lastname + " " + results[indexPath.row].firstname
then all is good. But if I use this:
cell!.textLabel.text = results[indexPath.row].lastname
cell!.detailTextLabel.text = results[indexPath.row].firstname
I see error: Can't unwrap Optional.None
What's wrong? Help, please.
Just in case the codes of other classes
Class UIViewController for add and edit records (DetailViewController.swift):
import UIKit
import CoreData
class DetailViewController: UIViewController {
#IBOutlet var currentOperation : UILabel = nil
#IBOutlet var firstnameField : UITextField = nil
#IBOutlet var lastnameField : UITextField = nil
var indexPath = NSIndexPath()
var receivedPerson:AddrBook[]=[]
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
if !receivedPerson.isEmpty { // If selected row in tableview in MainTableViewController
currentOperation.text = "Edit Person"
firstnameField.text = receivedPerson[indexPath.row].firstname
lastnameField.text = receivedPerson[indexPath.row].lastname
}
else { // If pressed "+" in MainTableViewController
currentOperation.text = "Add Person"
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func saveButton(sender : AnyObject) {
let appDelegate:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
let context:NSManagedObjectContext = appDelegate.managedObjectContext
if receivedPerson.isEmpty { // If pressed "+" in MainTableViewController
let projectEntity = NSEntityDescription.entityForName("Person", inManagedObjectContext: context)
var newPerson = AddrBook(entity: projectEntity, insertIntoManagedObjectContext: context)
newPerson.lastname = lastnameField.text
newPerson.firstname = firstnameField.text
}
else { // If selected row in tableview in MainTableViewController
receivedPerson[indexPath.row].firstname = firstnameField.text
receivedPerson[indexPath.row].lastname = lastnameField.text
}
context.save(nil)
self.navigationController.popViewControllerAnimated(true)
}
}
Class AddrBook.swift for CoreData:
import UIKit
import CoreData
#objc(AddrBook)
class AddrBook: NSManagedObject {
#NSManaged var lastname:String
#NSManaged var firstname:String
}
Use
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
instead
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
Swift 4+
Use
cell = UITableViewCell(style: .value1, reuseIdentifier: "Cell")
instead
cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
For Swift 4+ , use:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if( !(cell != nil))
{
cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell")
}
cell!.textLabel?.text = "Hello"
return cell!
}
try using like this.
just avoid the exclamation marks
cell.text = results[indexPath.row].lastname as NSString
cell.detailTextLabel.text = results[indexPath.row].firstname as NSString
And i see that , there is lots error in your code. !!

Resources