Guys i was making a simple application using Firebase and i was uploading an image and also downloading it sometime later. Uploading works perfectly well but when i try to download an error occurs that says. Object profile_pics not found. I have created a folder named profile_pics and i store the image inside that folder. The image is there but gives error while downloading. Here is the screen shot.
Here is what is in the console.
Error -: Object profile_pics does not exist.
Here is the code to download the image.
let storage = FIRStorage.storage().reference(forURL: "gs://dd-dd-dd.appspot.com/profile_pics/\(profileURL)")
print("Path Full \(storage.fullPath)")
storage.data(withMaxSize: 11 * 1024 * 1024, completion: {
(data, error) in
if let error = error{
print("Error -: \(error.localizedDescription)")
}
else{
let image = UIImage(data: data!)
cell.profileImageView.image = image
}
})
What could be the possible error? If you please guide me through this.
I recover it this way.
let url = URL(string: "\(ImageUrlSavedinDatabase)")
let task = URLSession.shared.dataTask(with: url!) { data, response, error in
guard let data = data, error == nil else { return }
DispatchQueue.main.sync() {
self.profilepicimageview.image = UIImage(data: data)
self.actIndicator.stopAnimating()
}
}
task.resume()
Does that work?
Niall
Related
I am trying to parse a image from a url the url is
https://a.ppy.sh/9795284
it doesn't have a specific image extension as far as i can tell, it's just a link my current code (which works for getting the username and when I print the user_id i do get 9795284 so I know the code works (I also already get other information I wanted to get since as the username however I can not for the life of me get the users image to show here is my code for dealing with parsing
fetchCoursesJSON { (res) in
switch res {
case .success(let playerinfo):
playerinfo.forEach({ (player) in
print(player.username)
DispatchQueue.main.async {
self.myLabel.text = player.username
self.avatar.image = UIImage(named: "https://a.ppy.sh/\(player.user_id)")
}
})
case .failure(let err):
print("Failed to fetch courses:", err)
}
}
I expected the output to show the users profile pick in the avatar image but it does not it's just blank.
You need to download the image first, you can do this by using a lib like SDWebImage, AlamofireImage, Kingfisher or using the native URLSession
The UIImage(named:) is used when the resource is in your assets.
The UIImage(named:) will attempt to retrieve the image from your app.. not from the internet. Here is some code that will help you retrieve the image from your url:
guard let url = URL(string: yourUrlString ?? "") else { return }
URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
guard let data = data, error == nil else { return }
let image = UIImage(data: data)
DispatchQueue.main.async {
self.avatar.image = image
}
}).resume()
when my app wants to download avatar(profile image) it will crash and show me the Error but my image is not nil But the application detect that its nil here is the Error massage
fatal error: unexpectedly found nil while unwrapping an Optional value
and here is the print of my image Data and image that proves the image is not nil
, {0, 0}
10059 bytes
and here is my codes for downloading Avatar(profile Image)
let avatarUrl = URL(string: "http://example.com/uploads/avatar/\(EmailSignInViewController.avatar)")!
let session = URLSession(configuration: .default)
// Define a download task. The download task will download the contents of the URL as a Data object and then you can do what you wish with that data.
let downloadPicTask = session.dataTask(with: avatarUrl) { (data, response, error) in
// The download has finished.
if let e = error {
print("Error downloading cat picture: \(e)")
} else {
// No errors found.
// It would be weird if we didn't have a response, so check for that too.
if let res = response as? HTTPURLResponse {
print("Downloaded personal picture with response code \(res.statusCode)")
if let imageData = data {
// Finally convert that Data into an image and do what you wish with it.
print(imageData)
print(profileViewController.userImage)
if #available(iOS 10, *) {
profileViewController.userImage = UIImage(data: imageData )!
} else {
profileViewController.userImage = UIImage(named: "user.jpg")!
}
// Do something with your image.
} else {
print("Couldn't get image: Image is nil")
}
}
else {
print("Couldn't get response code for some reason")
}
}
}
downloadPicTask.resume()
For some reason my photoimg will not update consistantly , sometimes it does sometimes it doesn't.
I'm pretty sure it has something to do with async calls but I've been stuck trying to figure out the root reason why its not updating. So this is in my mainVC and for a user to upload/update image they go to the settingsVC and when they segue back sometimes it shows to the updated image, other times still shows the old image , other times showing nothing . But oddly if I click on my settings and dismiss it then the image will show updated.
So I think my issue lies where I'm calling my method and my async queue.
func fetchProfileImage() {
Dataservice.dataService.USERS_REF_CURRENT_PROFILE_IMAGE.downloadURL { (url, error) in
if error != nil {
}
else {
let url = url?.downloadURL
URLSession.shared.dataTask(with: url!, completionHandler: { (data, resonse, error) in
if error != nil {
print("Fetching did not download \(error.debugDescription)")
}
if let data = data {
print("Fetching Image did download data")
DispatchQueue.main.async {
self.profilePhoto.image = UIImage(data: data)
}
}
}).resume()
}
}
}
Why not just use the built in download mechanism, which always presents callbacks on the main thread*:
let image: UIImage!
let ref = FIRStorage.storage().reference(forURL: Dataservice.dataService.USERS_REF_CURRENT_PROFILE_IMAGE)
ref.data(withMaxSize: 1 * 1024 * 1024) { data, error in
if let error = error {
// Uh-oh, an error occurred!
} else {
// Data for your profile image is returned
image = UIImage(data: data!)
}
}
*unless you explicitly change the thread by providing your own queue ;)
after you perform async, you need to back to main thread to set the download image
DispatchQueue.main.async {
DispatchQueue.main.sync {
self.profilePhoto.image = UIImage(data: data)
}
}
I'm downloading a picture from internet and storing its data locally then saving the path in my CoreData, this way:
getDataFromUrl(url!) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? "")
print("Download Finished")
let filename = self.getDocumentsDirectory().stringByAppendingPathComponent(userKey as! String + ".png")
data.writeToFile(filename, atomically: true)
user.setValue(filename, forKey: "avatar")
do {
try managedContext.save()
}
catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
}
The save does seem to work (I debugged by printing the data received and the data inside the file once copied and I don't have any managedContext error).
On the next view, I do use a UITableView and on cellForRowAtIndexPath
let path = authorArray.objectAtIndex(indexPath.row).objectAtIndex(0).objectForKey("avatar")! as! String
let name = authorArray.objectAtIndex(indexPath.row).objectAtIndex(0).objectForKey("name")
do {
let data = try NSData(contentsOfFile: path, options: NSDataReadingOptions())
let image = UIImage(data: data)
cell.profilePicture.image = image
cell.profilePicture.layer.cornerRadius = cell.profilePicture.layer.cornerRadius / 2;
cell.profilePicture.layer.masksToBounds = true;
}
catch {
print("failed pictures")
}
The thing is I get the photo on my cell.profilePicture but as soon as I do any modification elsewhere and relaunch my application from xCode, I get the error message. The pictures path did not change but the datas obtained from it are nil. I can't find a reason why it does work until I update the code. Any solutions to make it work everytime ?
As pbasdf stated on comments, I was storing the whole Document directory path instead of just the filename + extension. Documents directory changes on every build.
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
}
}