Delete specified file from document directory - ios

I want to delete an image from my app document directory. Code I have written to delete image is:
-(void)removeImage:(NSString *)fileName
{
fileManager = [NSFileManager defaultManager];
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsPath = [paths objectAtIndex:0];
filePath = [documentsPath stringByAppendingPathComponent:[NSString stringWithFormat:#"%#", fileName]];
[fileManager removeItemAtPath:filePath error:NULL];
UIAlertView *removeSuccessFulAlert=[[UIAlertView alloc]initWithTitle:#"Congratulation:" message:#"Successfully removed" delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[removeSuccessFulAlert show];
}
Its working partially. This code deleting file from directory, but when I'm checking for the contents in directory, it still showing the image name there. I want to completely remove that file from directory. What should I change in the code to do the same? Thanks

I checked your code. It's working for me. Check any error you are getting using the modified code below
- (void)removeImage:(NSString *)filename
{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:filename];
NSError *error;
BOOL success = [fileManager removeItemAtPath:filePath error:&error];
if (success) {
UIAlertView *removedSuccessFullyAlert = [[UIAlertView alloc] initWithTitle:#"Congratulations:" message:#"Successfully removed" delegate:self cancelButtonTitle:#"Close" otherButtonTitles:nil];
[removedSuccessFullyAlert show];
}
else
{
NSLog(#"Could not delete file -:%# ",[error localizedDescription]);
}
}

Swift 3.0:
func removeImage(itemName:String, fileExtension: String) {
let fileManager = FileManager.default
let nsDocumentDirectory = FileManager.SearchPathDirectory.documentDirectory
let nsUserDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
guard let dirPath = paths.first else {
return
}
let filePath = "\(dirPath)/\(itemName).\(fileExtension)"
do {
try fileManager.removeItem(atPath: filePath)
} catch let error as NSError {
print(error.debugDescription)
}}
Thanks to #Anil Varghese, I wrote very similiar code in swift 2.0:
static func removeImage(itemName:String, fileExtension: String) {
let fileManager = NSFileManager.defaultManager()
let nsDocumentDirectory = NSSearchPathDirectory.DocumentDirectory
let nsUserDomainMask = NSSearchPathDomainMask.UserDomainMask
let paths = NSSearchPathForDirectoriesInDomains(nsDocumentDirectory, nsUserDomainMask, true)
guard let dirPath = paths.first else {
return
}
let filePath = "\(dirPath)/\(itemName).\(fileExtension)"
do {
try fileManager.removeItemAtPath(filePath)
} catch let error as NSError {
print(error.debugDescription)
}
}

Swift 2.0:
func removeOldFileIfExist() {
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
if paths.count > 0 {
let dirPath = paths[0]
let fileName = "someFileName"
let filePath = NSString(format:"%#/%#.png", dirPath, fileName) as String
if NSFileManager.defaultManager().fileExistsAtPath(filePath) {
do {
try NSFileManager.defaultManager().removeItemAtPath(filePath)
print("old image has been removed")
} catch {
print("an error during a removing")
}
}
}
}

In Swift both 3&4
func removeImageLocalPath(localPathName:String) {
let filemanager = FileManager.default
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true)[0] as NSString
let destinationPath = documentsPath.appendingPathComponent(localPathName)
do {
try filemanager.removeItem(atPath: destinationPath)
print("Local path removed successfully")
} catch let error as NSError {
print("------Error",error.debugDescription)
}
}
or
This method can delete all local file
func deletingLocalCacheAttachments(){
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
do {
let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
if fileURLs.count > 0{
for fileURL in fileURLs {
try fileManager.removeItem(at: fileURL)
}
}
} catch {
print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
}
}

Instead of having the error set to NULL, have it set to
NSError *error;
[fileManager removeItemAtPath:filePath error:&error];
if (error){
NSLog(#"%#", error);
}
this will tell you if it's actually deleting the file

I want to delete my sqlite db from document directory.I delete the sqlite db successfully by below answer
NSString *strFileName = #"sqlite";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *contents = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:NULL];
NSEnumerator *enumerator = [contents objectEnumerator];
NSString *filename;
while ((filename = [enumerator nextObject])) {
NSLog(#"The file name is - %#",[filename pathExtension]);
if ([[filename pathExtension] isEqualToString:strFileName]) {
[fileManager removeItemAtPath:[documentsDirectory stringByAppendingPathComponent:filename] error:NULL];
NSLog(#"The sqlite is deleted successfully");
}
}

NSError *error;
[[NSFileManager defaultManager] removeItemAtPath:new_file_path_str error:&error];
if (error){
NSLog(#"%#", error);
}

FreeGor version converted to Swift 3.0
func removeOldFileIfExist() {
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
if paths.count > 0 {
let dirPath = paths[0]
let fileName = "filename.jpg"
let filePath = NSString(format:"%#/%#", dirPath, fileName) as String
if FileManager.default.fileExists(atPath: filePath) {
do {
try FileManager.default.removeItem(atPath: filePath)
print("User photo has been removed")
} catch {
print("an error during a removing")
}
}
}
}

You can double protect your file removal with NSFileManager.defaultManager().isDeletableFileAtPath(PathName) As of now you MUST use do{}catch{} as the old error methods no longer work.
isDeletableFileAtPath() is not a "throws" (i.e.
"public func removeItemAtPath(path: String) throws")
so it does not need the do...catch
let killFile = NSFileManager.defaultManager()
if (killFile.isDeletableFileAtPath(PathName)){
do {
try killFile.removeItemAtPath(arrayDictionaryFilePath)
}
catch let error as NSError {
error.description
}
}

If you are interesting in modern api way, avoiding NSSearchPath and filter files in documents directory, before deletion, you can do like:
let fileManager = FileManager.default
let keys: [URLResourceKey] = [.nameKey, .isDirectoryKey]
let options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles, .skipsPackageDescendants]
guard let documentsUrl = fileManager.urls(for: .documentDirectory, in: .userDomainMask).last,
let fileEnumerator = fileManager.enumerator(at: documentsUrl,
includingPropertiesForKeys: keys,
options: options) else { return }
let urls: [URL] = fileEnumerator.flatMap { $0 as? URL }
.filter { $0.pathExtension == "exe" }
for url in urls {
do {
try fileManager.removeItem(at: url)
} catch {
assertionFailure("\(error)")
}
}

Related

How to share on instagram in ios?

I have to share image on instagram with caption but in Instagram nothing is coming. I used below code for sharing on instagram. Is there any changes in code of sharing. I also check the official page of Instagram but no code is given. https://www.instagram.com/developer/mobile-sharing/iphone-hooks/
Following code is working till ios10 but in ios11 it is not working any more.
File write successfully in document directory but problem was in UIDocumentInteractionController. It is not able to read file from document directory.
//MARK:
//MARK: share with instagram
func shareImageToInstagram(withImagePath imgPath:String,withStrTitle strTitle:String,withView view:UIView,withSender sender:UIButton! = nil) {
let instagramURL = URL(string: "instagram://app")
if UIApplication.shared.canOpenURL(instagramURL!) {
interactionController = UIDocumentInteractionController(url: URL.init(fileURLWithPath: imgPath))
interactionController?.uti = "com.instagram.photos"
interactionController?.annotation = NSDictionary.init(dictionaryLiteral: ("InstagramCaption",strTitle))
interactionController?.presentOpenInMenu(from: CGRect.zero, in: view, animated: true)
sender.isUserInteractionEnabled = true
}
}
//MARK:
//MARK: share with instagram
func downloadUserImageFromURL(withImageUrl imgURl : URL,withView view:UIView,withstrTitle strTitle:String,withSender sender:UIButton! = nil){
DispatchQueue.global(qos: .userInitiated).async {
do {
DispatchQueue.main.async {
SINGLETON.startLoadingActivity(view)
}
let data = try Data.init(contentsOf: imgURl) //make sure your image in this url does exist, otherwise unwrap in a if let check
DispatchQueue.main.async {
SINGLETON.stopLoadingActivity(view)
//create instance of NSFileManager
let paths: [Any] = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
//create an array and store result of our search for the documents directory in it
let documentsDirectory: String = paths[0] as? String ?? ""
//create NSString object, that holds our exact path to the documents directory
let fullPath: String = URL(fileURLWithPath: documentsDirectory).appendingPathComponent("insta.igo").absoluteString
//add our image to the path
if FileManager.default.fileExists(atPath: fullPath)
{
do {
try FileManager.default.removeItem(at: URL.init(string: fullPath)!)
} catch let error as NSError {
sender.isUserInteractionEnabled = true
print(error.localizedDescription)
}
}
do {
try data.write(to: URL.init(string: fullPath)!)
self.shareImageToInstagram(withImagePath: fullPath, withStrTitle: strTitle, withView: view,withSender: sender)
} catch let error as NSError {
sender.isUserInteractionEnabled = true
print(error.localizedDescription)
}
}
}
catch{
DispatchQueue.main.async {
SINGLETON.stopLoadingActivity(view)
}
}
}
}
You use wrong UTI: "com.instagram.photos" should be "com.instagram.photo".
Also don't forget to add URL scheme instagram into plist at Key LSApplicationQueriesSchemes.
Here you can find example of sharing into Instagram (method - (void)send).
Main code from there:
Objective-C:
// make a path into documents
NSString* homePath = [self _getpathToDocuments];
NSString* basePath = #"integration/instagram";
NSString* tmpFileName;
if ([self _isInstagramOnly]) {
tmpFileName = #"jumpto.igo";
} else {
tmpFileName = #"jumpto.ig";
}
NSString* dirPath = [NSString stringWithFormat:#"%#/%#", homePath, basePath];
NSString* docPath = [NSString stringWithFormat:#"%#/%#", dirPath, tmpFileName];
[[NSFileManager defaultManager] removeItemAtPath:docPath error:nil];
if ([[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:nil]) {
UIImage* tmpImg = [self _imageForSharing];
if([self _needResizeImage]){
tmpImg = [self _resizeImage:tmpImg];
}
NSData* imgData = [self generateImageData:tmpImg];
[[NSFileManager defaultManager] createFileAtPath:docPath contents:imgData attributes:nil];
NSURL* url = [NSURL fileURLWithPath:docPath isDirectory:NO ];
NSString *UTI = nil;
if ([self _isInstagramOnly]) {
UTI = #"com.instagram.exclusivegram";
} else {
UTI = #"com.instagram.photo";
}
NSString *captionString = #"Caption message";
UIDocumentInteractionController* dic = [UIDocumentInteractionController interactionControllerWithURL:documentFileURL];
dic.UTI = UTI;
dic.annotation = #{#"InstagramCaption" : captionString};
dic.delegate = self;
[self presentOpenInMenuFromRect:[self _getButtonRect] inView:self.view animated:YES];
}
Swift:
// Converted with Swiftify v1.0.6491 - https://objectivec2swift.com/
// make a path into documents
var homePath: String = _getpathToDocuments()
var basePath = "integration/instagram"
var tmpFileName = ""
if _isInstagramOnly() {
tmpFileName = "jumpto.igo"
}
else {
tmpFileName = "jumpto.ig"
}
var dirPath = "\(homePath)/\(basePath)"
var docPath = "\(dirPath)/\(tmpFileName)"
try? FileManager.default.removeItem(atPath: docPath)
if try? FileManager.default.createDirectory(atPath: dirPath, withIntermediateDirectories: true, attributes: nil) != nil {
var tmpImg: UIImage? = _imageForSharing()
if _needResizeImage() {
tmpImg = _resize(tmpImg)
}
var imgData = generateImageData(tmpImg)
FileManager.default.createFile(atPath: docPath, contents: imgData, attributes: nil)
var url = URL.fileURL(withPath: docPath, isDirectory: false)
var UTI: String? = nil
if _isInstagramOnly() {
UTI = "com.instagram.exclusivegram"
}
else {
UTI = "com.instagram.photo"
}
var captionString = "Caption message"
var dic = UIDocumentInteractionController(url: documentFileURL)
dic.uti = UTI
dic.annotation = ["InstagramCaption": captionString]
dic.delegate = self
presentOpenInMenu(from: _getButtonRect(), in: view, animated: true)
}

Get the filename of image saved to photos album

In modern iOS (2017),
here's actually the only way I know to save an image to the iOS photos system, and get the filename/path.
import UIKit
import Photos
func saveTheImage... () {
UIImageWriteToSavedPhotosAlbum(yourUIImage, self,
#selector(Images.image(_:didFinishSavingWithError:contextInfo:)),
nil)
}
func image(_ image: UIImage, didFinishSavingWithError error: NSError?, contextInfo: UnsafeRawPointer) {
guard error == nil else {
print("Couldn't save the image!")
return
}
doGetFileName()
}
func doGetFileName() {
let fo: PHFetchOptions = PHFetchOptions()
fo.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let r = PHAsset.fetchAssets(with: PHAssetMediaType.image, options: fo)
if let mostRecentThingy = r.firstObject {
PHImageManager.default().requestImageData(
for: mostRecentThingy,
options: PHImageRequestOptions(),
resultHandler: { (imagedata, dataUTI, orientation, info) in
if info!.keys.contains("PHImageFileURLKey") {
let path = info!["PHImageFileURLKey"] as! NSURL
print("Holy cow. The path is \(path)")
}
else { print("bizarre problem") }
})
}
else { print("unimaginable catastrophe") }
}
The problem with this is that it fails in racetrack conditions.
This is amazingly unwieldy, and it seems worrysome in a number of ways.
Is it really the way to go, today?
extension PHPhotoLibrary {
func save(imageData: Data, withLocation location: CLLocation?) -> Promise<PHAsset> {
var placeholder: PHObjectPlaceholder!
return Promise { fullfil, reject in
performChanges({
let request = PHAssetCreationRequest.forAsset()
request.addResource(with: .photo, data: imageData, options: .none)
request.location = location
placeholder = request.placeholderForCreatedAsset
}, completionHandler: { (success, error) -> Void in
if let error = error {
reject(error)
return
}
guard let asset = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: .none).firstObject else {
reject(NSError())
return
}
fullfil(asset)
})
}
}
}
I think you can do this with PHPhotoLibrary and PHObjectPlaceholder.
You just saved image programmatically, so you can get the image from camera and save it with your path:
//save image in Document Derectory
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(#"Get Path : %#",documentsDirectory);
//create Folder if Not Exist
NSError *error = nil;
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/YourFolder"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
NSString *yourPhotoName=#"YourPhotoName";
NSString* path= [dataPath stringByAppendingString:[NSString stringWithFormat:#"/%#.png",yourPhotoName]];
NSData* imageData = UIImagePNGRepresentation(imageToSaved); //which got from camera
[imageData writeToFile:path atomically:YES];
imagePath = path;
NSLog(#"Save Image Path : %#",imagePath);
Maybe this is a different approach but here's what I'm doing in my app and I'm satisfied with it:
func saveImage(image: UIImage, name: String) {
var metadata = [AnyHashable : Any]()
let iptcKey = kCGImagePropertyIPTCDictionary as String
var iptcMetadata = [AnyHashable : Any]()
iptcMetadata[kCGImagePropertyIPTCObjectName as String] = name
metadata[iptcKey] = iptcMetadata
let library = ALAssetsLibrary()
library.writeImage(toSavedPhotosAlbum: image.cgImage, metadata: metadata) { url, error in
// etc...
}
}
If you don't want to use ALAssetsLibrary, you'll probably be interested in this answer.

Copy Sqlite DataBase in Swift does not work properly

I am using following code for objective c to copy the sqlite database and it works fine. But when I convert this code to swift it shows error on Bool type.
Here is objective c code
- (void) copyDatabaseIfNeeded {
//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];
if(!success) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"database.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];
if (!success)
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
- (NSString *) getDBPath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
return [documentsDir stringByAppendingPathComponent:#"database.sqlite"];
}
Here is the CopyDataBase for Swift which is causing issue.
var fileManager = FileManager.default
var error: Error!
var dbPath = self.getDBPath()
var success = fileManager.fileExists(atPath: dbPath)
if !success {
var defaultDBPath = URL(fileURLWithPath: Bundle.main.resourcePath!).appendingPathComponent("CapalinoDataBase.sqlite").absoluteString
do {
success = try fileManager.copyItem(atPath: defaultDBPath, toPath: dbPath)
}
catch {
}
if !success {
assert(false, "Failed to create writable database file with message '\(error.localizedDescription)'.")
}
}
Please try this one.
func copyDatabse() {
let fileMgr = FileManager.default
if let path = Bundle.main.path(forResource: "db", ofType:"sqlite") {
do {
try fileMgr.copyItem(atPath: path, toPath: dbPath())
print("Copy success")
}
catch {
print(error.localizedDescription )
}
}
}
func dbPath() -> String {
let dirPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask, true)
let docsDir = dirPaths[0]
let destPath = (docsDir as NSString).appendingPathComponent("/db.sqlite")
return destPath
}
Best way to use SQLIte using single ton class in swift.
Download example
func methodToCreateDatabase() -> NSURL? {
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
if let documentDirectory:NSURL = urls.first { // No use of as? NSURL because let urls returns array of NSURL
// exclude cloud backup
do {
try documentDirectory.setResourceValue(true, forKey: NSURLIsExcludedFromBackupKey)
} catch _{
print("Failed to exclude backup")
}
// This is where the database should be in the documents directory
let finalDatabaseURL = documentDirectory.URLByAppendingPathComponent("contact.db")
if finalDatabaseURL.checkResourceIsReachableAndReturnError(nil) {
// The file already exists, so just return the URL
return finalDatabaseURL
} else {
// Copy the initial file from the application bundle to the documents directory
if let bundleURL = NSBundle.mainBundle().URLForResource("contact", withExtension: "db") {
do {
try fileManager.copyItemAtURL(bundleURL, toURL: finalDatabaseURL)
} catch _ {
print("Couldn't copy file to final location!")
}
} else {
print("Couldn't find initial database in the bundle!")
}
}
} else {
print("Couldn't get documents directory!")
}
return nil
}
Please try this one it is working on swift 3.0
func copyDatabaseIfNeeded() {
//Using NSFileManager we can perform many file system operations.
let fileManager = FileManager.default
let error: Error?
let dbPath: String = self.getDBPath()
var success: Bool = fileManager.fileExists(atPath: dbPath)
if !success {
let defaultDBPath: String = URL(fileURLWithPath: (Bundle.main.resourcePath)!).appendingPathComponent("database.sqlite").absoluteString
do {
success = try fileManager.copyItem(atPath: defaultDBPath, toPath: dbPath) as Any as! Bool
}
catch let error as NSError {
print("Ooops! Something went wrong: \(error)")
}
if !success {
assert(false, "Failed to create writable database file with message '\(error?.localizedDescription)'.")
}
}
}
func getDBPath() -> String {
let paths: [Any] = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDir: String = paths[0] as! String
return URL(fileURLWithPath: documentsDir).appendingPathComponent("database.sqlite").absoluteString
}

How to create directory using Swift code (NSFileManager)

I'm having some trouble with converting Objective-C code to create a directory for Swift.
Objective-C:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/MyFolder"];
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error];
Swift 5.0
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let docURL = URL(string: documentsDirectory)!
let dataPath = docURL.appendingPathComponent("MyFolder")
if !FileManager.default.fileExists(atPath: dataPath.path) {
do {
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch {
print(error.localizedDescription)
}
}
Swift 4.0
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsDirectory: AnyObject = paths[0] as AnyObject
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")!
do {
try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
}
Swift 3.0
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentsDirectory: AnyObject = paths[0]
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")!
do {
try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
}
Swift 2.1
You can create directory using below method:
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentsDirectory: AnyObject = paths[0]
let dataPath = documentsDirectory.stringByAppendingPathComponent("MyFolder")
do {
try NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription)
}
None of #Kampai and #Crashalot's answers worked for me.
The .absoluteString makes a url with file:// prefix and it cause exception while creating directory. Instead I've used .path method.
The fixed code for Swift 3
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let dataPath = documentsDirectory.appendingPathComponent("MyFolder")
do {
try FileManager.default.createDirectory(atPath: dataPath.path, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print("Error creating directory: \(error.localizedDescription)")
}
The accepted answer no longer compiles as the line with appendingPathComponent generates an error.
Here's a Swift 3 version that compiles:
fileprivate func createDir(dirName: String) {
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let dataPath = documentsDirectory.appendingPathComponent(dirName)
do {
try FileManager.default.createDirectory(atPath: dataPath.absoluteString, withIntermediateDirectories: false, attributes: nil)
} catch let error as NSError {
printError("Error creating directory: \(error.localizedDescription)")
}
}
Swift 4 :
NSSearchPathForDirectoriesInDomains returns an array of strings, not URLs.
appendingPathComponent to string makes app crash with the message
-[NSPathStore2 URLByAppendingPathComponent:]: unrecognized selector sent to instance
Here's a Swift 4 version that compiles:
let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
if let pathURL = URL.init(string: paths[0]) {
let dataURL = pathURL.appendingPathComponent("MyFolder")
do {
try FileManager.default.createDirectory(atPath: dataURL.absoluteString, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription);
}
}
else {
print("Error in getting path URL");
}
Simpler solution:
"~/Desktop/demo".expand.createDir()//Now you have a folder named demo on your desk
extension String{
func createDir(_ path:String){
do {
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
NSLog("Unable to create directory \(error.debugDescription)")
}
}
var expand:String {return NSString(string: self).expandingTildeInPath}
}
Swift 4
// DB Directory and Path
lazy var applicationDocumentsDirectory: URL = {
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectoryURL = urls[urls.count - 1] as URL
let dbDirectoryURL = documentDirectoryURL.appendingPathComponent("DB")
if FileManager.default.fileExists(atPath: dbDirectoryURL.path) == false{
do{
try FileManager.default.createDirectory(at: dbDirectoryURL, withIntermediateDirectories: false, attributes: nil)
}catch{
}
}
return dbDirectoryURL
}()
Swift 5
guard let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first else { return }
if let pathURL = URL.init(string: path) {
let dataURL = pathURL.appendingPathComponent("MyFolderName")
do {
try FileManager.default.createDirectory(atPath: dataURL.absoluteString, withIntermediateDirectories: true, attributes: nil)
} catch let error as NSError {
print(error.localizedDescription);
}
}
else {
print("Error in URL path");
}
For Other developers, Im gonna leave this here as it may help someone like me looking for a way to figure out where the folder is being created.
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDir = paths.firstObject as String
println("Path to the Documents directory\n\(documentsDir)")
(lldb) p path.absoluteString
(String) $R23 = "file:///Users/vincent/Library/Developer/CoreSimulator/Devices/4778E487-D1AD-41E7-9B91-18E08A400DEA/data/Containers/Data/Application/286AF87C-1134-4308-9656-DEE8F9FF046E/Documents/tide/927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE"
(lldb) p path.path
(String) $R25 = "/Users/vincent/Library/Developer/CoreSimulator/Devices/4778E487-D1AD-41E7-9B91-18E08A400DEA/data/Containers/Data/Application/286AF87C-1134-4308-9656-DEE8F9FF046E/Documents/tide/927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE"
(lldb)
so if you receive
Error Domain=NSCocoaErrorDomain Code=642 "You can’t save the file “927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE” because the volume is read only." UserInfo={NSFilePath=file:///Users/vincent/Library/Developer/CoreSimulator/Devices/4778E487-D1AD-41E7-9B91-18E08A400DEA/data/Containers/Data/Application/286AF87C-1134-4308-9656-DEE8F9FF046E/Documents/tide/927EBC30-EAD1-44BA-80B2-FD3D0A66E9DE, NSUnderlyingError=0x6000009cccf0 {Error Domain=NSPOSIXErrorDomain Code=30 "Read-only file system"}}
you need
path.absoluteString => path.path

Write a file on iOS

How do I write a file on iOS? I'm trying to do it with the following code but I'm doing something wrong:
char *saves = "abcd";
NSData *data = [[NSData alloc] initWithBytes:saves length:4];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"MyFile"];
[data writeToFile:appFile atomically:YES];
I have created MyFile.txt on resources.
May be this is useful to you.
//Method writes a string to a text file
-(void) writeToTextFile{
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/textfile.txt",
documentsDirectory];
//create content - four lines of text
NSString *content = #"One\nTwo\nThree\nFour\nFive";
//save content to the documents directory
[content writeToFile:fileName
atomically:NO
encoding:NSUTF8StringEncoding
error:nil];
}
//Method retrieves content from documents directory and
//displays it in an alert
-(void) displayContent{
//get the documents directory:
NSArray *paths = NSSearchPathForDirectoriesInDomains
(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//make a file name to write the data to using the documents directory:
NSString *fileName = [NSString stringWithFormat:#"%#/textfile.txt",
documentsDirectory];
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error:nil];
//use simple alert from my library (see previous post for details)
[ASFunctions alert:content];
[content release];
}
Your code is working at my end, i have just tested it. Where are you checking your changes? Use Documents directory path. To get path -
NSLog(#"%#",documentsDirectory);
and copy path from console and then open finder and press Cmd+shift+g and paste path here and then open your file
Swift
func saveFile() {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0] as! String
let fileName = "\(documentsDirectory)/textFile.txt"
let content = "Hello World"
content.writeToFile(fileName, atomically: false, encoding: NSUTF8StringEncoding, error: nil)
}
func loadFile() {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0] as! String
let fileName = "\(documentsDirectory)/textFile.txt"
let content: String = String(contentsOfFile: fileName, encoding: NSUTF8StringEncoding, error: nil)!
println(content)
}
Swift 2
func saveFile() {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
let fileName = "\(documentsDirectory)/textFile.txt"
let content = "Hello World"
do{
try content.writeToFile(fileName, atomically: false, encoding: NSUTF8StringEncoding)
}catch _ {
}
}
func loadFile()->String {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentsDirectory = paths[0]
let fileName = "\(documentsDirectory)/textFile.txt"
let content: String
do{
content = try String(contentsOfFile: fileName, encoding: NSUTF8StringEncoding)
}catch _{
content=""
}
return content;
}
Swift 3
func saveFile() {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let fileName = "\(documentsDirectory)/textFile.txt"
let content = "Hello World"
do{
try content.write(toFile: fileName, atomically: false, encoding: String.Encoding.utf8)
}catch _ {
}
}
func loadFile()->String {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let documentsDirectory = paths[0]
let fileName = "\(documentsDirectory)/textFile.txt"
let content: String
do{
content = try String(contentsOfFile: fileName, encoding: String.Encoding.utf8)
} catch _{
content=""
}
return content;
}
Try making
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"MyFile"];
as
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"MyFile.txt"];

Resources