How to retrieve File from Parse to display on PFQueryTableVIewController? - swift

I'm trying to retrieve users profile pictures(File) from Parse onto my PFQueryTableViewController. I believe I've written my code correctly but I'm probably doing something wrong. So how do I retrieve users images from parse to display on my query?
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?, object: PFObject!) -> PFTableViewCell? {
let cell = tableView!.dequeueReusableCellWithIdentifier("TCell", forIndexPath: indexPath!) as! Tweets
if let userTweet : PFObject = self.tweets.objectAtIndex(indexPath!.row) as! PFObject {
cell.username.text = object["account"] as? String
cell.post.text = object["post"] as? String
cell.post.numberOfLines = 0
if let Pic = object["photo"] as? PFFile {
cell.userImage.image = UIImage(named: "Image")
cell.userImage.file = Pic
}
}

You're not loading the PFFile for one.
if let pic = object["photo"] as? PFFile {
// Make sure your imageView is a PFImageView
let imageView = cell.userImage as! PFImageView
// I assume this is the placeholder image while your load your image files from Parse
imageView.image = UIImage(named: "image.png")
imageView.file = pic
// Load the image file however you see fit
imageView.loadInBackground(nil)
}
As a side note, It's good practice to not capitalize your constants due to the chance they could get confused with class names in your code.

It looks like your code is using a PFImageView, but that the cell subclass is presenting it as a UIImageView so the compiler is complaining. You need to make sure that the image view is properly set and exposed as a PFImageView.

Related

If there is a like button next to each user, why could scrolling trigger random users' like buttons be highlighted?

I use self.like.alpha = 0.5 to grey out the like button next to the user who was liked. Scrolling causes the highlight to sometimes disappear and appear next to other users.
I've used self.like.alpha = 0.5 last various places in the code but it changes nothing.
#IBAction func likePressed(_ sender: Any) {
self.like.alpha = 0.5
let ref = Database.database().reference()
let keyToPost = ref.child("likes").childByAutoId().key
ref.child("humans").child(self.postID).observeSingleEvent(of: .value, with: {(snapshot) in
if let humans = snapshot.value as? [String: AnyObject] {
let updateLikes: [String: Any] = ["humansWhoLike/\(keyToPost)" : Auth.auth().currentUser!.uid]
ref.child("humans").child(self.postID).updateChildValues(updateLikes, withCompletionBlock: { (error, reff) in
if error == nil {
ref.child("humans").child(self.postID).observeSingleEvent(of: .value, with: { (snap) in
if let properties = snap.value as?[String: AnyObject]{
if let likes = properties["humansWhoLike"] as? [String : AnyObject] {
let count = likes.count
let update = ["likes" : count]
ref.child("humans").child(self.postID).updateChildValues(update)
}
}
})
}
})
}
})
ref.removeAllObservers()
}
What I need is for the like button that is clicked to be greyed out. It has to stay greyed out and the greying out should not jump to another user's like button.
/Updated code after 1st answer
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
let like = cell.viewWithTag(3) as! UIButton
let immy = cell.viewWithTag(1) as! UIImageView
let person: Userx = humans[indexPath.row]
cell.lblName.text = person.Education
cell.postID = self.humans[indexPath.row].postID
if let PhotoPosts = person.PhotoPosts {
let url = URL(string: PhotoPosts)
immy.sd_setImage(with: url)
}
return cell
}
Remember that tableView cells are reusable. When you dequeue one, you cannot assume anything about the existing values. If you mark a cell liked (with button formatting), when that cell is reused, the formatting is still there.
When you dequeue a cell in your cellForRowAt function, you need to reset all the values according to your data store.
I am having a little trouble understanding your database design/usage, but based on the code you added to the post:
let currUser = Auth.auth().currentUser!.uid // better to add this as a VC level variable as you will do this lookup a lot.
let likeArray = person.humansWhoLike ?? []
let likeStatus = likeArray.contains(currentUser)
//from your code, 'like' is the button to be formatted
like.alpha = likeStatus ? 0.5 : 1.0

