Hey I am trying to retrieve the user image saved in the firebase storage but I am using this storage path (the folder of profile pictures in firebase) as a string(child path) to update the user image. When the user profile updates there are no errors this code just didn't update the user image as I expected what am I missing here that will allow me to successfully my user image and solve my problem ?
var spaceRef = Storage.storage().reference()
let storagePath = "gs://tunnel-vision-bc055.appspot.com/images/space.jpg"
spaceRef = Storage.storage().reference(forURL: storagePath)
let reference = spaceRef.child("profilePic")
// UIImageView in your ViewController
let imageView: UIImageView = self.ProfileImage
// Placeholder image
let placeholderImage = UIImage(named: "image/jpeg")
// Load the image using SDWebImage
imageView.sd_setImage(with: reference, placeholderImage: placeholderImage)
// Uh-oh, an error occurred!
return
}
This will not be the answer to all your issues, but hopefully some of them.
First of all, in Swift, variables and constants starts with a lowercase letter. Classes with uppercase. For example, your ProfileImage should be profileImage. For clarity, when I type profileImage I refer to your ProfileImage.
Now, types. You have a constant profileImage in the code you posted. This is of type String. You set the value of the key "ProfileImageUrl" to it. I would change it's name to profileImageURL.
Then (according to one of your comments) you are calling self.profileImage
let imageView: UIImageView = self.profileImage
Since you're not seeing any errors I assume you also have a class property called profileImage of type UIImageView.
The line
// let user = User(ProfileImage: ProfileImage)
will not help you. As far as I understand from the code you posted - and what you are trying to achieve - you may as well delete it. Or comment it (//) as I did above.
What you want to do is to set an imageView's image.
For this you need to do
imageView.image = image
And to be able to do that you need an imageView and an image. If you don't know how to create an imageView, search for answers here on SO.
You can then create the image from the url you get from Firebase and set it to the imageView. Kind of like this
let profileImageURL = value?["ProfileImageUrl"] as? String ?? ""
let url = URL(string: profileImageURL)
DispatchQueue.global().async {
guard let data = Data(contentsOf: url) else {return} // if url is nil, return block is executed and code below is not
DispatchQueue.main.async {
self.imageView.image = UIImage(data: data)
}
}
Related
When the user selects an item from their photo library, the app saves the UIImage to the app's directory using the following code:
let imageUUID = UUID()
let filename = getDocumentsDirectory().appendingPathComponent("\(imageUUID)")
guard let uiImage = newImage else { return}
if let jpegData = uiImage.jpegData(compressionQuality: 0.8) {
try? jpegData.write(to: filename, options: [.atomicWrite, .completeFileProtection])
}
How can I use the saved image in a view?
Thanks!
First, you should save the UUID somewhere so that you can read the file later. This could be in UserDefaults, a JSON file, CoreData, or whatever, depending on your needs.
Suppose you have the path to the file stored in filePath, you can create an Image like this:
Image(uiImage: UIImage(contentsOfFile: filePath) ?? UIImage())
This will use an empty image as fallback if it failed to read the file.
Following code convert UIImage to Image in SwiftUI:
let uiImage = UIImage(contentsOfFile: path) ?? UIImage() // Access it from your storage
let image = Image(uiImage: uiImage)
There are different UIImage initializer methods available, you can use any one of them to get UIImage instance.
https://developer.apple.com/documentation/swiftui/image
You will like this tutorial of Coredata with SwiftUI: https://www.raywenderlich.com/9335365-core-data-with-swiftui-tutorial-getting-started
I have a follow view controller which has a table view controller embedded in it.
When I try to load profile images from the firebase it loads well but keeps on interchanging images with rest of the profile images on scrolling down or up.
Also when I tap the table view cell to follow that particular user the indication (a checkmark) appears on the fourth cell too.
Is this a bug in xcode
I use Xcode 9.1 on Mac os sierra 10.12.6
If you are getting the images from the background, make sure you assign each image to correct cell. One way to do this is to create a custom class that holds an image and an unique id, whenever you want to assign an image to a cell, check the id first to make sure it's the right one.
About the checkmark bug, you can try to reset cell inside the prepareForReuse() function.
EDIT
Since you are using async, nothing guarantees that the images will be returned in order. As a result, to get the right image into the right cell you need to do something like this
//if the image is already fetched, you don't have to get it from firebase again
private var imageCache = [String:UIImage]()
//Create custom ImageView class that downloads image from url
class CustomImageView: UIImageView{
var lastImageURL: String?
//call this function to get the right image with url
func setupWithImageURL(imageURL: String){
self.contentMode = .scaleAspectFill
self.clipsToBounds = true
//keep track of the url of the right image
lastImageURL = imageURL
//check if the image is already there
if let cachedImage = imageCache[imageURL]{
self.image = cachedImage
return
}
//if no image, get it with url
guard let url = URL(string: imageURL) else {return}
URLSession.shared.dataTask(with: url) { (data, response, err) in
if let err = err{
print("Unable to download data from database: ",err)
return
}
guard let data = data else {return}
guard let image = UIImage(data: data) else {return}
imageCache[url.absoluteString] = image
//if not the correct image, return and do nothing
if (url.absoluteString != self.lastImageURL){
return
}
//if the image is the correct one, set it to the imageView
DispatchQueue.main.async {
self.image = image
}
}.resume()
}
}
I'm tyring to learn swift. I have a simple demo project. I have a variable, and its value is a url which points to an image. when I try to print this value (the value of the URL encoded in the variable), it works fine, but when I try to use that same variable's value at runtime, it fails. What should I do?
var picurl : String!
profilePicView.image = UIImage(named: "\(picurl)") // image is not showing with pic url
print("User name --- \(Username)")
print("User picurl --- \(picurl)")// but here value is printed.
Thank you.
if you are fetch the image from URL use this
if let imageUrl = NSURL(string: \(picurl)) {
if let imageData = NSData(contentsOfURL: imageUrl) {
profilePicView.image = UIImage(data: imageData)
}
}
load from locally use this
if let img = UIImage(named: "\(picurl)") {
profilePicView.image = img
}
Looking through the forums I have found that this issue is one that shows its head every now and then. And apparently doing so in a wide scope of different cases. None that I have managed to find seem to be similar to mine though.
I'm halfway through my program (lesson) in creating a usable twitter application. Testing it currently runs the program as it should, without any errors. But when I select an account the program crashes and an error message shows up at the image method which is supposed to load the avatar of the selected user. I assume that it is not able to retrieve a valid image or fetch data at all (because of the line ImageData = (NSDATA?) nil in the debug area), but I am by no means sure of anything, let alone how to or where to find a solution. If I am searching with the wrong keywords then please let me know. (I am searching for exc_bad_instruction and uiimage error) Thanks in advance.
I'll post the snippet of code where the issue presents itself below and what is shown in the debug area below that.
if let cachedImage = image {
cell.tweetUserAvatar.image = cachedImage
}
else {
cell.tweetUserAvatar.image = UIImage(named: "camera.png")
queue?.addOperationWithBlock() {
let imageURL = NSURL(string: imageURLString) as NSURL!
let imageData = NSData(contentsOfURL: imageURL) as NSData?
let image = UIImage(data: imageData!) as UIImage? // EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subode=0x0)
if let downloadedImage = image {
NSOperationQueue.mainQueue().addOperationWithBlock(){
let cell = tableView.cellForRowAtIndexPath(indexPath) as! TweetCell
cell.tweetUserAvatar.image = downloadedImage
}
self.imageCache?.setObject(downloadedImage, forKey: imageURLString)
}
}
}
Debug area:
imageURLString String
"http://pbs.twimg.com/profile_images/465756113825067008/8jH2nZO0_normal.png"
tableView UITableView 0x00007fc52481b400
indexPath NSIndexPath * 0xc000000000000016
self Chapter7_8___Social_App.FeedViewController 0x00007fc5235f5ef0
imageURL NSURL! "http://pbs.twimg.com/profile_images/465756113825067008/8jH2nZO0_normal.png"
imageData NSData? nil None
image UIImage? 0x000000010ee778dd
downloadedImage UIImage
I had this issue as well and found that my image was being initialized with bad data. This is to say that the image I requested from the server did not exist and the server sent back a response which could not be converted into an UIImage.
To mitigate this you can do the following:
if let cachedImage = image {
cell.tweetUserAvatar.image = cachedImage
}
else {
cell.tweetUserAvatar.image = UIImage(named: "camera.png")
queue?.addOperationWithBlock() {
let imageURL = NSURL(string: imageURLString) as NSURL!
let imageData = NSData(contentsOfURL: imageURL) as NSData?
if let image = UIImage(data: imageData!) {
let downloadedImage = image
NSOperationQueue.mainQueue().addOperationWithBlock(){
let cell = tableView.cellForRowAtIndexPath(indexPath) as! TweetCell
cell.tweetUserAvatar.image = downloadedImage
}
self.imageCache?.setObject(downloadedImage, forKey: imageURLString)
}
}
}
What I have done above is changed
let image = UIImage(data: imageData!) as UIImage?
if let downloadedImage = image {
...
...
}
To:
if let image = UIImage(data: imageData!) {
let downloadedImage = image
...
...
}
In this way I have checked that the image was able to be created successfully. If the image is not able to be created then the code will not execute and you will not receive an error.
If you expect an image to be at the url you specified in 'imageURLString' then I would suggest that you check the url you are using.
I also noticed that you did not get any data back which is why you could not create the UIIMage. You can test to see if this is the case with the following:
let imageData = NSData(contentsOfURL: imageURL) as NSData?
if imageData != nil {
Do More Stuff
...
{
I hope my answer was helpful. If you have any questions feel free to leave a comment and I'll do my best to answer them.
More Info Here:
This question & answer also provides methods on how to handle the case when the UIImage cannot be created from the data provide.
I have a very large set of images to upload, and the best way to do that is to let my app do it for me. But after copy and pasting the code from Parse's docs, it doesn't work.
var image = NSData(contentsOfURL: NSURL(string: "XY1_EN_1.jpg")!)!
#IBAction func xyButton1(sender: AnyObject) {
for var i = 1; i < 147; i++ {
let imageData = UIImageJPEGRepresentation(image)
//ERROR on line above: Missing argument for parameter #2 in call
let imageFile = PFFile(name:"image.png", data:imageData)
var userPhoto = PFObject(className:"Cards")
userPhoto["imageName"] = "XY1_EN_1"
userPhoto["imageFile"] = imageFile
userPhoto.save()
}
}
What am I doing wrong?
There are two problems with the code. UIImageJPEGRepresentation(::) takes two parameters, a UIImage and a float. Right now you are calling UIImageJPEGRepresentation(_:) and giving it NSData. If you want to use that method to get NSData from an Image, you need to make self.image of UIImage type instead of NSData. Maybe init your variable image with UIImage(named: "imageName") if the image is bundled.