Check if photo still exists in camera roll after restart ios app - ios

I'm still new in iOS development and I'm creating an app that allows to select some photos and access them quickly.
In CoreData, I store the referenceUrl of the photo instead of the photo itself. I'm able to load photos when starting the app this way.
But, before loading photos, I need to check that they still exist and cannot figure out how to check, using the referenceUrl, if a photo exists or not.
Even using the localPath does not work. It returns false all the time.
If you have any idea how I can proceed, I'll be very grateful.
Thanks.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)!
let localPathString = String(describing: localPath)
let fileManager = FileManager.default
if fileManager.fileExists(atPath: localPathString){
print ("Photo exists")
} else{
print ("Photo does not exist")
}
}

I found a solution, here it is.
I use imageUrl from my code above like that:
let assets = PHAsset.fetchAssets(withALAssetURLs: [imageUrl as URL], options: nil)
if assets.firstObject != nil {
//Then the image is still there
}
else{
//The image is not present anymore
}
Hope that helps.

Related

How to store and use MP4 files directly to an iOS application

I am trying to store videos from a user's camera roll directly on the application itself using the following:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
let videoURL = info[UIImagePickerController.InfoKey.mediaURL] as! URL
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let fileName = String(Date().hashValue) + ".mp4"
let dataPathStr = documentsDirectory + "/" + fileName
url = dataPathStr
let dataPath = URL(fileURLWithPath: dataPathStr)
var videoData : NSData?
do {
try videoData = NSData(contentsOf: videoURL)
videoData?.write(to: dataPath, atomically: true)
} catch {
print("Error saving video:")
print(error)
}
self.dismiss(animated: true) {
self.performSegue(withIdentifier: "importToCrop", sender: self)
}
}
I have this working as I am able to access the video after storing it by using its URL (dataPath).
However, when I close and reopen the app, I can no longer the access via the same URL - It seems like the video is deleted once the app is closed.
Is there a way to check if the video is actually deleted or maybe is there a better way to store mp4 files on the application?
Figured it out -- turns out the way I saved the file above was correct, but what I didn't realize is that the path to the Documents directory changes with each run.
So, to get retrieve the a file stored in your Documents directory, you would have to get the url each time by the following:
func getVideoURL(fileName : String)-> URL {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(fileName)
}

Error on image capture with camera mode

I'm working on image picker with camera and gallery and using following code to get image captured from camera but imageurl and image name is nil.I'm testing on mobile with os version of 11.2.2.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl?.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
print("file saved")
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
}
Use UIImagePickerControllerImageURL instead of UIImagePickerControllerReferenceURL like this:
let imageUrl = info[UIImagePickerControllerImageURL] as? NSURL
You will not get any imageUrl or imageName because you are using the camera mode and that image is still not saved in your gallery and hence no image path is created for that camera clicked pic. So they will be nil. You can only get the UIImage object info[UIImagePickerControllerOriginalImage] in this case.
If you pick the image from photo album, then you will get everyhting. You can get the url by info[UIImagePickerControllerImageURL] and you can grab the name using the last path component.
Change your imagePickerController source to photo imagePickerController.sourceType = .photoLibrary and then you will get the urls.

Persisting data in iOS documents directory

