I'm retrieving set of images from Parse, using the following code using Swift.
var imageResources : Array<UIImage> = []
override func viewDidLoad(){
super.viewDidLoad()
self.loadImages()
}
func loadImages(){
var query = PFQuery(className: "Images")
query.orderByDescending("objectId")
query.findObjectsInBackgroundWithBlock ({(objects:[AnyObject]!, error: NSError!) in
if(error == nil){
for object : PFObject! in objects as [PFObject] {
var thumbNail = PFFile()
thumbNail = object["image"] as PFFile
println("thumNail \(thumbNail)")
thumbNail.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) in
if (error == nil) {
let image : UIImage = UIImage(data:imageData)
//image object implementation
self.imageResources.append(image)
}
})//getDataInBackgroundWithBlock - end
}//for - end
}
else{
println("Error in retrieving \(error)")
}
})//findObjectsInBackgroundWithblock - end
}
My Parse Class detail
class name - Images
When I run this function, it's getting crashed without a message in the console.
Note: I'm able to get the collection of PFFile objects in the callback.
I've replaced
"thumbNail.getDataInBackgroundWithBlock({...." block with the synchronous function call thumbNail.getData() like
"var imageData= thumbNail.getData()
var image = UIImage(data:imageData)"
Then the error says
Warning: A long-running operation is being executed on the main thread.
Break on warnBlockingOperationOnMainThread() to debug.
So, I reverted to thumbNail.getDataInBackGroundWithBloack({...
But now, there is no error display in the console, as it happens before. Is there anything wrong in my approach please let me know.
Any help would be appreciated...!
I managed to recreate the error, which seems to be some kind of memory leak / zombie on a PFObject. I'm not sure exactly why, but refactoring your code in the following manner got rid of the error in my case:
func loadImages() {
var query = PFQuery(className: "Images")
query.orderByDescending("objectId")
query.findObjectsInBackgroundWithBlock ({(objects:[AnyObject]!, error: NSError!) in
if(error == nil){
self.getImageData(objects as [PFObject])
}
else{
println("Error in retrieving \(error)")
}
})//findObjectsInBackgroundWithblock - end
}
func getImageData(objects: [PFObject]) {
for object in objects {
let thumbNail = object["image"] as PFFile
println(thumbNail)
thumbNail.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
let image = UIImage(data:imageData)
//image object implementation
self.imageResources.append(image)
println(image)
}
})//getDataInBackgroundWithBlock - end
}//for - end
}
EDIT: Incidentally, this also works:
func loadImages() {
var query = PFQuery(className: "Images")
query.orderByDescending("objectId")
query.findObjectsInBackgroundWithBlock ({(objects:[AnyObject]!, error: NSError!) in
if(error == nil){
let imageObjects = objects as [PFObject]
for object in objects {
let thumbNail = object["image"] as PFFile
thumbNail.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
let image = UIImage(data:imageData)
//image object implementation
self.imageResources.append(image)
println(image)
}
})//getDataInBackgroundWithBlock - end
}//for - end
}
else{
println("Error in retrieving \(error)")
}
})//findObjectsInBackgroundWithblock - end
}
This would indicate that the error was due to the following line:
for object : PFObject! in objects as [PFObject] {
Rewriting that line as follows:
for object : PFObject in objects as [PFObject] {
Also removes the error. So the reason for this error seems to be that that you told the program to unwrap something that wasn't an optional.
Related
How do i convert an PFFile to an UIImage with swift?
In this code, the app is getting the file from parse and now i want it to show on a UIImageView, But i get an error...
Here is my code...
var ImageArray:UIImage = [UIImage]()
var textArray:String = [String]()
var query = PFQuery(className:"ClassName")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
//this works fine
self.textArray.append(object.valueForKey("Image")! as! String)
//this does not work...
self.ImageArray.append(object.valueForKey("Image")! as! PFFile)
//I get an error that says PFFile is not convertible to UIImage. How do i convert it?
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
PFFile is a parse representation of anykind of file. To get the "real" file (image), you need to call getDataInBackgroundWithBlock. Try it:
if let userPicture = object.valueForKey("Image")! as! PFFile {
userPicture.getDataInBackgroundWithBlock({
(imageData: NSData!, error NSError!) -> Void in
if (error == nil) {
let image = UIImage(data:imageData)
self.ImageArray.append(image)
}
})
}
Swift 1.2+ Version
if let userPicture = PFUser.currentUser()!.valueForKey("Image") as? PFFile {
userPicture.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let image = UIImage(data:imageData!)
self.ImageArray.append(image)
}else{
print("Error: \(error)")
}
}
}
With Swift 3 on Parse.
if let photo = obj.file as? PFFile {
photo.getDataInBackground(block: {
PFDataResultBlock in
if PFDataResultBlock.1 == nil {//PFDataResultBlock.1 is Error
if let image = UIImage(data:PFDataResultBlock.0!){
//PFDataResultBlock.0 is Data
photoCell.attachedPicture.image = image
}
}
})
}
Hi I have a PFQuery where I am retrieving map images and I need to sort them so that i can retrieve the correct image in my code. This is currently my code:
func retrieveImages() {
self.imageArray = [UIImage]()
var query = PFQuery(className:"Maps")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
self.objectNames.append(object["Name"]!)
let userImageFile = object["imageFile"] as! PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if imageData != nil {
let imageData = imageData
var image = UIImage(data:imageData!)
if image != nil {
self.imageArray.append(image!)
}
}
}
}
}
}
}
}
}
I tried to sort the query by using the orderByDescending function but when i run the code only the names of the objects are sorted and the images themselves are not. There also seems to be no pattern in how the images are sorted because each time I run this code the order of the images are different. Any advice or insight would be appreciated.
I am getting a fatal error: unexpectedly found nil while unwrapping an optional value. I get this error after the code gets to self.imageArray.append(image!) from this code:
func retrieveImages()
{
var query = PFQuery(className: "Maps")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil && objects != nil {
let objects = objects as! [PFObject]
for object in objects {
let imageFile = object["imageFile"] as! PFFile
imageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if imageData != nil {
let imageData:NSData! = imageData
let image = UIImage(data: imageData)
self.imageArray.append(image!)
}
}
}
}
}
}
}
I have checked each line of code and image does not become nil until i try to append it to the end of the imageArray.
like previous mentioned, you are reassigning a lot of variables. Try you if-let statements on the optional variables like this:
func retrieveImages(){
var query = PFQuery(className: "Maps")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) in
if let objects = objects as? [PFObject] where error == nil {
for object in objects {
if let imageFile = object["imageFile"] as? PFFile {
imageFile.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) in
if let imageData = imageData, let image = UIImage(data: imageData) {
self.imageArray.append(image)
}
}
}
}
}
}
}
I am trying to display an image from parse using swift. This is my code:
var query = PFQuery(className: "Maps")
query.getObjectInBackgroundWithId("1234asdf3456") {
(object: PFObject?, error: NSError?) -> Void in
if error == nil
{
println(object)
var objectAsPF = object as PFObject!
let file = objectAsPF["imageFile"] as! PFFile
file.getDataInBackgroundWithBlock {
(imageData:NSData?, error:NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let map:UIImage = UIImage(data: imageData)!
self.MapView.image = map
println("success")
}
}
}
}
else
{
println(error)
}
}
I set a breakpoint at println("success") and i checked the variable values and everything is fine until i try to convert imageData to UIImage. Any tips?
Use this code to retrieve images from parse then convert it from a PFFile to a UIImage...
var query = PFQuery(className:"Maps")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
self.scored = objects!.count
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
let userImageFile = object["imageFile"] as! PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
if image != nil {
self.imageArray.append(image!)
}
}
}
}
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
dispatch_async(dispatch_get_main_queue()) {
println("Finished Loading Image")
}
All,
I have a simple class in the parse backend - which feeds a uitableview. The data is stored in Arrays. I guess because all parse data is done in the background sometimes data gets downloaded before others. I have a very mixed up tableview. With images in the wrong cell etc. Also the custom cells are sometimes not showing up at all and I need to do a refresh.
Here is my code that I used to download all the data from parse and add into the arrays.
Can you have a look please and suggest a way to do this.
Also how can I add a placeholder image , before the original image comes up.
Also this code is in my ViewDidLoad, would it be better in an earlier function, hopefully so i don't have to relsoaddata on the tableview..
var query = PFQuery(className:"TableViewData")
query.includeKey("EventLoc")
query.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
for object in objects {
let thumbNail = object["backgroundImage"] as PFFile
thumbNail.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
dispatch_async(dispatch_get_main_queue()) {
let image = UIImage(data:imageData)
self.CellBackgroundImage.append(image!)
}
}
})
var VenueLocation = object["EventLoc"] as PFObject!
VenueLocation.fetchIfNeededInBackgroundWithBlock {
(VenueLocation: PFObject!, error: NSError!) -> Void in
dispatch_async(dispatch_get_main_queue()) {
let VenueLocationTitle = VenueLocation["EventLocation"] as NSString
self.EventLocationArray.append(VenueLocationTitle)
}
}
let eventiconimage = object["EventIcon"] as PFFile
eventiconimage.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
dispatch_async(dispatch_get_main_queue()) {
let image = UIImage(data:imageData)
self.EventIconImageArray.append(image!)
}
}
})
dispatch_async(dispatch_get_main_queue()) {
self.TitleArray.append(object["EventTitle"] as String)
self.EventPriceArray.append(object["EventPrice"] as String)
self.EventStartDate.append(object["EventStartDate"] as NSDate)
self.EventEndDate.append(object["EventEndDate"] as NSDate)
self.tableView.reloadData()
}
You need to use serial queue then your array data will be in order. Whats happening because of concurrent task the data is not appended in order
var backgroundQueue:dispatch_queue_t = dispatch_queue_create("SerialQueue", DISPATCH_QUEUE_SERIAL)
var query = PFQuery(className:"TableViewData")
query.includeKey("EventLoc")
query.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
for object in objects {
dispatch_async(backgroundQueue, { () -> () in
let thumbNail = object["backgroundImage"] as PFFile
thumbNail.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
dispatch_async(dispatch_get_main_queue()) {
let image = UIImage(data:imageData)
self.CellBackgroundImage.append(image!)
}
}
})
var VenueLocation = object["EventLoc"] as PFObject!
VenueLocation.fetchIfNeededInBackgroundWithBlock {
(VenueLocation: PFObject!, error: NSError!) -> Void in
dispatch_async(dispatch_get_main_queue()) {
let VenueLocationTitle = VenueLocation["EventLocation"] as NSString
self.EventLocationArray.append(VenueLocationTitle)
}
}
let eventiconimage = object["EventIcon"] as PFFile
eventiconimage.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
dispatch_async(dispatch_get_main_queue()) {
let image = UIImage(data:imageData)
self.EventIconImageArray.append(image!)
}
}
})
dispatch_async(dispatch_get_main_queue()) {
self.TitleArray.append(object["EventTitle"] as String)
self.EventPriceArray.append(object["EventPrice"] as String)
self.EventStartDate.append(object["EventStartDate"] as NSDate)
self.EventEndDate.append(object["EventEndDate"] as NSDate)
self.tableView.reloadData()
}
});
}
}