This question already has answers here:
Save An Image To Application Documents Folder From UIView On IOS
(6 answers)
Closed 5 years ago.
I want to in my app, be able to allow users to save large images(jpg) as well as data for each image(txt) and load the images/data. I'm having trouble figuring out where to save these images and text files. Userdefault wouldnt work because of the size of the image files and I don't want to save in the documents directory because then the user can access and potentially corrupt the data.
Where is a good place to save large data files for my app so I can load them later?
You can save and retrieve your files in application directory folder. Also you can use iCloud to save your files.
Use below code if you want to save and retrieve files from Directory folder .
Xcode 8.3.2 Swift 3.x. Using NSKeyedArchiver and NSKeyedUnarchiver
Reading file from documents
let documentsDirectoryPathString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
let documentsDirectoryPath = NSURL(string: documentsDirectoryPathString)!
let jsonFilePath = documentsDirectoryPath.appendingPathComponent("Filename.json")
let fileManager = FileManager.default
var isDirectory: ObjCBool = false
if fileManager.fileExists(atPath: (jsonFilePath?.absoluteString)!, isDirectory: &isDirectory) {
let finalDataDict = NSKeyedUnarchiver.unarchiveObject(withFile: (jsonFilePath?.absoluteString)!) as! [String: Any]
}
else{
print("File does not exists")
}
Write file to documents
NSKeyedArchiver.archiveRootObject(finalDataDict, toFile:(jsonFilePath?.absoluteString)!)
If for some reason you don't want to use the documents directory, or you want those data in a separate folder, or you don't want to permanently save them, you can also create your own temporary directory
saving data as file in a new directory (swift 3):
func saveToMyDirectory(data: Data, filename: String) {
var tempDirectoryURL = NSURL.fileURL(withPath: NSTemporaryDirectory(), isDirectory: true)
tempDirectoryURL = tempDirectoryURL.appendingPathComponent(filename)
do {
try data?.write(to: tempDirectoryURL)
} catch {}
}
Alternative approach: use Apple's UIDocumentInteractionController or UIActivityViewController and let the user choose how to save his/her documents:
https://developer.apple.com/documentation/uikit/uidocumentinteractioncontroller
https://developer.apple.com/documentation/uikit/uiactivityviewcontroller
Related
I have a WKWebView app which i will like to clear a specific cache when image is uploaded .
When i upload an image, the name remains same but the old image will be override with new one, like old image is logo.png, new image will be renamed with logo.png also. But because of cache users will still be seeing the old image.
I have below line of code to clear cache once image has been uploaded and it working fine, but my only problem now is that all cached data is being cleared also.
Is there any way i can clear cache for just the image was uploaded, maybe by passing the image name?
Or just clear cache for images?
static func clearCache(){
let cacheURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
let fileManager = FileManager.default
do {
// Get the directory contents urls (including subfolders urls)
let directoryContents = try FileManager.default.contentsOfDirectory( at: cacheURL, includingPropertiesForKeys: nil, options: [])
for file in directoryContents {
print("CACHE = ", file)
do {
try fileManager.removeItem(at: file)
}
catch let error as NSError {
debugPrint("Ooops! Something went wrong: \(error)")
}
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
From the loop i got this
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/com.myapp.ios.sellers/
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/google-sdks-events/
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/com.apple.WebKit.WebContent/
CACHE =
file:///private/var/mobile/Containers/Data/Application/BFEB788B-9EA4-4921-A902-230869CAC814/Library/Caches/WebKit/
It seems like you need to find the file you want to remove when you are in the for loop loop for files. Remove that specific image when the for loop hits. Right now that for loop removes all cache in directoryContents.
hope you are doing good in development. I have a question regarding Zipping currently i am using Zip framework which I am using for zip the all captured image in device but the problem here is I do not want to save the Zip file in document directory instead I wanna save this memory itself. I am struggling since last week please let me know how can we achieve the zipping without saving it in local directory filepath
Also when I captured the image successfully I saved it to local directory using
let documentsDirectory = FileManager.default.urls(for:
.documentDirectory, in: .userDomainMask).first!
let fileName = "image.jpg"
let fileURL = documentsDirectory.appendingPathComponent(fileName)
if let data = UIImageJPEGRepresentation(image, 1.0),
!FileManager.default.fileExists(atPath: fileURL.path) {
do {
// writes the image data to disk
try data.write(to: fileURL)
print("file saved")
} catch {
print("error saving file:", error)
}
}
After when I am trying to send the image before our server I want to make it all one file so I have implemented the Zip (framework)
Here filpathArray meant all captured image in local path
do {
var urls = [URL]()
for i in 0..<(self.filePathArray.count)
{
urls.append(self.filePathArray[i] as! URL)
}
if self.filePathArray.count > 0 {
let zipFiles = try Zip.quickZipFiles(urls, fileName: "AllFiles")
}
}
Here zipping is done successfully but it saved in local path so when using app container I can able to see the images, I do not want to see the images in device like apple sandbox or Xcode container itself
I want to make zipping on the flow like without saving it document directory, Thanks in advance.
First of all I know this is a subjective question, not code based, How ever I need to find solution. Please provide any references
I am working on a task in which I saving the files in Device Document directory. Upto here all is working fine. However when I see these files from :
Files App -> App Folder and the files
I can see all those files.
Now I want to hide few of them, How can I achieve these....?
As per your requirement. You need to change some lines of code in saving file.
Firstly, The FileApp shows all the data that save in documentsDirectory of app whether you put code for hide or not. To hide few files you need to make separate path for them.
First, the file you want to show in documentDirectory:
let documentsDirectory = (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
The file you don’t want to show with user, you need to create path here:
let libraryDirectory = (FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask)).last! as URL
Once you set the library path for saving all your important files. All will be hidden and cannot be accessed by user.
To know more about files, please refer to this link:
https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html
Xcode 9 • Swift 4 or Xcode 8 • Swift 3
extension URL {
var isHidden: Bool {
get {
return (try? resourceValues(forKeys: [.isHiddenKey]))?.isHidden == true
}
set {
var resourceValues = URLResourceValues()
resourceValues.isHidden = newValue
do {
try setResourceValues(resourceValues)
} catch {
print("isHidden error:", error)
}
}
}
}
for more reference see chain here Cocoa Swift, get/set hidden flag on files and directories
or
https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/ManagingFIlesandDirectories/ManagingFIlesandDirectories.html
How would one programmatically save an image generated from a playground to the resources folder?
I have generated some photos through filters in my playground that I would like to save somehow. The resources folder seems like a good fit. What if I wanted to save the image to the desktop?
I've seen this done with saving images for apps, but I just want to save it to my desktop (or a specified folder in a specified location.)
Create folder first in 'Documents' with name 'Shared Playground Data' otherwise app will give error.
SWIFT 5:
let image = // your UIImage
let filepath = playgroundSharedDataDirectory.appendingPathComponent("export.jpg")
let imagedata = image.jpegData(compressionQuality: 1.0)
try! imagedata?.write(to: URL.init(fileURLWithPath: filepath.path))
print("write to \(filepath)")
In Xcode 11, the folder is not in ~/Documents anymore for iOS playgrounds but buried deep in ~/Library/Developer/. You have to print the path and create the Shared Playground Data folder manually to save a file from a playground:
import PlaygroundSupport
// ...
let url = playgroundSharedDataDirectory.appendingPathComponent("example.png")
print(url)
try! image.pngData()!.write(to: url)
Here's how to save it to the shared data directory:
Create a path to the image:
let path = XCPlaygroundSharedDataDirectoryURL.appendingPathComponent("export.jpg")!
(you may need to create the directory ~/Documents/Shared Playground Data/)
Then to save your output (in this case a CIImage from a filter)
let temp:CGImage = context.createCGImage(output, from: output.extent)!
let image = UIImage(cgImage: temp)
let data = UIImageJPEGRepresentation(image, 1.0)
try! data?.write(to: path)
While the first answer helped point me in the right direction, the lack of ability to validate the required playgroundSharedDataDirectory path exists, the requirement to create that directory in order for the path to work, as well as force unwrapping (using !) the try can lead to frustration as well as drag out the process.
Here is a safer, more convenient solution that checks the name you provide for extra safety:
func writeImage(_ image: UIImage, name: String) {
if name.isEmpty || name.count < 3 {
print("Name cannot be empty or less than 3 characters.")
return
}
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
print("No documents directory found.")
return
}
let imagePath = documentsDirectory.appendingPathComponent("\(name).png")
let imagedata = image.jpegData(compressionQuality: 1.0)
do {
try imagedata?.write(to: imagePath)
print("Image successfully written to path:\n\n \(documentsDirectory) \n\n")
} catch {
print("Error writing image: \(error)")
}
}
Call using:
writeImage(image, name: "MyNewImage")
A break down of what is happening:
The method writeImage checks to see if the documents directory exists.
If the documents directory does not exist (unlikely), stop process.
If the documents directory exists, carry on and write the image to the path.
Below are the two functions which I use in the picker view controller to save the file in the App documents directory. And save the url in the local DB & display the image using UIImage(contentsOfFile: ImagePathString)
Everything works well as until this point however as soon as i re-run the simulator images does not show up. I believe its because the app directory keeps changing every time its run on the simulator. My question if its the same when deployed on the device?
func getDocumentsDirectory() -> NSString {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
return documentsDirectory
}
//Below function is used in imagePickerController
if let data = UIImagePNGRepresentation(modifiedImage!) {
let filename = getDocumentsDirectory().stringByAppendingPathComponent("\(NSDate()).png")
data.writeToFile(filename, atomically: true)
pathImage = filename
print(pathImage)
}
Yes url to App documents folder may change when the app is deployed on the device.
Refer below link
Technical Note TN2406
.