How to update friends image like whatsApp with Firebase - swift

Im working on a chat app using Firebase for storage and the realTime DB.
I have an userFriends tree in my DB where each user get his list of friends:
I have in storage each users profil photo , whats the best way/logic to download photos of the user's friends (to a local File with NSUrl/ in memory with NSData/ generate an URL) ,and more important to be updated if a friend modify his photo?
thanks for your help!

For storing the image
Parameters
infoOnThePicture:- info of the picture that you send from the UIImagePicker
completionBlock:- call when the uploading is complete
func profilePictureUploading(infoOnThePicture : [String : AnyObject],completionBlock : (()->Void)) {
if let referenceUrl = infoOnThePicture[UIImagePickerControllerReferenceURL] {
print(referenceUrl)
let assets = PHAsset.fetchAssetsWithALAssetURLs([referenceUrl as! NSURL], options: nil)
print(assets)
let asset = assets.firstObject
print(asset)
asset?.requestContentEditingInputWithOptions(nil, completionHandler: { (ContentEditingInput, infoOfThePicture) in
let imageFile = ContentEditingInput?.fullSizeImageURL
print("imagefile : \(imageFile)")
let filePath = FIRAuth.auth()!.currentUser!.uid + "/\(Int(NSDate.timeIntervalSinceReferenceDate() * 1000))/\(imageFile!.lastPathComponent!)"
//Creating a unique path for the image in FIRStorage
print("filePath : \(filePath)")
//Storing under the parent Node `ProfilePictures` in FIRStorage FIRControllerClass.storageRef.child("ProfilePictures").child(filePath).putFile(imageFile!, metadata: nil, completion: {
(metadata, error) in
if error != nil{
print("error in uploading image : \(error)")
//Show alert
}
else{
print("metadata in : \(metadata!)")
print(metadata?.downloadURL())
print("The pic has been uploaded")
print("download url : \(metadata?.downloadURL())")
self.uploadSuccess(metadata!, storagePath: filePath)
completionBlock()
}
})
})
}else{
print("No reference URL found!")
}
}
//Storing the filepath to NSUserDefaults
//Much better option would be to store the pictures filePath or storagePath in the FIREBASE DATABASE ITSELF WITH THE USERS DETAILS
//And retrieve that storagePath every time you wanna download the image(much sound option)
func uploadSuccess(metadata : FIRStorageMetadata , storagePath : String)
{
print("upload succeded!")
print(storagePath)
NSUserDefaults.standardUserDefaults().setObject(storagePath, forKey: "storagePath.\((FIRAuth.auth()?.currentUser?.uid)!)")
NSUserDefaults.standardUserDefaults().synchronize()
}
For retrieving the image
Parameters :-
UID:- userId
completion :- completionBlock for handling the completion for retrieval of your image
func retrieveStorageForUID( UID : String, completion : ((image : UIImage) -> Void) ){
print("initial storage")
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentDirectory = paths[0]
let filePath = "file:\(documentDirectory)/\(UID).jpg"
let filePath1 = "\(documentDirectory)/\(UID).jpg"
print(filePath)
print(filePath1)
//Again i am retrieving the storagePath from the NSUserDefaults but you can retrieve it from Firebase database if you stored it while uploading.
if let storagePath = NSUserDefaults.standardUserDefaults().objectForKey("storagePath.\(UID)") as? String {
print(storagePath)
FIRControllerClass.storageRef.child("ProfilePictures").child(storagePath).writeToFile(NSURL.init(string: filePath)!, completion: {(url, err) -> Void in
if err != nil{
self.delegate.firShowAlert("Error downloading", Message: "There was an error downloading your profile picture")
}else{
if let downloadedImage = UIImage(contentsOfFile: filePath1){
print("DOWNLOADED IMAGE :\(downloadedImage)")
self.profilePicture = downloadedImage
completion(image : self.profilePicture)
}
}
})
}else{
completion(image: UIImage(named: "defaultProfilePic")!)
//Default profile pic or Placeholder picture if there is no picture from the user...which you can also download from the FIRStorage..think
}
}
As for checking when your friends change their profile picture, you will replace users pic in the storage when user changes its profile pic, and store its link in the DB, and for knowing when did the user changed its profile pic, Use .observeEventType(.ChildChanged,.. which will notify you of the change at that location, and then update your UI asynchronously through dispatch_
PS:- Refer to the official sample example's of Firebase, You are looking for authentication in this project :https://github.com/firebase/quickstart-ios

Related

Using Firebase Storage for Uploading Images

I can only upload a single photo to FirebaseStorage.
All the tutorials I have seen on youtube use FirebaseStorage to save user's profile pictures. However, I am trying to make a restaurant app where I should be able to keep several pictures and not only one. My code right now only allows me to keep one. As soon as I try to upload a second image, it erases the first one.
Here's my code:
#IBAction func agregarComidaFav(_ sender: Any) {
guard let imageData = imagen?.jpegData(compressionQuality: 0.4) else {
return
}
let storageRef = Storage.storage().reference(forURL: "gs://comidas-68043.appspot.com")
let storageProfileRef = storageRef.child("ComidasFavoritas")
let metadata = StorageMetadata()
metadata.contentType = "image/png"
storageRef.child("comidasFavoritas/png").putData(imageData, metadata: metadata) { (storageMetaData, error) in
if error != nil {
print(error?.localizedDescription ?? "")
return
}
}
storageProfileRef.downloadURL(completion: { (url, error) in
if let metaImageUrl = url?.absoluteString {
print(metaImageUrl)
self.imagenURL = metaImageUrl
}
})
var ref: DocumentReference? = nil
ref = db.collection("comidasFavoritas").addDocument(data: [
"imagenURL" : imagenURL
]) { err in
if let err = err {
print("Error agregando comida: \(err)")
} else {
let id = ref!.documentID
print("Comida agregado con ID: \(id)")
}
}
}
This line:
storageRef.child("comidasFavoritas/png").putData(...)
...guarantees that each time, the data is going to be written to "comidasFavoritas/png"
I don't know anything about how you're keeping track of your data/images in your app, but you'll probably need some way to keep track of an ID for that image. Then, when you store it, you could store it like:
storageRef.child("comidasFavoritas/png\(imageId)").putData(...)
You'd probably also want to store that ID in your database when you store the image URL.

