Getting images from parse on correct order - swift

I'm trying to get some strings and one photo from parse.com for tableview. I have an NSObject for this class and also an array of object to store them. I can get the newsTitle and the newsDetail in correct order by got fail when try to get newsPhoto. I suppose it lost its order when try get get images in block. Does anybody know what should I change on below code to fix it?
func getNews(){
let query = PFQuery(className: "bulletinOnParse")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(allNews: [PFObject]?, error: NSError?) -> Void in
if error == nil {
var duyuru:News
for news in allNews! {
duyuru = News()
let nTitle = news.objectForKey("title") as! String
duyuru.newsTitle = nTitle
let nDetail = news.objectForKey("comment") as! String
duyuru.newsDetail = nDetail
let imageFile = news["newsphoto"] as! PFFile
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
duyuru.newsPhoto = image!
}
}
}
self.bulletin += [duyuru]
}
} else {
// Log details of the failure
print("\(error!.userInfo)")
}
self.tableView.reloadData()
}
}
And cellForRowAtIndexPath method below
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! DuyuruTableViewCell
self.tableView.rowHeight = 100
let cellInfo = bulletin[indexPath.row]
cell.newsTitle.text = cellInfo.newsTitle
cell.news.text = cellInfo.newsDetail
dispatch_async(dispatch_get_main_queue(), {
cell.newsPhoto.image = cellInfo.newsPhoto
})
return cell
}

Here is the answer of how I solve the problem;
First I created an image array from PFFile object
var resultUserImageFiles = [PFFile]()
Then I get the name and add the array on getNews() method
self.resultUserImageFiles.append(news.objectForKey("newsphoto") as! PFFile)
And I get each photo for cell on below method in cellForRowAtIndexPath method.
self.resultUserImageFiles[indexPath.row].getDataInBackgroundWithBlock { (imageData: NSData?, error:NSError?) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
cell.newsPhoto.image = image
}
}

Related

Can any one help me to solve this error using Swift

would you please help me to solve this error .I'am trying to download an Image From Firebase Database, this is my code and I put a snapshot for the error . ThanksThis is a snapshot for the error in Xcode
import UIKit
import FirebaseDatabase
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var ref:FIRDatabaseReference?
var Handle:FIRDatabaseHandle?
var myClass = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
ref=FIRDatabase.database().reference()
Handle = ref?.child("Posts").observe(.childAdded, with: { (snapshot) in
let post = snapshot.valueInExportFormat()
for url in post! as! [Post] { // Error Here
self.myClass.append(url)
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return myClass.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)as? TableViewCell{
cell.MyImage.alpha = 0
cell.textLabel?.text = PostData[indexPath.row]
DispatchQueue.main.async(execute: {
let imgurl = URL(string : self.myClass [(indexPath as NSIndexPath).row].url)
let imgdata = NSData(contentsOf: imgurl!)
cell.MyImage.image = UIImage(data: imgdata as! Data)
UIView.animate(withDuration: 0.5, animations: {
cell.MyImage.alpha = 1
})
})
return cell
} else {
let cell = TableViewCell()
DispatchQueue.main.async(execute: {
let imgurl = URL(string : self.myClass [(indexPath as NSIndexPath).row].url)
let imgdata = NSData(contentsOf: imgurl!)
cell.MyImage.image = UIImage(data: imgdata as! Data)
})
return cell
}
}
}
})
}
Sometimes simple is the way to go.
assume you have a Firebase structure
Planets
planet_4
some_text = "My post about Mars"
image_url = "images/mars.jpg"
planet_2
some_text = "My post about Venus"
image_url = "images/venus.jpg"
and suppose we want to load each text and image and display in a tableview. We can do it one of two ways, one at a time with .childAdded or all at once with .value. In this example, we'll walk through them one at a time.
let planetsRef = myRootRef.child("Planets")
planetsRef.observe(.childAdded, with: { snapshot in
let dict = snapshot.value as! [String: AnyObject]
let text = dict["text"]
let imageUrl = dict["image_url"]
// Create a reference to the file you want to download
let planetRef = storageRef.child(imageUrl) //storageRef is defined elsewhere
// Download in memory with a maximum allowed size
// of 1MB (1 * 1024 * 1024 bytes)
planetRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
// Got an error so handle it
} else {
// Data for "images/some planet.jpg" is returned
// let planetImage: UIImage! = UIImage(data: data!)
// then add the text and the image to your dataSource array
// and reload your tableview.
}
})
})
This is not tested but will provide the general idea
Maybe you want:
for url in post! {
var wrappedPost = Post()
wrappedPost.url = url
... use wrappedPost for whatever you need a Post object for
}

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

Swift - Parse PFQueryTableViewController Error on loading the LocalDataStore

Good day! I'm using Parse in my swift project, Now my problem is loading and saving the query or objects to the localDataStore, I tried this method
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as CustomPFTableViewCell!
if cell == nil {
cell = CustomPFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
}
// Extract values from the PFObject to display in the table cell
if let placeName = object?["placeName"] as? String {
cell.cellName.text = placeName
}
if let station = object?["station"] as? String {
cell.cellDetail.text = station
}
if let placeImg = object?["placeImg"] as? String {
let decodedData = NSData(base64EncodedString: placeImg, options: NSDataBase64DecodingOptions(rawValue: 0))
// var decodedimage = UIImage(data: decodedData!)
var finImage = UIImage(data: decodedData!)
cell.cellBgImg.image = finImage
}
PFObject.pinAllInBackground(self.objects, block: { (succeeded, error) -> Void in
if (error == nil) {
}else {
println(error!.userInfo)
}
})
return cell
}
now in my queryForTable method i have this
override func queryForTable() -> PFQuery {
// Start the query object
var query = PFQuery(className: "Places")
// Add a where clause if there is a search criteria
if searchBar.text != "" {
query.whereKey("filterKeyword", containsString: searchBar.text.lowercaseString)
}
// Order the results
query.orderByAscending("placeName")
var cReturn = PFQuery()
if (IJReachability.isConnectedToNetwork()) {
cReturn = query
} else {
cReturn = query.fromLocalDatastore()
}
return cReturn
}
As you can see, I'm using Reachability to check if the device is connected to the internet. If not, The query will return query.fromLocalDataStore and if the device is connected it will return the normal query to get the latest data.
Now, my problem is when I'm turning off the internet to test it, it gives me an error 'Method requires Pinning enabled.' which i already did in tableView method
PFObject.pinAllInBackground(self.objects, block: { (succeeded, error) -> Void in
if (error == nil) {
}else {
println(error!.userInfo)
}
})
What do you think I did wrong? Thanks!
I think you should put the method where you pin the objects inside your objectsDidLoad() method and not in your cellForRowAtindexPath() method.