I'm trying to save images from Parse to a variable called image stored which I can then set to tableview cells. At the moment I just have the images from parse being saved to a PFImageView. But when I try to set these to Table View Cells I get an error : Cannot assign value of type 'PFImageView' to type 'UIImage?' . Really appreciate any help.
Here's my code:
import UIKit
import Parse
import Bolts
import ParseUI
class YourEvents: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var currentuser = PFUser.currentUser()?.username
//array
var testArray = [String]()
var testdecr = [String]()
var image = UIImage()
var imagestored = PFImageView()
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className:"Companies")
let pUserName = PFUser.currentUser()?["username"] as? String
query.whereKey("createdby", equalTo:"\(pUserName)")
// let runkey = query.orderByAscending("companyname")
query.findObjectsInBackgroundWithBlock{
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
//do something with the found objects
if let objects = objects as [PFObject]! {
for object in objects {
let load = object.objectForKey("companyname") as! String
self.testArray .append(load)
print(self.testArray)
let load2 = object.objectForKey("companydescription") as! String
self.testdecr.append(load2)
print(self.testdecr)
if let userImageFile = object["imagefile"] as? PFFile {
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
self.image = UIImage(data:imageData)!
}
}
}
}
}
}
} else {
//log details of failure
print("Error: \(error!) \(error?.userInfo) ")
}
}
// reload UIViewController and UITabkeView
sleep(3)
do_table_refresh()
}
func do_table_refresh () {
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
return
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return testArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("yourstartups", forIndexPath: indexPath) as! YourStartupsCell
cell.lbTitle!.text = self.testArray[indexPath.row]
cell.lbDescription!.text = self.testdecr[indexPath.row]
cell.logo!.image = self.imagestored
return cell
}
}
In your code you never initialize imagestored (PFImageView) but only image (UIImage). try to change in to
cell.logo!.image = self.image
I no have idea if PFImageView has any
PFImageView.image
instances, than should be UIImage() class.
Also you should have something like this:
if let userImageFile = object["imagefile"] as? PFFile {
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
self.image = UIImage(data:imageData)!
var img = UIImage(data:imageData)
image.append(img)
self.tableView.reloadData()
}
}
}
Try to set the image to UIImage and call do_table_refresh() at the next line
Related
I have seen the following questions.
Get data from a pointer's row in Parse (ios)
and various other questions but still unable to figure out.
I have a class in Parse called 'Plumber'
As you can see the 'practiceArea' is a pointer to this class called 'PracticeArea' (mind the uppercase P in the class)
So from here I want to extract the corresponding 'title' column value for the corresponding pointer. How can I do this?
This is my code so far
//
// Directory.swift
// plumber_main
//
// Created by James on 13/4/16.
// Copyright © 2016 James. All rights reserved.
//
import UIKit
import Parse
class Directory: UITableViewController {
#IBOutlet var plumbersDirectory: UITableView!
var profImages = [PFFile]()
var plumberName = [String]()
var plumberRate = [NSNumber]()
var plumberPracArea = [PFObject]()
var plumberExp = [String]()
var refresher: UIRefreshControl!
func refresh()
{
let query_one = PFQuery(className: "PracticeArea")
query_one.includeKey("title")
let query = PFQuery(className: "plumber")
query.includeKey("practiceArea")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock(
{
(listll: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(listll!.count) names of the plumbers.")
// Do something with the found objects
if let objects = listll {
for object in objects {
print(object)
self.profImages.append(object["photo"] as! PFFile)
self.plumberName.append(object["name"] as! String)
self.plumberExp.append(object["expLevel"] as! String)
self.plumberPracArea.append(object["practiceArea"] as! PFObject)
print(object ["practiceArea"].objectId)
self.plumberRate.append(object["ratePerHr"] as! NSNumber)
// print(object["plumber_Name"] as! String )
// self.plumbersname.append(object["plumber_Name"] as! String)
//self.lblName.text = object["plumber_Name"] as? String
}
self.plumbersDirectory.reloadData()
}
print(self.plumberName.count)
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
self.tableView.reloadData()
self.refresher.endRefreshing()
})
}
override func viewDidLoad() {
super.viewDidLoad()
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refrehsh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
refresh()
}
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
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return plumberName.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let plumbercell: plumber_Directory_Cell = tableView.dequeueReusableCellWithIdentifier("plumberlistproto") as! plumber_Directory_Cell
plumbercell.name.text = plumberName[indexPath.row]
plumbercell.exp.text = plumberExp[indexPath.row]
plumbercell.pracArea.text = String(plumberPracArea[indexPath.row])
plumbercell.price.text = String (plumberRate[indexPath.row])
profImages[indexPath.row].getDataInBackgroundWithBlock{(imageData: NSData?, error: NSError?) -> Void in
if imageData != nil {
let image = UIImage(data: imageData!)
plumbercell.mini_image.image = image
}
else
{
print(error)
} }
//cell.textLabel?.text = plumbersname[indexPath.row]
return plumbercell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
print(indexPath.row)
}
}
Try this
func refresh()
{
let query = PFQuery(className: "PracticeArea")
query.includeKey("practiceArea")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock( {
(listll: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(listll!.count) names of the plumbers.")
// Do something with the found objects
if let objects = listll {
self.plumberName = objects
} else {
self.plumberName.removeAllObjects()
}
self.plumbersDirectory.reloadData()
print(self.plumberName.count)
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
})
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let plumbercell: plumber_Directory_Cell = tableView.dequeueReusableCellWithIdentifier("plumberlistproto") as! plumber_Directory_Cell
let object = plumberName[indexPath.row]
plumbercell.name.text = object["name"]
plumbercell.exp.text = object["expLevel"]
let practiceArea = object["practiceArea"]
plumbercell.pracArea.text = practiceArea["title"]
plumbercell.pracArea.text = String(plumberPracArea[indexPath.row])
plumbercell.price.text = String (plumberRate[indexPath.row])
profImages[indexPath.row].getDataInBackgroundWithBlock{(imageData: NSData?, error: NSError?) -> Void in
if imageData != nil {
let image = UIImage(data: imageData!)
plumbercell.mini_image.image = image
}
else
{
print(error)
} }
//cell.textLabel?.text = plumbersname[indexPath.row]
return plumbercell
}
You were really close and definitely not "doing it all wrong". Since you've already included the key in the query request, when you want the information from that object too, then you just need this
let practiceArea = object["projectArea"] as! PFObject
let title = practiceArea["title"] as? String
you should query the different class if you want to use the pointer with the "includeKey"...
let query: PFQuery = PFQuery(className: "PracticeArea")
query.orderByDescending("createdAt")
query.includeKey("practiceArea")
query.findObjectsInBackgroundWithBlock{
(objects:[PFObject]?, error:NSError?)->Void in
if error == nil{
for object in objects! {
//do stuff with each object
}
}
}
I am using this code to create a feed view that shows users, images, and comments similar to instagram. For some reason, the cells on the feed are duplicating the current user's posts. Not only that, but it is also putting the incorrect username with the images on the duplicate cells. What am I doing wrong?
import UIKit
import Parse
class FeedTableViewController: UITableViewController {
var usersBeingFollowed = [String]()
var imageFiles = [PFFile]()
var imageComment = [""]
var usernames = [String]()
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.hidesBackButton = true
let getFollowedUsersQuery = PFQuery(className: "Followers")
getFollowedUsersQuery.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
self.usernames.removeAll(keepCapacity: true)
self.imageComment.removeAll(keepCapacity: true)
self.imageFiles.removeAll(keepCapacity: true)
self.usersBeingFollowed.removeAll(keepCapacity: true)
if let objects = objects {
for object in objects {
let followedUser = object["following"] as! String
let getFollowedUsers = PFQuery(className: "Post")
getFollowedUsers.whereKey("userId", equalTo: followedUser)
let getCurrentUser = PFQuery(className: "Post")
getCurrentUser.whereKey("userId", equalTo: (PFUser.currentUser()?.objectId)!)
var query = PFQuery.orQueryWithSubqueries([getFollowedUsers,getCurrentUser])
query.findObjectsInBackgroundWithBlock({ (imageObjects, error) -> Void in
if let objects = imageObjects {
for images in objects {
let userQuery = PFUser.query()
userQuery?.whereKey("_id", equalTo: images["userId"])
userQuery?.findObjectsInBackgroundWithBlock({ (user, error) -> Void in
print(user)
if let user = user {
for username in user {
self.usernames.append(username["username"] as! String)
}
}
})
self.imageFiles.append(images["imageFile"] as! PFFile)
self.imageComment.append(images["imageComment"] as! String)
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
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("imagePostCell", forIndexPath: indexPath) as! cell
if imageFiles.count > 0{
myCell.userLabel.text = "\(usernames[indexPath.row]) completed the \(imageComment[indexPath.row]) challenge!"
imageFiles[indexPath.row].getDataInBackgroundWithBlock({ (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.imagePost.image = downloadedImage
// self.tableView.reloadData()
}
})
}
return myCell
}
You should reset the cell property before add new values, you can use
prepareForReuse()
More info on Apple Doc https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UITableViewCell_Class/index.html#//apple_ref/occ/instm/UITableViewCell/prepareForReuse
It will be obviously, generate the duplicate content because you have put the condition that if imageFiles.count > 0 then the data will be displayed.
But what when there are no images? It will definitely take the value from reusable UITableViewCell. Check the below change:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("imagePostCell", forIndexPath: indexPath) as! cell
if imageFiles.count > 0{
myCell.userLabel.text = "\(usernames[indexPath.row]) completed the \(imageComment[indexPath.row]) challenge!"
imageFiles[indexPath.row].getDataInBackgroundWithBlock({ (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.imagePost.image = downloadedImage
// self.tableView.reloadData()
}
})
}else{
myCell.userLabel.text = "Put What You Want Here" //make just nil
myCell.imagePost.image = UIImage(name: "placeholder.png") //Some Placeholder image when there is no data
}
return myCell
}
I have my tableview returning titles, their descriptions and now I am trying to return images. It currently returns only one image for all of my cells. Is this because I'm storing it in a UIImage?
Here's my code:
import UIKit
import Parse
import Bolts
import ParseUI
class YourEvents: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var currentuser = PFUser.currentUser()?.username
//array
var testArray = [String]()
var testdecr = [String]()
var image = UIImage()
// var imagestored = UIImage()
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className:"Companies")
let pUserName = PFUser.currentUser()?["username"] as? String
query.whereKey("createdby", equalTo:"\(pUserName)")
// let runkey = query.orderByAscending("companyname")
query.findObjectsInBackgroundWithBlock{
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
//do something with the found objects
if let objects = objects as [PFObject]! {
for object in objects {
let load = object.objectForKey("companyname") as! String
self.testArray .append(load)
print(self.testArray)
let load2 = object.objectForKey("companydescription") as! String
self.testdecr.append(load2)
print(self.testdecr)
if let userImageFile = object["imagefile"] as? PFFile {
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
self.image = UIImage(data:imageData)!
print("done!")
self.do_table_refresh()
}
}
}
}
}
}
} else {
//log details of failure
print("Error: \(error!) \(error?.userInfo) ")
}
}
// reload UIViewController and UITabkeView
sleep(3)
do_table_refresh()
}
func do_table_refresh () {
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
return
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return testArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("yourstartups", forIndexPath: indexPath) as! YourStartupsCell
cell.lbTitle!.text = self.testArray[indexPath.row]
cell.lbDescription!.text = self.testdecr[indexPath.row]
cell.logo!.image = self.image
return cell
}
}
I would recommend making an array of PFImage objects, and then in your table view delegate method you can simply access the element at the current row in your index path. Right now your method to get the data is being called once and therefore setting your image to the last fetched object, but since the tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) is being called each time a cell is loaded, you need to keep the images in an array, as you are doing with the text labels.
I can't figure out what is wrong with my tableView: cellForRowAtIndexPath. its never getting called for some reason. i have called the proper delegate and datasource. When I add a print("") line under the cellForRowAtIndexPath function, it never appears when i simulate the app.
Thank you in advanced.
here is my code for the whole page:
class MainPageViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var sportCells = [PFObject]()
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var profilePictureImageView: UIImageView!
#IBOutlet weak var fullNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
//Do any additional setup after loading the view.
}
override func viewDidAppear(animated: Bool) {
updateSportsTable()
print("its happening")
let lastName = PFUser.currentUser()! ["last_name"]
if let firstName = PFUser.currentUser()?["first_name"] as? String {
self.fullNameLabel.text = "\(firstName) \(lastName)"
}
if let userPicture = PFUser.currentUser()?["profile_picture"] as? PFFile {
userPicture.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if (error == nil) {
self.profilePictureImageView.image = UIImage(data:imageData!)
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("sportCells count is \(sportCells.count)")
return sportCells.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("data extracted1")
let cell = tableView.dequeueReusableCellWithIdentifier("sportCell") as! SportTableViewCell
print("data extracted")
let sportPost = self.sportCells[indexPath.row]
let user = sportPost["user"] as! PFUser
print("data extracted")
do {
try user.fetchIfNeeded()
print("its happening 3rd time")
} catch _ {
print("There was an error")
}
cell.sportTitle.text = sportPost["basketballTitle"] as? String
cell.sportLogo.text = sportPost["basketballLogo"] as? String
cell.numberOfPOTM.text = "5"
return cell
}
func updateSportsTable() {
let query = PFQuery(className: "Sports")
query.findObjectsInBackgroundWithBlock { (sportCells:[PFObject]?, error:NSError?) -> Void in
if error == nil {
self.tableView.reloadData()
print("its happening again")
}
}
}
As confirmed from the comments, you problem is data population in model sportCells.
Ensure that sportCells is populated properly and that you call self.tableView.reloadData after that.
So this is how I'm retrieving all the data and then added a custom button this way :
import UIKit
class userListTableViewController: UITableViewController {
var data:NSMutableArray = NSMutableArray()
func loadData() {
data.removeAllObjects()
var userQuery = PFUser.query()
userQuery?.orderByAscending("createdAt")
userQuery?.findObjectsInBackgroundWithBlock({ (objects, erroe) -> Void in
if let objects = objects {
for object in objects {
if let user = object as? PFUser {
if user.objectId != PFUser.currentUser()?.objectId {
self.data.addObject(object)
}
}
}
}
self.tableView.reloadData()
})
}
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
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 data.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("users", forIndexPath: indexPath) as! userListTableViewCell
let userData:PFObject = self.data.objectAtIndex(indexPath.row) as! PFObject
// Usernames and gender..
myCell.fullName.text = userData.objectForKey("fullName") as! String!
myCell.genderLabel.text = userData.objectForKey("gender") as! String!
// Profile pictures..
let profilePics = userData.objectForKey("profilePicture") as! PFFile
profilePics.getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.dp.image = downloadedImage
}
}
myCell.followButtton.removeTarget(nil, action: nil, forControlEvents: UIControlEvents.AllEvents)
myCell.followButtton.addTarget(self, action: "followButtonTapped:", forControlEvents: UIControlEvents.TouchUpInside)
return myCell
}
// IBActions..
func followButtonTapped(sender:AnyObject) {
let buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition)
if indexPath != nil {
if let cell = self.tableView.cellForRowAtIndexPath(indexPath!) as? userListTableViewCell {
cell.followButtton.setTitle("unfollow", forState: UIControlState.Normal)
var followers:PFObject = PFObject(className: "Followers")
followers["follower"] = PFUser.currentUser()?.objectId
followers["user"] = //*********************** here i want to save the objectId of the user being tapped on. want to get the NSMutableArray index from the indexPath
}
println(indexPath!)
}
}
my problem is there where you see ************************. now like in cellForRowAtIndexPath I've used this to show the data :
let userData:PFObject = self.data.objectAtIndex(indexPath.row) as! PFObject
same like this i want to do it in func followButton(sender:AnyObject).
You should not call self.tableView.reloadData() in the for loop, you should do that only once at the end of the for loop when all the data is loaded.
self.data.objectAtIndex(indexPath.row) this worked.