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")
}
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
}
}
})
}
So I am saving some objects to the localDatastore using parse.
//Pin the objects here!!
var imageObject = PFObject(className: "img")
imageObject["theFile"] = imageFile
imageObject.pinInBackgroundWithBlock({ (success, error) -> Void in
if error == nil {
imageObject.saveEventually()
println("object pinned in background")
} else {
println(error)
}
})
Then in the viewDidLoad I am querying the objects and appending them into an array of PFFile's
var query = PFQuery(className: "img")
query.fromLocalDatastore()
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil{
var objects : AnyObject = objects as! AnyObject
for object in objects as! [AnyObject]{
self.testImages.append(object["theFile"] as! PFFile)
}
} else {
println(error)
}
}
With this array now containing data. I am trying to insert the images into the tableView
if testImages.count >= 1{
testImages[indexPath.row].getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil{
//The app crashes here ~ fatal error: unexpectedly found nil while unwrapping an Optional value
cell.theImage.image = UIImage(data: imageData!)
} else {
println(error)
}
})
}
Because you are using a tableview, I think the best way is to download all the images from Parse and save it to an array. Then in the cellForRowAtPath method then you assign each index of that array to the cell.imageView.image
var query = PFQuery(className:"img")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil
{
if let objects = objects as? [PFObject]
{
for one in objects
{
var pictureImage = one["theFile"] as! PFFile
pictureImage.getDataInBackgroundWithBlock({ (dataToget:NSData?, error:NSError?) -> Void in
if error == nil
{
if let Image = UIImage(data: dataToget)
{
// save the image to array
// reload the tableview
}
}
})
}
}
}
}
I am attempting to fetch data from parse.com into my custom cell which is full of strings and images. I believe I am either retrieving my PFFile incorrectly from parse.com or I am retrieving the PFFile correctly but converting the file to UIImage improperly. The error i am receiving is going on within the loadData() function. It reads as follows: could not find an overload for 'init' that accepts the supplied arguments
Information
//Used to set custom cell
class Information {
var partyName = ""
var promoterName = ""
var partyCost = ""
var flyerImage: UIImage
var promoterImage: UIImage
init(partyName: String, promoterName: String, partyCost: String, flyerImage: UIImage, promoterImage: UIImage) {
self.partyName = partyName
self.promoterName = promoterName
self.partyCost = partyCost
self.flyerImage = flyerImage
self.promoterImage = promoterImage
}
}
Parse fetch function
func loadData() {
var findDataParse:PFQuery = PFQuery(className: "flyerDataFetch")
findDataParse.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]?, error: NSError?) -> Void in
if (error == nil) {
for object in objects! {
var eventImage0 : UIImage
var eventImage10 : UIImage
let userImageFile = object["partyFlyerImage"] as! PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let eventImage = UIImage(data:imageData!)
eventImage0 = eventImage!
}
}
let userImageFile1 = object["partyPromoterImage"] as! PFFile
userImageFile1.getDataInBackgroundWithBlock {
(imageData1: NSData?, error1: NSError?) -> Void in
if error1 == nil {
let eventImage1 = UIImage(data:imageData1!)
eventImage10 = eventImage1!
}
}
//Error below
var party1 = Information(partyName: (object["partyName"] as? String)!, promoterName: (object["partyPromoterName"] as? String)!,partyCost: (object["partyCost"] as? String)!, flyerImage: UIImage(data: eventImage0)!, promoterImage: UIImage(data: eventImage10)!)
self.arrayOfParties.append(party1)
}
}
self.tableView.reloadData()
}
}
You are fetching data from Parse in background, but processing on main thread. Try this:
func loadData() {
var findDataParse:PFQuery = PFQuery(className: "flyerDataFetch")
findDataParse.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]?, error: NSError?) -> Void in
if (error == nil) {
for object in objects! {
var eventImage0 : UIImage
var eventImage10 : UIImage
let userImageFile = object["partyFlyerImage"] as! PFFile
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let eventImage = UIImage(data:imageData!)
eventImage0 = eventImage!
let userImageFile1 = object["partyPromoterImage"] as! PFFile
userImageFile1.getDataInBackgroundWithBlock {
(imageData1: NSData?, error1: NSError?) -> Void in
if error1 == nil {
let eventImage1 = UIImage(data:imageData1!)
eventImage10 = eventImage1!
var party1 = Information(partyName: (object["partyName"] as? String)!, promoterName: (object["partyPromoterName"] as? String)!, partyCost: (object["partyCost"] as? String)!, flyerImage: UIImage(data: eventImage0)!, promoterImage: UIImage(data: eventImage10)!)
self.arrayOfParties.append(party1)
}
}
}
}
}
}
self.tableView.reloadData()
}
}
Your fetching your images Asynchronously and creating your Information cell Synchronously. So when you create the cell, the images are likely not loaded and your are in effect sending nil to the constructor for the cell.
In the following code you are retrieving the image data async:
userImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let eventImage = UIImage(data:imageData!)
eventImage0 = eventImage!
}
}
So when you assign the image data to eventImage0, the call to the Information cell initializer has probably already happened.
You need to modify the code to instead of passing the image into the cell view initializer, allow you to access the UIImageview from the Information cell, so that when the background image loads complete you can simply set the loaded image into that UI/PF/ImageView.
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 attempting to check if a PFFile has data before it attempts to pull the image from the background. I am attempting this because I keep getting a fatal crash if you try and open one of the objects and there is no image! My problem is that I can't get the data check to work. PFFile != nil does not work and you can't check if it exists with if (recipeImageData) because PFFile does not conform to the boolean protocol. Any help would be appreciated!
Here is the declaration of the variable:
var recipeImageData: PFFile = PFFile()
And here is the function for fetching the data:
override func viewWillAppear(animated: Bool) {
navItem.title = recipeObject["Name"] as? String
recipeImageData = recipeObject["Image"] as PFFile //Fatally crashes on this line
// Fetch the image from the background
if (recipeImageData) {
recipeImageData.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
self.recipeImage.image = UIImage(data: imageData)?
} else {
println("Error: \(error.description)")
}
})
}
}
EDIT:
I just tried this seeing that I probably am making a check in the wrong area. Here is my updated code.
override func viewWillAppear(animated: Bool) {
navItem.title = recipeObject["Name"] as? String
if let recipeImageData = recipeObject["Image"] as? PFFile {
// Fetch the image in the background
recipeImageData.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
self.recipeImage.image = UIImage(data: imageData)?
} else {
println("Error: \(error.description)")
}
})
}
}
This check actually works just fine, there was another issue that was causing the crash. The correct code is posted below:
override func viewWillAppear(animated: Bool) {
navItem.title = recipeObject["Name"] as? String
if let recipeImageData = recipeObject["Image"] as? PFFile {
// Fetch the image in the background
recipeImageData.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if error == nil {
self.recipeImage.image = UIImage(data: imageData)?
} else {
println("Error: \(error.description)")
}
})
}
}