I want to save UIImage instead of nil value on parse - swift

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

Related

SwiftUI UIImage from path not visible

I have an image stored inside an AppGroup, but I'm unable to show the image and I'm not sure why.
I have this inside my view:
Image(uiImage: getImageFromDir(imageName: name)!)
.resizable()
I get the image using the following function:
func getImageFromDir(imageName: String) -> UIImage? {
let appGroupPath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myId")!
let imagePath = appGroupPath.appendingPathComponent(imageName)
do {
let imageData = try Data(contentsOf: imagePath)
return UIImage(data: imageData)
} catch {
print("Error loading image : \(error)")
}
return nil
}
This runs fine and the catch block is never hit, but the image still isn't visible. My initial thought was that I had an invalid path, but this doesn't seem the case since I can load the image as expected in React Native using the path.
There's also nothing wrong with my styles since a different image loaded from Assets.xcassets works fine.
Assuming the file is really existed at specified location (you can verify generated URL for that) try with security scoped resource wrapper, like below
func getImageFromDir(imageName: String) -> UIImage? {
let appGroupPath = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.myId")!
let imagePath = appGroupPath.appendingPathComponent(imageName)
do {
if imagePath.startAccessingSecurityScopedResource() { // << this !!
defer {
imagePath.stopAccessingSecurityScopedResource() // << and this !!
}
let imageData = try Data(contentsOf: imagePath)
return UIImage(data: imageData)
}
} catch {
print("Error loading image : \(error)")
}
return nil
}
While my solution is working, it is NOT a valid answer to why my images aren't showing and I would still like to know why, if anyone knows who comes across this post in the future.
To solve this, instead of using an absolute path to the image, I used a base64 string to use as the data. The image now succesfully shows.

Display Image From Parse In Swift

I am trying to display the image I have stored in Buddy For Parse into a UIImageView, however I keep getting this error:
Could not cast value of type 'PFFileObject' (0x1045e0568) to 'NSString' (0x1041d75d8).
2019-04-13 18:15:09.869460-0500 PerfectLaptop[43839:3094232] Could not cast value of type 'PFFileObject' (0x1045e0568) to 'NSString' (0x1041d75d8).
I have already stored numerous strings into Parse, and am able to access them with no problems, and have stored the image I wanted to use also, however no matter what I try, I can't seem to get it to work. Many of the solutions I have found include casting the object as a PFFile, however this doesn't seem to exist anymore.
let query = PFQuery(className: "whichOneRecommended")
query.findObjectsInBackground { (objects, error) in
if error == nil
{
if let returnedobjects = objects
{
for object in returnedobjects
{
if (object["whichOne"] as! String).contains("\(self.whichOneJoined)")
{
self.laptopImage.image = UIImage(named: (object["laptopImage"]) as! String)
}
}
}
}
}
While the image file is viewable and downloadable in parse, I can't seem to actually have it be displayed in the imageview, and i want the image view to change programmatically by running this function as I have with other parts of the object.
Thanks in advance
The first thing to note is that PFFile has been renamed to PFFileObject.
You are trying to pass object["laptopImage"] which is a value of type Any to UIImage(named:) which can't be done because that function expects a String.
Firstly you need to create a constant of type PFFileObject:
let file = object["laptopImage"] as? PFFileObject
And then download the file data, create a UIImage from the PFFileObject and assign the image to the UIImageView:
file.getDataInBackground { (imageData: Data?, error: Error?) in
if let error = error {
print(error.localizedDescription)
} else if let imageData = imageData {
let image = UIImage(data: imageData)
self.laptopImage.image = image
}
}
Details on this can be found in the section on files in the iOS Guide.
guard let imageString = message,
let imageURL = URL(string: imageString) else { return }
do {
let imageData = try Data(contentsOf: imageURL)
image.image = UIImage(data: imageData)
} catch {
}

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")
}
}
})
}

Saving UIImage Into Core Data Always Returns Nil when using ImagePickerView - Swift 3

I've been trying to save a single picture to an entity containing a single property titled "prof" and configured as a Binary Data type.
I go through the hoops to select a picture from UIImagePickerViewController, then I call up my method that handles saving the picture in Core Data in the desired NSData format.
My issue stems from loading the picture, in my loadImage method the entity for the image is not nil, meaning it does exist. However, I get nil when I try to parse the fetched NSData to a UIImage format to recreate the picture and then be able to use it.
Now i am using Swift 3 and Xcode 8, so far all the troubleshooting questions on here have the solution of casting the NSData to UImage like so:
let image : UIImage = UIImage(data: imageData)
however, xcode gives me a compiler error when I do this, and instead forces me to cast it as:
let image : UIImage = UIImage(data: (imageData as Data?)!)
which is where i get the nil that's throwing up my flow in the air... i've tried saving the data in many different ways, but still nothing.
if anyone could go through my following methods, see if i might be doing something wrong in the saving part, or the formating of NSData on the fetch method... anything would help.
My configuration:
-the prof property has "Allow external storage" set to true
-my persistent store is seeded blank at the app installation, meaning all the needed properties are already set up when the app is launched for the first time, but obviously set to nil until changed or modified by my various data flows.
-There is no other picture entity in my data model, this is the only one.
func saveProfilePicture(_ pic: UIImage){
let picData = UIImagePNGRepresentation(pic)
let request: NSFetchRequest<UsePics> = UsePics.fetchRequest()
do {
let records = try coreDataManager.managedObjectContext.fetch(request) as [UsePics]
let first = (records.first)
first?.setValue(picData, forKey: "prof")
try context.save()
} catch let err {
print(err)
}
}
func getProfilePicture() -> UIImage? {
let request: NSFetchRequest<UsePics> = UsePics.fetchRequest()
var image : UIImage?
do {
let records = try coreDataManager.managedObjectContext.fetch(request) as [UsePics]
let first = (records.first?.prof) as NSData
if let parsedImage : UIImage = UIImage(data: (first as Data?)!) as? UIImage {
image = parsedImage
}
} catch let err {
print(err)
}
return image
}
EDIT
The solution was found by noticing that in Swift 3, the UIImage class adheres to the Transformable protocol. Swapping my property type for the image from Binary Data to Transformable actually made it possible to save the UIImage as UIImage directly into Core Data without parsing it to another data type.
func saveProfilePicture(_ image: UIImage){
let request: NSFetchRequest<UsePics> = UsePics.fetchRequest()
do {
let records = try coreDataManager.managedObjectContext.fetch(request) as [UsePics]
let first = (records.first)
first?.prof = image
print(first)
coreDataManager.saveData()
} catch let err {
print(err)
}
}
func loadProfilePicture() -> UIImage? {
var image : UIImage?
let request: NSFetchRequest<UsePics> = UsePics.fetchRequest()
do {
let records = try coreDataManager.managedObjectContext.fetch(request) as [UsePics]
let first = records.first
if let img = first?.prof {
image = img as? UIImage
} else {
print("no image")
}
} catch let err {
print(err)
}
return image
}

How to update friends image like whatsApp with Firebase

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