I'm trying to save, and later load, an image from disk. The following works on the simulator, but when I test on the device, I get unexpectedly found nil while unwrapping an Optional value.
Saving image to disk:
let sketchData: NSData = UIImagePNGRepresentation(sketch)
let destinationFolder: String = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let sketchPath: String = "\(destinationFolder)\(currentProjectID).png"
defaults.setObject(sketchPath, forKey: "sketchpath")
sketchData.writeToFile(sketchPath, atomically: true)
Loading image from disk:
let sketchPath: String = defaults.objectForKey("sketchpath") as String
let image = UIImage(contentsOfFile: sketchPath)
Here's an example path. It's identical in saving and loading, so the issue is not trying to load from a different file path.
/var/mobile/Containers/Data/Application/72EDBC3D-F9D8-4108-8A64-751A10FF1E71/Documents4.png
Does saving to an actual device require a different file path?
You just forgot to add "/" between the folder and the file's name:
let sketchPath: String = "\(destinationFolder)/\(currentProjectID).png"
You should use stringByAppendingPathComponent and stringByAppendingPathExtension:
let currentProjectID = "Test"
// you can also use NSFileManager's method URLsForDirectory to find the device's DocumentDirectory
let destinationFolder = (NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL).path!
let sketchPath = destinationFolder.stringByAppendingPathComponent(currentProjectID).stringByAppendingPathExtension("png")!
You are also saving it as NSData so you should load it as NSData
let imageData: NSData = UIImagePNGRepresentation(UIImage(data: NSData(contentsOfURL: NSURL(string:"http://i.stack.imgur.com/Xs4RX.jpg")!)! ))
imageData.writeToFile(sketchPath, atomically: true)
let loadedImage = UIImage(data: NSData(contentsOfFile: sketchPath)! )!!
Related
I'm using Realm and storing the file path to captured images as Strings. I want to retrieve them later for use in a tableView. Here's my code to store the path for each image:
func saveImage(imageName: String){
//create an instance of the FileManager
let fileManager = FileManager.default
//get the image path
thisImagePath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent(imageName)
//get the image taken with camera
let image = originalCapturedImage
//get the PNG data for this image
let data = UIImagePNGRepresentation(image!)
//store it in the document directory
fileManager.createFile(atPath: thisImagePath as String, contents: data, attributes: nil)
print("Picture path at assignment \n")
print(thisImagePath as Any)
}
And here's the code to retrieve the image:
...
var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsPath = paths[0] //Get the docs directory
let filePath = URL(fileURLWithPath: documentsPath).appendingPathComponent(item.picPath).path
let image = UIImage(contentsOfFile: filePath)
print("Picture path at retrieval \n")
print(item.picPath as Any)
cell.imageWell.image = image
cell.imageWell.clipsToBounds = true
return cell
}
Here's the comparison of the file path at runtime:
Picture path at assignment
/var/mobile/Containers/Data/Application/0E9CACAD-C6B3-4F6C-B0DB-72C43AC722E1/Documents/1535219147
...
...
Picture path at retrieval
/var/mobile/Containers/Data/Application/0E9CACAD-C6B3-4F6C-B0DB-72C43AC722E1/Documents/1535219147
The paths appear identical to me, yet no image appears. I've searched all over SO, and at one point came across a mention of the use of the URL for the file path. Somehow, I lost track of that entry and haven't been able to find it again.
Any help would be greatly appreciated!
You can try with below code for writing the image to the file instead of creating file with content. try? data.write(to: URL(fileURLWithPath: documentsPath))
You can also refer below code for saving image.
class func saveImageToFileWithDirectory(_ imageData:Data, fileName:String, folderName : String? = nil) {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) as NSArray
let documentsDirectory = paths.object(at: 0) as! NSString
let path = documentsDirectory.appendingPathComponent(folderName) as NSString
if !FileManager.default.fileExists(atPath: path as String) {
do {
try FileManager.default.createDirectory(atPath: path as String, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription);
}
}
let imagePath = path.appendingPathComponent(fileName)
if !FileManager.default.fileExists(atPath: imagePath as String) {
try? imageData.write(to: URL(fileURLWithPath: imagePath))
} }
Code for retrieving the image looks good. If you need help in that also, pls comment, I will post that also.
Hope this solves your issue.
I am getting a photo's URL using requestContentEditingInput using the PHLibrary
asset.requestContentEditingInput(with: PHContentEditingInputRequestOptions()) { (input, _) in
let url = input?.fullSizeImageURL
}
This URL prints: file:///Users/josh/Library/Developer/CoreSimulator/Devices/EE65D986-55E7-414C-A73E-D1C96FF17004/data/Media/DCIM/100APPLE/IMG_0005.JPG.
How do I retrieve this image? I've tried the following but it does not return anything:
var fileLocation = "file:///Users/josh/Library/Developer/CoreSimulator/Devices/EE65D986-55E7-414C-A73E-D1C96FF17004/data/Media/DCIM/100APPLE/IMG_0005.JPG"
let url = URL(string: fileLocation)
let asset = PHAsset.fetchAssets(withALAssetURLs: [url!], options: nil)
if let result = asset.firstObject {
//asset.firstObject does not exist
}
apparently apple will not allow the developer to access any and every photo in the user's photo library even after they have accepted photos usage. If you are using an image that hasnt been picked from the imagePicker, (i.e. choosing last image in library), you have to store the image in the document directory before you can use the document directory URL. I guess this prevents people hacking into others photo library
//Storing the image (in my case, when selecting last photo NOT via imagePicker)
let fileManager = FileManager.default
let paths = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("image01.jpg")
let imageData = UIImageJPEGRepresentation(image!, 1.0)
fileManager.createFile(atPath: paths as String, contents: imageData, attributes: nil)
//Retrieving the image
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
if let dirPath = paths.first {
let imageURL = URL(fileURLWithPath: dirPath).appendingPathComponent("image01.jpg")
if let imageRetrieved = UIImage(contentsOfFile: imageURL.path) {
//do whatever you want with this image
print(imageRetrieved)
}
}
I am saving path in Database return by UIImagepicker from Gallery
let imageURL = info[UIImagePickerControllerReferenceURL] as! NSURL
let imageName = imageURL.lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
//let localPath = documentDirectory.stringByAppendingPathComponent(imageName!)
let imagePath = String("\(documentDirectory)/\(imageName!)")
where path look like
/Users/kshitijghule/Library/Developer/CoreSimulator/Devices/3AC7B500-E980-4A00-BC32-34FA3C7DDE8A/data/Containers/Data/Application/838FB5A1-4448-46C9-8BEC-2E939668B97D/Documents/asset.JPG
Now i want load this image from this path.
i used this code
let url = NSURL(string:"/Users/kshitijghule/Library/Developer/CoreSimulator/Devices/3AC7B500-E980-4A00-BC32-34FA3C7DDE8A/data/Containers/Data/Application/838FB5A1-4448-46C9-8BEC-2E939668B97D/Documents/asset.JPG")!//path from database but mention static
let imageData = NSData(contentsOfURL:url)!
cell?.petImageView.image = UIImage(data: imageData)
But i am getting crash at line
let imageData = NSData(contentsOfURL:url)!
How to fix this issue? It will work on device ?
If you are storing images in the document directory store only image name in the db
At the time of retrieval append the current document directory path with your image name like you done at save time
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
//let localPath = documentDirectory.stringByAppendingPathComponent(imageName!)
//imageName which you have stored in the db at retrieval time
let imagePath = String("\(documentDirectory)/\(imageName!)")
let url = NSURL(string:imagePath)
let imageData = NSData(contentsOfURL:url)!
as i have also this type of issue at last if found that the app number of simulator(838FB5A1-4448-46C9-8BEC-2E939668B97D) is changes which cause the issue
Hope this may solve your issue
I have answered a similar question here.You only have to save those paths to your database, and from the database path you can retrieve those images.
Save image in Document Directory taken from Gallery or Camera.
func origionalImage(origionalImage: UIImage!, editedImage: UIImage!, userInfo info: [NSObject : AnyObject]!) {
let imageData = NSData(data:UIImagePNGRepresentation(origionalImage)!)
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let docs: String = paths[0]
let imageName = self.randomStringWithLength(6) as String
//imageName can save in sqlite to load image later
let fullPath = String("\(docs)/\(imageName).png")
print(fullPath)
let result = imageData.writeToFile(fullPath, atomically: true)
print("FILE WRITTEN SUCCESS=>:\(result)")
}
Load Image from Database
let tempDBObject = self.petListArray[indexPath.row] as! Database
cell?.petName.text = tempDBObject.Hname
//Doc Path
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
let imagePath = String("\(documentDirectory)/\(tempDBObject.Hpath!)")
if imagePath == "" {
}else{
cell?.petImageView.image = UIImage(contentsOfFile: imagePath)
}
I am developing an app where user can save 13 screenshots and display them on a single view as thumbnails or as a full screen image. This is how I save the screenshots:
let fileName:String = self.stickerUsed + "saved" + ".png"
var arrayPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as! NSString
var pngFileName = arrayPaths.stringByAppendingPathComponent(fileName)
UIImagePNGRepresentation(resizeImage(screenshot!, newSize: CGSizeMake(self.view.frame.width, self.view.frame.height))).writeToFile(pngFileName, atomically:true)
NSUserDefaults.standardUserDefaults().setObject(pngFileName, forKey: self.stickerUsed)
NSUserDefaults.standardUserDefaults().synchronize()
and this is how i retrieve them:
var defaultName:String = self.stickerUsed + "saved" + ".png"
let path = NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true)[0] as! NSString
let fileName = NSUserDefaults.standardUserDefaults()
.stringForKey(stickerUsed) ?? defaultName
let imagePath = path.stringByAppendingPathComponent(fileName)
let image = UIImage(named: imagePath )
How do i overwrite the saved images ? When i use the code to save imageof a different screenshot with same filename and then retrieve it i get the previous image that was initially saved and new image is not overwritten!
I made your code cleaner and fixed the problem! Comments will help you learn some basic stuff about how it works.
First, define function that gives you full filepath from filename:
func documentsPathWithFileName(fileName : String) -> String {
// Get file path to document directory root
let documentsDirectoryPath = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)[0] as! String
return documentsDirectoryPath.stringByAppendingPathComponent(fileName)
}
And then, function that takes UIImage and saves it, or replaces it, depending:
func saveOverrideImage(screenshot : UIImage, stickerName : String) {
// Get file path poining to documents directory
let filePath = documentsPathWithFileName(stickerName)
// We could try if there is file in this path (.fileExistsAtPath())
// BUT we can also just call delete function, because it checks by itself
NSFileManager.defaultManager().removeItemAtPath(filePath, error: nil)
// Resize image as you want
let image : NSData = UIImagePNGRepresentation(resizeImage(screenshot!, newSize: CGSizeMake(self.view.frame.width, self.view.frame.height)))
// Write new image
image.writeToFile(filePath, atomically: true)
// Save your stuff to
NSUserDefaults.standardUserDefaults().setObject(stickerName, forKey: self.stickerUsed)
NSUserDefaults.standardUserDefaults().synchronize()
}
Also, following the same style, you can get image:
func imageForStickerName(stickerName : String) -> UIImage? {
// Get file path poining to documents directory
let filePath = documentsPathWithFileName(stickerName)
// Get image from file on given local url
return UIImage(contentsOfFile: filePath)
}
Hope it helps!
Try You can use
var error:NSError?
var resultingURL:NSURL?
let oldURL:NSURL = NSURL.fileURLWithPath("<old path>")!
let newURL:NSURL = NSURL.fileURLWithPath("<new path>")!
fileManager.replaceItemAtURL(oldURL,
withItemAtURL: newURL,
backupItemName: nil,
options: .UsingNewMetadataOnly,
resultingItemURL: &resultingURL,
error: &error)
or you can delete old file and write new on, for more details on FileManager visit here
I am trying to take a picture and upload the image into an iCloud database, however I keep getting the error: Type 'UIImage' does not conform to protocol 'CKRecordValue'
The code I am trying to use to upload the file is as follows:
data.setObject(picFile.image, forKey: "picture")
Is there something wrong with the line of code, or am I missing something else?
I had to convert it to a CKAsset. I used the following code:
let imageData = UIImageJPEGRepresentation(picFile.image, 1)
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentDirectory = paths[0] as String
let myFilePath = documentDirectory.stringByAppendingPathComponent("picture")
imageData.writeToFile(myFilePath, atomically: true)
let url = NSURL(fileURLWithPath: myFilePath)
let asset = CKAsset(fileURL: url)
data.setObject(asset, forKey: "picture"