Error on displaying image asynchronously with Parse - ios

I'm building app and I need to populate a TableView with some users infos, like username and the profile picture. The following code works for downloading and displaying the image.
if let imageFile = usersArr[indexPath.row]["profileImage"] as? PFFile {
let data = try? imageFile.getData()
cell?.imageView?.image = UIImage(data: data!)
}
But this is synchronously and I want it to be asynchronously. So I tried this.
if let imageFile = usersArr[indexPath.row]["profileImage"] as? PFFile {
imageFile.getDataInBackgroundWithBlock({ (data, error) -> Void in
if let imageData = data where error == nil {
cell?.imageView!.image = UIImage(data: imageData)
} else {
cell?.imageView!.image = UIImage(named: "defaultProfile")
}
})
}
But it's not working and I can't figure out why. Not even the defaultProfile image is appearing.
Any tips?

The issue is that the view is not being refreshed once the data has been fetched and image has been set.
I recommend using PFImageView from the ParseUI framework. It is a Parse-made image view which will automatically handle displaying a placeholder while loading, updating the data once available, and refreshing the view once the download is complete. Here's an example usage.
let imageView = PFImageView()
// Set placeholder image
imageView.image = UIImage(named: "placeholder")
// Set remote image
imageView.file = profilePicture
// Once the download completes, the remote image will be displayed
imageView.loadInBackground { (image: UIImage?, error: NSError?) -> Void in
if (error != nil) {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
} else {
println("image loaded")
}
}

Related

iOS How to fetch profile image for each user use Parse Swift

I have an app in which I have news, which users are added and I want in a table view to show user photo which are taken from DB "_User" and I fetch data from class "news". My code is:
var user = PFUser.current()
let useravatar = user!["profilePicture"] as? PFFile
useravatar?.getDataInBackground{ (imageData, error)in
if imageData != nil {
let image = UIImage(data: imageData!)
cell.userPhoto.image = image
}
}
But this code loads only the current user photo, but I need the user photo for each row, how I can do this? Example:
As you see in pictures I have two user, but it loads only my profile photo.
Load images asynchronously
var user = PFUser.current() //you'e setting an image for same user
let useravatar = user!["profilePicture"] as? PFFile
useravatar?.getDataInBackground{ (imageData, error)in
DispatchQueue.main.async {
if imageData != nil, error == nil {
let image = UIImage(data: imageData!)
cell.userPhoto.image = image
}
}
}

Add an image as an accessory in your UITableView in Swift 3

In my project, I show a UITableView, which currently has text describing a show's name and genre loading from a remote JSON file.
That all works. What I want next is to use the URL from the JSON file and load a thumbnail next to each show.
Using a tutorial, I have added a function to download the remote image with a print to test if it's successful.
if let shows_list = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let shows_obj = shows_list[i] as? NSDictionary
{
let show_name = shows_obj["show"] as? String
let show_genre = shows_obj["genre"] as? String
let show_image = shows_obj["thumbnail"] as? String
TableData.append(show_name! + " | " + show_genre!)
let testPictureURL = URL(string: show_image!)!
let session = URLSession(configuration: .default)
// Here's the download task where I'm grabbing the image
let downloadPicTask = session.dataTask(with: testPictureURL) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
if let res = response as? HTTPURLResponse {
print("Downloaded picture with response code \(res.statusCode)")
if let imageData = data {
// Now I know I have data, so I think I can use UIImage to convert it into an image
let image = UIImage(data: imageData)
} else {
print("Couldn't get image: Image is nil")
}
} else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
}
There are three items in the JSON array, and I get three printed statements that the picture was download: but the image does not appear.
My theory: since this is a table, maybe I have to add this as an accessory, but there isn't an image accessory subclass.
I am new to Swift -- do you have any ideas about how I should append this uploaded image to the table.
This is probably being caused by the asynchronous behavior of URLSession so when the requested image returns the view is already loaded.
To solve that, you can use a callback, for instance:
func myFunction(completion: (returnedImage -> UIIMage) -> Void){
//...
let downloadPicTask = session.dataTask(with: testPictureURL) { (data, response, error) in
//...
let image = UIImage(data: imageData)
completion(returnedImage: image)
//...
}
downloadPicTask.resume()
}
}
By using a callback, let's say that you have a method called myFunction(completion:), so now when you call the method you can handle whatever comes back from completion:
myFunction { (image) in
DispatchQueue.main.async { cell.imageView.image = image }
}