PFFile Image cache in Swift 2.0

I am getting image as PFFile. but when my table is scrolling every time PFFile is downloading and its take time.
I want to cache my file so if its will be downloaded then it will get from cache not from the Parse.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as! RidesCustomCell!
if cell == nil {
cell = RidesCustomCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
}
let currentDic = dataArray.objectAtIndex(indexPath.row) as! NSDictionary
cell.backgroundColor = UIColor.clearColor()
cell.txtName.text = currentDic.valueForKey("firstName") as? String
cell.txtPrice.text = currentDic.valueForKey("price") as? String
cell.txtTime.text = currentDic.valueForKey("date")as? String
cell.txtFrom.text = currentDic.valueForKey("from") as? String
cell.txtTo.text = currentDic.valueForKey("to") as? String
print(currentDic)
cell.imgUser.image = UIImage(named: "noImg.png")
if (currentDic.valueForKey("imageFile") != nil){
// let userImageFile = currentDic.valueForKey("imageFile") as! PFFile
let queue : dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue, { () -> Void in
print(currentDic)
let pfuserGet = currentDic.valueForKey("user") as! PFUser
print(pfuserGet.username)
print(pfuserGet.email)
print(pfuserGet.password)
let userImageFile = pfuserGet.objectForKey("profilePicture") as! PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
cell.imgUser.image = image
}
}
}
})
}
return cell;
}
I had a look at your code. The issue is the PFFile.getDataInBackground() now since you are using dictionaries I would get the PFFile inside your PFQuery block and and store it in the dictionary as UImage() instead of a PFFile.
And all you have to do in the cellForRowAtIndexPath is load the image from the dictionary.
I think this will solve your problem

How do I fix this error"Could not cast value of type 'UIImageView' () to 'PFImageView' " to display images on query?

