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

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.

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

Parse and Swift. Get cells in UITableView which have a checkmark. "Cannot invoke argument.ā€œ

Iā€™m trying to get rows from a UITableView that have been marked by the user and then save them as Parse relations to the current user.
Here is the code for the IBAction (Save button) and the function:
#IBAction func saveButton(sender: AnyObject) {
getCheckmarkedCells(tableView: UITableView,indexPath: NSIndexPath)
}
func getCheckmarkedCells(tableView: UITableView, indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if cell.accessoryType == .Checkmark {
let checkedCourse = cell.textLabel?.text
var query = PFQuery(className: "Courses")
query.whereKey("coursename", equalTo: checkedCourse!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
}
}
} else {
// Log details of the failure
println("Error")
}
}
}
}
I get an error in line 2:
Cannot invoke 'getCheckmarkedCells' with an argument list of type '(tableView: UITableView.Type, indexPath: NSIndexPath.Type)ā€˜
What am I doing wrong?
EDIT:
// Configure cells for Checkmarks
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if cell.accessoryType == .Checkmark
{
cell.accessoryType = .None
}
else
{
cell.accessoryType = .Checkmark
}
}
}
EDIT2:
import UIKit
import Parse
import ParseUI
class KurseTableViewController: 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 = "Courses"
self.textKey = "coursename"
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: "Courses")
query.orderByDescending("coursename")
return query
}
var selectedRows = NSMutableIndexSet()
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if (self.selectedRows.containsIndex(indexPath.row)) {
cell.accessoryType = .None
self.selectedRows.removeIndex(indexPath.row)
} else {
cell.accessoryType = .Checkmark
self.selectedRows.addIndex(indexPath.row);
}
}
}
#IBAction func saveButton(sender: AnyObject) {
//getCheckmarkedCells(tableView: UITableView indexPath: NSIndexPath)
}
/*func getCheckmarkedCells(tableView: UITableView, indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if cell.accessoryType == .Checkmark {
let checkedCourse = cell.textLabel?.text
var query = PFQuery(className: "Courses")
query.whereKey("coursename", equalTo: checkedCourse!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
}
}
} else {
// Log details of the failure
println("Error")
}
}
}*/
}
EDIT3:
#IBAction func saveButton(sender: AnyObject) {
let currentUser = PFUser.currentUser()
var selectedObjects = Array<PFObject>()
let cUserRel = currentUser?.relationForKey("usercourses")
for object in qObjects {
cUserRel!.removeObject(object as! PFObject)
}
println(selectedRowSets)
for selectedRows in self.selectedRowSets {
println("count")
selectedRows.enumerateIndexesUsingBlock(
{(index, stop) -> Void in
// Get object reference
if self.objects != nil{
let anObject = self.objects![index] as! PFObject
selectedObjects.append(anObject)
println(anObject)
cUserRel!.addObject(anObject)
}
})
}
currentUser?.save()
navigationController?.popViewControllerAnimated(true)
}
When you are calling your function you are specifying the parameter types (which is why the error message says that you call it with UITableView.Type and NSIndexPath.Type.
You need to specify instances of a UITableView and an NSIndexPath -
Something like
getCheckmarkedCells(tableview:self.tableView indexPath: someIndexPath);
However, you probably don't want to send a specific index path to this method because you want to scan the entire table, not just look at a specific row.
Your fundamental problem is that you appear to be using your table view as a data model - the tableview should simply be a view of data stored in some other data structure. For example, cellForRowAtIndexPath may return nil for a cell that isn't currently on screen.
You can use an NSMutableIndexSet for storing your selected rows -
var selectedRowSets = [NSMutableIndexSet]() // You will need to add a NSMutableIndexSet to this array for each section in your table
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let selectedRows=self.selectedRowSets[indexPath.section]
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
if (selectedRows.containsIndex(indexPath.row)) {
cell.accessoryType = .None
selectedRows.removeIndex(indexPath.row)
} else {
cell.accessoryType = .Checkmark
selectedRows.addIndex(indexPath.row);
}
}
}
You should use the same test in cellForRowAtIndexPath to set the accessory on cells as they are reused.
You can retrieve the checked row using
func getSelectedObjects() {
self.selectedObjects=Array<PFObject>()
for selectedRows in self.selectedRowSets {
selectedRows.enumerateIndexesUsingBlock({index, stop in
// Get object reference
if self.objects != nil{
let anObject=self.objects![index] as! PFObject
self.selectedObjects.append(anObject)
}
})
}
}
Do you already have an array that contains all of the Courses from Parse?
You need to allocate a new NSIndexSet for each section. Remove the selectedSet instance variable and change your loop in objectsDidLoad to
for index in 1...section {
self.selectedRowSets.append(NSMutableIndexSet())
}
Another solution would be to parse through each cell in the tableView at the end and check if it is marked or not. I am assuming you have only one section
let rowCount = tableView.numberOfRowsInSection(0)
let list = [TableViewCell]()
for var index = 0; index < rowCount; ++index {
let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: index, inSection: 0)) as! YourCell
if cell.accessoryType = .Checkmark{
list.append(cell)
}

Swift Displaying Parse Image in TableView Cell

I am attempting to display the users image that is saved to parse property "image". I have been able to display my username with no issue, but I can't seem to be able to get my image to appear. Should I be casting this information as UIImage? Am I correctly calling where the file is stored?
Here is my code:
import UIKit
class SearchUsersRegistrationViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var userArray : NSMutableArray = []
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadParseData()
var user = PFUser.currentUser()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadParseData() {
var query : PFQuery = PFUser.query()
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
if let objects = objects {
println("\(objects.count) users are listed")
for object in objects {
self.userArray.addObject(object)
}
self.tableView.reloadData()
}
} else {
println("There is an error")
}
}
}
let textCellIdentifier = "Cell"
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.userArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! SearchUsersRegistrationTableViewCell
let row = indexPath.row
var individualUser = userArray[row] as! PFUser
var username = individualUser.username as String
var profilePicture = individualUser["image"] as? UIImage
cell.userImage.image = profilePicture
cell.usernameLabel.text = username
return cell
}
#IBAction func finishAddingUsers(sender: AnyObject) {
self.performSegueWithIdentifier("finishAddingUsers", sender: self)
}
}
The photos are saved in a PFFile and not as a UIImage..
What makes your code the following:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! SearchUsersRegistrationTableViewCell
let row = indexPath.row
var individualUser = userArray[row] as! PFUser
var username = individualUser.username as String
var pfimage = individualUser["image"] as! PFFile
pfimage.getDataInBackgroundWithBlock({
(result, error) in
cell.userImage.image = UIImage(data: result)
})
cell.usernameLabel.text = username
return cell
}
See more in the docs
fileprivate func getImage(withCell cell: UITableViewCell, withURL url: String) {
Alamofire.request(url).responseImage { (image) in
/* Assign parsed Image */
if let parsedImage = image.data {
DispatchQueue.main.async {
/* Assign Image */
cell.imageView?.image = UIImage(data: parsedImage)
/* Update Cell Content */
cell.setNeedsLayout()
cell.layoutIfNeeded()
}
}
}
}

PFQueryTable Parse

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
}

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)

Resources