Retrieving an image using CloudKit and Swift

I am new to CloudKit.
I would like to know how I can retrieve from the database only one image. I created a new record type and added a Asset type in it with the name EventsImage. Now I want to retrieve this image and place it in an ImageView I have on my View controller. This is an image of what the View looks like (it is not a tableViewController).
(There is an ImageView in the middle)
Here is a snippet in which I recover an image from my database. I fetch CKRecord using the record ID.
self.publicDatabase.fetch(withRecordID: recordID, completionHandler: { (record: CKRecord?, error: Error?) -> (Void) in
guard let record = record else
{
if let error = error
{
DispatchQueue.main.async
{
completionHandler(SeeYuuResult.error(message: error.localizedDescription))
}
}
return
}
// Here is where the image is recovered
if let asset = record["avatar"] as? CKAsset, let data = try? Data(contentsOf: asset.fileURL)
{
DispatchQueue.main.async
{
avatar_image = UIImage(data: data)
}
}
})

How to download and view images from the new Firebase Storage?

I am able to upload images to Firebase Storage but I am having trouble downloading them. This is my code to download images:
let storage = FIRStorage.storage()
let localURL : NSURL! = NSURL(string: "file:///Documents/co.png")
// i also tried let localURL : NSURL! = NSURL.fileURLWithPath("file:///Documents/co.png")
func download() {
let storageRef = storage.referenceForURL("gs://project-5547819591027666607.appspot.com")
let imageRef = storageRef.child("co.png")
let downloadTask = imageRef.writeToFile(localURL) { (URL, error) -> Void in
if (error != nil) {
print(error?.localizedDescription)
}
else {
self.imageView.image = UIImage(data: data!)
}
}
}
I am receiving - Optional("An unknown error occurred, please check the server response.")
Also once I get them downloaded How would I view that image?
For trying to see if the image was downloaded I created a UIImageView and set an outlet for it in storyboard called "imageView" then set the downloaded image to the UIImageView.
self.imageView.image = UIImage(data: data!)
Try
first getting reference to the image you want to download using
let reference = FIRStorage.storage().reference("uploads/sample.jpg")
If you know the size of image is low - like 1-2 mb max . download the image in memory
reference.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
print(error)
} else {
let myImage: UIImage! = UIImage(data: data!)
}
}
This will be the quickest and easy way to download directly from Firebase Storage.
However there are cases when you want the progress blocks and certain other things like caching. In such cases you could use any third party like Alamofire to download the image from the url you get from Firebase Storage.
To get the url do something like this
reference.downloadURLWithCompletion { (URL, error) -> Void in
if (error != nil) {
// Handle any errors
} else {
print(URL)
// download image using NSURLSession or Alamofire
}
}

Auto Saving a Photo in Parse

I'm building an app that requires the user to have a photo. What I'm trying to do is autosave the placeholder photo until they choose the camera/photo gallery and choose a pick. My problem is that it's not happening. I've used the code from the Parse documentation as well as from my own choose photo source code that works. It still will not automatically save the photo when no photo is detected. I know finding nil and/or data in Parse is complicated. The problem may also be how I'm establishing my photo.image in the first place. If you have ideas on how to get my photo to save when a user doesn't have one please help. Here is my code.....
if let userPicture = PFUser.currentUser()?["userPhoto"] as? PFFile {
userPicture.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if !(error != nil)
{
if imageData != nil
{
self.profileIMG.image = UIImage(data: imageData!)
}
else
{
let image = UIImage(named: "blueplaceholder2.png")
let imageData = UIImageJPEGRepresentation(image!, 0.25)!
let imageFile = PFFile(name:"image.png", data:imageData)
let user = PFUser.currentUser()
user!.setObject(imageFile, forKey: "userPhoto")
user!.saveInBackground()
}
}
}
}

Resources