I'm trying to retrieve users profile pictures(File) from Parse onto my PFQueryTableViewController. The code I've written doesn't give me errors but every time I run my app crashes and says "Could not cast value of type UIImageView to PFImageView. I'm new to coding and don't know what that means. Is there something I have to fix in my code? I just want to retrieve the users image to display on my query.
Here is my code below for my FeedViewController:
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?, object: PFObject!) -> PFTableViewCell? {
let cell = tableView!.dequeueReusableCellWithIdentifier("BubbleCell", forIndexPath: indexPath!) as! Bubbles
if let userPost : PFObject = self.posts.objectAtIndex(indexPath!.row) as! PFObject {
/ if let pic = object["photo"] as? PFFile {
// Make sure your imageView is a PFImageView
let imageView = cell.userImage as! PFImageView
// I assume this is the placeholder image while your load your image files from Parse
imageView.image = UIImage(named: "image.png")
imageView.file = pic
// Load the image file however you see fit
imageView.loadInBackground(nil)
}
Here is my code for my PostViewController:
#IBAction func postPressed(sender: AnyObject) {
let testObj = PFObject(className: "Test")
testObj["photo"] = PFUser.currentUser()?.valueForKey("photo") as! PFFile
testObj.saveInBackgroundWithBlock { (success:Bool, error :NSError?) -> Void in
if error == nil
{
print("***///detail is saved///***")
self.dismissViewControllerAnimated(true, completion: nil)
}
else {
self.alert()
}
}

Parse get data with block not assigning value to variable in scope

Having issues to assign uiImageFile = image!. If It try to assign self.myImage = image! where myImage is a global variable it works.
Is it something possible to be done?
The code is retrieving images ok, also the cell will take an image if pointed directly. Just this bridge that is not working. And it only do not work for the image.
Also the following test line println("TESTSTRING\(indexPath.row)") just above the return is being able to get and print value from testString = "\(indexPath.row)" that is inside getDataInBackgroundWithBlock.
Sorry about the question title. Not sure how to resume the issue in a single sentence.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! HobbieFeedTableViewCell
let object: PFObject = self.timelineData.objectAtIndex(indexPath.row) as! PFObject
var myText = object.objectForKey("postText") as? String
let userImageFile = object.objectForKey("postImage") as? PFFile
var uiImageFile = UIImage()
var testString = String()
println(userImageFile, indexPath.row)
if userImageFile != nil {
userImageFile?.getDataInBackgroundWithBlock({ (imageData:NSData?, error:NSError?) -> Void in
if error == nil {
if let myImageData = imageData {
let image = UIImage(data:myImageData)
self.myImage = image!
uiImageFile = image!
testString = "\(indexPath.row)"
}
}
}, progressBlock: { (percent: Int32) -> Void in
})
}
cell.cellTitle.text = myText
cell.cellImage.image = uiImageFile
// cell.cellImage.image = myImage
println("TESTSTRING\(indexPath.row)")
return cell
}
cell.cellImage.image = uiImageFile
gets executed before uiImageFile has been retrieved. This is because the
getDataInBackgroundWithBlock
returns right away before the retrieval is done.
You can fix it by: (1) Retrieve all images into a local array in the viewDidLoad function (2) Use push notification on completion on retrieval to trigger a tableview.reload

Localization using Core Data

today I read and created around 10 projects related to Core Data. I and finally accomplished what I need but I'm not sure that this approach is very good
I want to change the book title base on the user device lang, I will use
let locale = NSLocale.preferredLanguages()[0] as! String
but first to test the Core Data implementation
Core Data Setup
Source Code
// Get the data from Core Data and change the book title base on the lang
func printBooks(){
let request = NSFetchRequest(entityName: "Langs")
let predicate: NSPredicate = NSPredicate(format: "lang==%#", "fr");
request.returnsObjectsAsFaults = false;
request.predicate = predicate;
let result:NSArray = context.executeFetchRequest(request, error: nil)!;
var frTitle: String!
if(result.count > 0){
for res in result {
let resTmp = res as! NSManagedObject
frTitle = resTmp.valueForKey("langTitle") as! String
}
} else {
println("empty");
}
let requestTwo = NSFetchRequest(entityName: "Book")
requestTwo.returnsObjectsAsFaults = false;
let resultTwo:NSArray = context.executeFetchRequest(requestTwo, error: nil)!;
if(resultTwo.count > 0){
for res in resultTwo {
let resTmpTwo = res as! NSManagedObject
// rename the title
resTmpTwo.setValue(frTitle, forKey: "title");
}
// add to NSArray
entriesArray = resultTwo;
} else {
println("empty two");
}
}
// Adds the new book with the fr version
func insertBook(){
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context: NSManagedObjectContext = appDel.managedObjectContext!
let newBook = NSEntityDescription.insertNewObjectForEntityForName("Book", inManagedObjectContext: context) as! DB.Book
newBook.setValue("Sir Arthur Conan Doyle", forKey: "author")
newBook.setValue("Sherlock Holmes", forKey: "title")
let newLang = NSEntityDescription.insertNewObjectForEntityForName("Langs", inManagedObjectContext: context) as! DB.Langs
newLang.setValue("fr", forKey: "lang")
newLang.setValue("Sherlock Holmes fr - test", forKey: "langTitle")
newBook.setValue(newLang, forKey: "lanBook")
context.save(nil)
println("Saved");
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.entriesArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell_one", forIndexPath: indexPath) as! UITableViewCell
let db = entriesArray[indexPath.row] as! NSManagedObject
// result in the UITableView is: Sherlock Holmes fr - test
cell.textLabel?.text = db.valueForKey("title") as? String
return cell
}
The code does change the book title, but it can be done much better. I'm not sure how this will be done with large numbers of books.
Anyone who knows how it must be done, pleace be so kind to take a moment of your time and answer with some code :)
Also excuse my bad english..
You should think of implementing a transient property say 'langSpecificTitle' on your NSObjectModel, that would compute this for you from your actual'title' property. Ideally to access localised title, you should access this property and it should get a language specific title by reading the actual 'title' property.
This tutorial explains 'transient' properties well.
Also see this from Apple documentation
Hope this helps.