Swift : My files in Firebase Storage wouldn't be deleted

I've got an application which allow user to save some picture on firebase Storage.
I'm trying to allow user to delete this files from the app, and so also to delete it from the storage.
My code :
if let user = Auth.auth().currentUser{
// user is connect
let storRef = Storage.storage().reference()
let userID = Auth.auth().currentUser?.uid
storRef.child("Planes").child(userID!).child(dataME[indexPath.row].image).delete(completion: nil)
self.tableView.reloadData()
dataME.remove(at: indexPath.row)
}else{
fatalError("⛔️ error ...")
}
Now in this case the line in my tableView is totally deleted with the other part of my code the database references is also deleted but the storage doesn't erase the picture ... Why ?
Thank's a lot for your help
Check if you get error when you delete storage
let storageRef = Storage.storage().reference().child("Planes").child(userID!).child(dataME[indexPath.row].image)
storageRef.delete { (error) in
if error != nil{
print(error)
return
}
// else proceed
}
You should not search by image.
Instead try using download URL that firebase supply
you can get the URL from the firebase dashboard by clicking on storage and than clicking on the current image, there you can see the download image.
when you upload an image it returns callback with URL, you have to save the URL on your data structure
upload image example:
func uploadImagePic(img1 :UIImage){
var data = NSData()
data = UIImageJPEGRepresentation(img1!, 0.8)! as NSData
// set upload path
let filePath = "\(userid)" // path where you wanted to store img in storage
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
self.storageRef = FIRStorage.storage().reference()
self.storageRef.child(filePath).put(data as Data, metadata: metaData){(metaData,error) in
if let error = error {
print(error.localizedDescription)
return
}else{
//store downloadURL
let downloadURL = metaData!.downloadURL()!.absoluteString
data[index].downloadURL = downloadURL
}
}
}
// delete example
let storage = Storage.storage()
let url = data[index].downloadURL
let storageRef = storage.reference(forURL: url)
storageRef.delete { error in
if let error = error {
print(error)
} else {
// File deleted successfully
}
}