I have an app that saves a recorded video to the documents directory, as well as a Post object, and populates a collection view from the Post object. However upon restarting the app, the collection view is empty, so the videos being saved to the docs directory is not persisting (at least I think that's the problem).
This is the function that saves the video:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let mediaType = info[UIImagePickerControllerMediaType] as! NSString
dismiss(animated: true, completion: nil)
if mediaType == kUTTypeMovie {
var uniqueVideoID = ""
var videoURL:NSURL? = NSURL()
var uniqueID = ""
uniqueID = NSUUID().uuidString
// Get the path as URL and store the data in myVideoVarData
videoURL = info[UIImagePickerControllerMediaURL] as? URL as NSURL?
let myVideoVarData = try! Data(contentsOf: videoURL! as URL)
// Write data to temp diroctory
let tempPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let tempDocumentsDirectory: AnyObject = tempPath[0] as AnyObject
uniqueVideoID = uniqueID + "TEMPVIDEO.MOV"
let tempDataPath = tempDocumentsDirectory.appendingPathComponent(uniqueVideoID) as String
try? myVideoVarData.write(to: URL(fileURLWithPath: tempDataPath), options: [])
// Get the time value of the video
let fileURL = URL(fileURLWithPath: tempDataPath)
let asset = AVAsset(url: fileURL)
let duration : CMTime = asset.duration
// Remove the data from the temp Document Diroctory.
do{
let fileManager = FileManager.default
try fileManager.removeItem(atPath: tempDataPath)
} catch {
//Do nothing
}
// Check to see if video is under the 18500 (:30 seconds)
if duration.value <= 18500 {
// Write the data to the Document Directory
let docPaths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsDirectory: AnyObject = docPaths[0] as AnyObject
uniqueVideoID = uniqueID + "VIDEO.MOV"
let docDataPath = documentsDirectory.appendingPathComponent(uniqueVideoID) as String
try? myVideoVarData.write(to: URL(fileURLWithPath: docDataPath), options: [])
print("docDataPath under picker ",docDataPath)
print("Video saved to documents directory")
//Create a thumbnail image from the video
let assetImageGenerate = AVAssetImageGenerator(asset: asset)
assetImageGenerate.appliesPreferredTrackTransform = true
let time = CMTimeMake(asset.duration.value / 3, asset.duration.timescale)
if let videoImage = try? assetImageGenerate.copyCGImage(at: time, actualTime: nil) {
//Add thumbnail & video path to Post object
let video = Post(pathToVideo: URL(fileURLWithPath: docDataPath), thumbnail: UIImage(cgImage: videoImage))
posts.append(video)
print("Video saved to Post object")
}
}else{
print("Video not saved")
}
}
}
Specifically, this is where the video path and thumbnail are added to my object:
//Add thumbnail & video path to Post object
if let videoImage = try? assetImageGenerate.copyCGImage(at: time, actualTime: nil) {
let video = Post(pathToVideo: URL(fileURLWithPath: docDataPath), thumbnail: UIImage(cgImage: videoImage))
posts.append(video)
So I do give it the path to the video in the documents directory; how can I ensure that the data persists there?
EDIT:
To verify if the videos are being saved on the device, connect the device to Xcode and navigate to Window->Devices in Xcode. Then select your device on the left and find your app in the Installed Apps list. Select your app and click on the gear icon at the bottom of the list and press 'Show Containter'. Wait for a few seconds and you should see all the folders in your app.
Secondly, not sure why you are writing the video and deleting it and writing it back again and also why use 'try?' instead of actually catching any exceptions thrown during the file write?

How can I create a UIImageGIFRepresentation function?

Using Swift 3 for iOS, I am able to use cinemagraphs (animated gifs) that I download through a UIWebView without any problem. I am also trying to get them to work from the iPhone library. However, there is no way that I have found to get the data representation of a GIF stored in the library.
Someone will say that "there is no such thing as an animated gif in the library", but they would be wrong. Go to a web page in Safari, long-tap on an animated gif, and save it to your library. Then send a text message to yourself and copy in that image from the library. You'll see that the animated gif is intact and works perfectly.
My problem is that I need to copy the image from the library programmatically, and I'm not sure how to do it with no specific function built for GIFs. I would like to create the equivalent of UIImagePNGRepresentation or UIImageJPEGRespresentation, except for GIF images. Alternatively, is there a way to get an image from the library as a UIImage, so I don't have to try to convert it to data?
Here's the code I am using for other image formats:
* Edited to be latest version *
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let origImage = info[UIImagePickerControllerOriginalImage] as! UIImage
let refURL : URL = info[UIImagePickerControllerReferenceURL] as! URL
var resizedImage: UIImage!
var ext: String!
ext = refURL.pathExtension
if ext == "GIF" {
resizedImage = origImage
} else {
resizedImage = resizeImage(origImage: origImage, ext: ext)
}
DispatchQueue.main.async(execute: { () -> Void in
self.photoUpdated(newImage: resizedImage)
})
picker.dismiss(animated: true, completion: nil)
}
For GIFs, I tried the following, using the SwiftGif project, which was not successful:
let url = Bundle.main.url(forResource: refURL.absoluteString, withExtension: "GIF")
let data = try! Data(contentsOf: url!)
let advTimeGif = UIImage.gifWithData(data)
let imageView = UIImageView(image: advTimeGif)
newImage = imageView.image
Anyone have any suggestions as to how I might get this to work? Thanks.
Edit:
I figured out a few more pieces of the puzzle. Specifically, I can get the image name and the local path to it.
let refURL : URL = info[UIImagePickerControllerReferenceURL] as! URL
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String
let localPath = URL(fileURLWithPath: documentDirectory).appendingPathComponent(imageName)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
Still can't figure out how to get it from there to Data.

Swift 3.0 Getting URL of UIImage selected from UIImagePickerController

Note:- This question is only for Swift 3.0
I am able to get the path prio to Swift 3.0
I want to get UIImage's path picked in didFinishPickingMediaWithInfo method
let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
But this path is not pointing to my image, Even there is no any image in Documents folder.
Can anyone help me on this?
You can't access the path of the picked image directly. You need to save that in your DocumentsDirectory and then take the image back with the path.
Do this
Swift 3.x
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageUrl = info[UIImagePickerControllerReferenceURL] as? NSURL
let imageName = imageUrl?.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let photoURL = NSURL(fileURLWithPath: documentDirectory)
let localPath = photoURL.appendingPathComponent(imageName!)
if !FileManager.default.fileExists(atPath: localPath!.path) {
do {
try UIImageJPEGRepresentation(image, 1.0)?.write(to: localPath!)
print("file saved")
}catch {
print("error saving file")
}
}
else {
print("file already exists")
}
}
Also note that you are using the name as the last path component which is same for every file. So, this will save your image in DocumentDirectory only once as it will find the path next time.
Now when you access the localPath variable and navigate to the path, you will find the image.
NOTE:
If you are using a device here, then you need to download the container of the device, show its package contents and navigate to the Documents Directory where you will find your saved image.
In SWIFT 4 U Can Try This, It's working properly.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let imgUrl = info[UIImagePickerControllerImageURL] as? URL{
let imgName = imgUrl.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first
let localPath = documentDirectory?.appending(imgName)
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
let data = UIImagePNGRepresentation(image)! as NSData
data.write(toFile: localPath!, atomically: true)
//let imageData = NSData(contentsOfFile: localPath!)!
let photoURL = URL.init(fileURLWithPath: localPath!)//NSURL(fileURLWithPath: localPath!)
print(photoURL)
}
APPDEL.window?.rootViewController?.dismiss(animated: true, completion: nil)
}

Resources