Get Facebook profile picture from URL

I want to upload the profile picture from Facebook to Firebase. I tried this answer: Upload Facebook image URL to Firebase Storage
However, Swift is giving me errors on the third line of code of that answer. The code is:
let dictionary = result as? NSDictionary
let data = dictionary?.object(forKey: "data")
let urlPic = (data?.objectForKey("url"))! as! String
Swift is telling me: Cannot call value of non-function type 'Any?!' after I changed the code to what Swift keeps suggesting me:
let urlPic = ((data as AnyObject).object(ForKey: "url"))! as! String
What is the code to use when I want to retrieve the profile picture from Facebook? My goal is to also store it into Firebase, but that will come after I get the profile picture first.
The answer is in Swift 1.2
I took reference here and implemented also
You can do this:
// accessToken is your Facebook id
func returnUserProfileImage(accessToken: NSString)
{
var userID = accessToken as NSString
var facebookProfileUrl = NSURL(string: "http://graph.facebook.com/\(userID)/picture?type=large")
if let data = NSData(contentsOfURL: facebookProfileUrl!) {
imageProfile.image = UIImage(data: data)
}
}
This is the way I got Facebook id:
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
println("fetched user: \(result)")
if let id: NSString = result.valueForKey("id") as? NSString {
println("ID is: \(id)")
self.returnUserProfileImage(id)
} else {
println("ID es null")
}
}
})
}

Firebase retrieve image from URL save with Firebase database

I have saved an image to the Firebase storage and also saved the imageURL to Firebase database, but how can I get the image back by the URL saved in firebase database? Here is how I save it
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage, editingInfo: [String : AnyObject]?) {
userPhoto.image = image
dismissViewControllerAnimated(true, completion: nil)
var data = NSData()
data = UIImageJPEGRepresentation(userPhoto.image!, 0.8)!
// set upload path
let filePath = "\(FIRAuth.auth()!.currentUser!.uid)/\("userPhoto")"
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpg"
self.storageRef.child(filePath).putData(data, metadata: metaData){(metaData,error) in
if let error = error {
print(error.localizedDescription)
return
} else {
// store downloadURL
let downloadURL = metaData!.downloadURL()!.absoluteString
// store downloadURL at database
self.databaseRef.child("users").child(FIRAuth.auth()!.currentUser!.uid).updateChildValues(["userPhoto": downloadURL])
}
}
}
Here's one way of doing it, by downloading the data and then creating a UIImage for it:
self.storage.referenceForURL(url).dataWithMaxSize(25 * 1024 * 1024, completion: { (data, error) -> Void in
let image = UIImage(data: data!)
chatMessage.image = image!
self.messages.append(chatMessage)
self.tableView.reloadData()
self.scrollToBottom()
})
This code comes from the Zero To App talk at Google I/O. Complete code is available in this gist

I want to save UIImage instead of nil value on parse

I am implementing saving post part, the post contains user profile Picture when it is saved for showing on main page. but there would be a user who hasn't profile picture. I tried this code, it occurs error.
if let profilePicture = PFUser.currentUser()?.objectForKey("profile_picture") {
post["profile_picture"] = profilePicture
} else {
post["profile_picture"] = UIImage(named: "AvatarPlaceholder" )
}
post.saveInBackgroundWithBlock({ ( isSucessful: Bool, error : NSError?) -> Void in
if error == nil {
self.alert("success", message : "your post has been uploaded")
} else {
self.alert("Error", message : (error?.localizedDescription)!)
}
if user has profile photo, it will be fine. but if not, that is the problem.
I have Avatarplaceholder jpeg file in assets.
my questions are.....
how can I upload my avatarplaceHolder ?
or is there better way to cover nil value?,
actually I don't want to waste my cloud storage.
I guess that you have to wrap you UIImage into a PFFile as follows:
let imageData = UIImageJPEGRepresentation(UIImage(named: "AvatarPlaceholder")!, 0.5)!
let profileImageFile = PFFile(name: "profileImage", data: imageData)
post["profile_picture"] = profileImageFile