Copy Sqlite DataBase in Swift does not work properly - ios

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
}

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

How to properly send an image to CloudKit as CKAsset?

I have an image (UIImage and it's url too) and I'm trying to send it to CloudKit as a CKAsset but I'm having this error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Non-file URL'. Here is the code:
override func viewDidLoad() {
super.viewDidLoad()
send2Cloud()
}
func send2Cloud() {
let newUser = CKRecord(recordType: "User")
let url = NSURL(string: self.photoURL)
let asset = CKAsset(fileURL: url!)
newUser["name"] = self.name
newUser["photo"] = asset
let publicData = CKContainer.defaultContainer().publicCloudDatabase
publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("User saved")
})
} else {
print(error?.localizedDescription)
}
})
}
I have the URL, I can print it, copy and paste to my navigator and it will show my image! So, I don't know what is happening here...
It would be easier if I worked with an UIImage instead of it's URL? Because, as I sais before, I have both of them! Any help is very appreciated! Thanks, guys!!
In my experience, the only way to save upload UIImage as a CKAsset is to:
Save the image temporarily to disk
Create the CKAsset
Delete the temporary file
let data = UIImagePNGRepresentation(myImage); // UIImage -> NSData, see also UIImageJPEGRepresentation
let url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat")
do {
try data!.writeToURL(url, options: [])
} catch let e as NSError {
print("Error! \(e)");
return
}
newUser["photo"] = CKAsset(fileURL: url)
// ...
publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in
// Delete the temporary file
do { try NSFileManager.defaultManager().removeItemAtURL(url) }
catch let e { print("Error deleting temp file: \(e)") }
// ...
}
I filed a bug report a few months ago requesting the ability to initialize CKAsset from in-memory NSData, but it hasn't been done yet.
This is Objective C version of how to save an image to Cloudkit
This took quite a bit of digging as there is not much info to go on, but this works
if([results count] <= 0) {
NSLog(#"this Record doesnt exist so add it ok!! %#", error);
CKRecordID *wellKnownID = [[CKRecordID alloc]
initWithRecordName:idString];
CKRecord *entitiesName = [[CKRecord alloc] initWithRecordType:#"mySavedDetails"
recordID:wellKnownID];
[entitiesName setObject:idString
forKey:#"myDetailsId"];
[entitiesName setObject:self.myName.text
forKey:#"myName"];
if (myUIImage.image != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"test.png" ];
NSData* data = UIImagePNGRepresentation(myUIImage.image.image);
[data writeToFile:path atomically:YES];
//so we get the full path of the uiimage
NSLog(#"Path details %#",path);
NSURL* myImagePath = nil;
myImagePath =
[[NSBundle mainBundle] URLForResource:path
withExtension:#"png"];
//here we change the path of Image which is a string to a URL
NSURL *yourURL = [NSURL fileURLWithPath:path];
CKAsset* myImageAsset = nil;
myImageAsset =
[[CKAsset alloc] initWithFileURL:yourURL];
[entitiesName setObject: myImageAsset
forKey:#"myImage"];
[publicDatabase saveRecord: entitiesName
completionHandler:^(CKRecord *savedState, NSError *error) {
if (error) {
NSLog(#"ERROR SAVING: %#", error);
}
}];
}
}
I did something a tad different: I made a class that you can use in multiple places, and thanks to the fact that Swift has deinitialization that works (unlike C++), it cleans up after itself:
//
// ImageAsset.swift
//
import CloudKit
import UIKit
class ImageAsset {
let image:UIImage
var url:NSURL?
var asset:CKAsset? {
get {
let data = UIImagePNGRepresentation(self.image)
self.url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat")
if let url = self.url {
do {
try data!.writeToURL(url, options: [])
} catch let e as NSError {
print("Error! \(e)")
}
return CKAsset(fileURL: url)
}
return nil
}
}
init(image:UIImage){
self.image = image
}
deinit {
if let url = self.url {
do {
try NSFileManager.defaultManager().removeItemAtURL(url) }
catch let e {
print("Error deleting temp file: \(e)")
}
}
}
}
Here's a unit test that exercises it (presumes there is an image named stopwatch in the test target):
//
// ImageExtensionTests.swift
//
import CloudKit
import XCTest
#testable import BudgetImpactEstimator
class ImageExtensionTests: XCTestCase {
let testImageName = "stopwatch" // provide the name of an image in test bundle
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testConvertingImageToAsset() {
guard let image = UIImage(named: self.testImageName) else {
XCTFail("failed to load image")
return
}
let imageAsset = ImageAsset(image: image)
XCTAssertNotNil(imageAsset)
guard let asset = imageAsset.asset else {
XCTFail("failed to get asset from image")
return
}
print("constructed asset: \(asset)")
}
}
Was originally going to do it as an extension on UIImage but then the deinit made me move to a class.

Merge folders with NSFileManager, overwrite only existing files

Basically I am looking for a way to merge two folder in the filesystem with the cocoa API:
I have a folder containing files and sub-folders, which I want to copy to a different location in the filesystem.
At my destination path, an equally-named folder already exists, which may contain files and folders as well.
Now I want to overwrite existing files inside my destination folder (or its subfolders) with the new content of my source folder if they have the same name.
All the rest of the files I want to leave untouched.
sourcefolder
|
- file1
- subfolder
- file2
destinationfolder
|
- file3
- subfolder
- file2
- file4
resultingfolder
|
- file1
- file3
- subfolder
- file2 <-- version from source folder
- file4
How can I do that?
Thanks a lot for your help!
I searched everywhere but found nothing. So I came up with my own solution, utilizing NSDirectoryEnumerator. This should work the diagram (overriding old files). Hope it helps.
- (void)mergeContentsOfPath:(NSString *)srcDir intoPath:(NSString *)dstDir error:(NSError**)err {
NSLog(#"- mergeContentsOfPath: %#\n intoPath: %#", srcDir, dstDir);
NSFileManager *fm = [NSFileManager defaultManager];
NSDirectoryEnumerator *srcDirEnum = [fm enumeratorAtPath:srcDir];
NSString *subPath;
while ((subPath = [srcDirEnum nextObject])) {
NSLog(#" subPath: %#", subPath);
NSString *srcFullPath = [srcDir stringByAppendingPathComponent:subPath];
NSString *potentialDstPath = [dstDir stringByAppendingPathComponent:subPath];
// Need to also check if file exists because if it doesn't, value of `isDirectory` is undefined.
BOOL isDirectory = ([[NSFileManager defaultManager] fileExistsAtPath:srcFullPath isDirectory:&isDirectory] && isDirectory);
// Create directory, or delete existing file and move file to destination
if (isDirectory) {
NSLog(#" create directory");
[fm createDirectoryAtPath:potentialDstPath withIntermediateDirectories:YES attributes:nil error:err];
if (err && *err) {
NSLog(#"ERROR: %#", *err);
return;
}
}
else {
if ([fm fileExistsAtPath:potentialDstPath]) {
NSLog(#" removeItemAtPath");
[fm removeItemAtPath:potentialDstPath error:err];
if (err && *err) {
NSLog(#"ERROR: %#", *err);
return;
}
}
NSLog(#" moveItemAtPath");
[fm moveItemAtPath:srcFullPath toPath:potentialDstPath error:err];
if (err && *err) {
NSLog(#"ERROR: %#", *err);
return;
}
}
}
}
A solution in Swift 3
let merger = FoldersMerger(actionType: .copy, conflictResolution: .keepSource)
merger.merge(atPath: sourceFolder, toPath: destinationFolder)
class FoldersMerger {
enum ActionType { case move, copy }
enum ConflictResolution { case keepSource, keepDestination }
private let fileManager = FileManager()
private var actionType: ActionType!
private var conflictResolution: ConflictResolution!
private var deleteEmptyFolders: Bool!
init(actionType: ActionType = .move, conflictResolution: ConflictResolution = .keepDestination, deleteEmptyFolders: Bool = false) {
self.actionType = actionType
self.conflictResolution = conflictResolution
self.deleteEmptyFolders = deleteEmptyFolders
}
func merge(atPath: String, toPath: String) {
let pathEnumerator = fileManager.enumerator(atPath: atPath)
var folders: [String] = [atPath]
while let relativePath = pathEnumerator?.nextObject() as? String {
let subItemAtPath = URL(fileURLWithPath: atPath).appendingPathComponent(relativePath).path
let subItemToPath = URL(fileURLWithPath: toPath).appendingPathComponent(relativePath).path
if isDir(atPath: subItemAtPath) {
if deleteEmptyFolders! {
folders.append(subItemAtPath)
}
if !isDir(atPath: subItemToPath) {
do {
try fileManager.createDirectory(atPath: subItemToPath, withIntermediateDirectories: true, attributes: nil)
NSLog("FoldersMerger: directory created: %#", subItemToPath)
}
catch let error {
NSLog("ERROR FoldersMerger: %#", error.localizedDescription)
}
}
else {
NSLog("FoldersMerger: directory %# already exists", subItemToPath)
}
}
else {
if isFile(atPath:subItemToPath) && conflictResolution == .keepSource {
do {
try fileManager.removeItem(atPath: subItemToPath)
NSLog("FoldersMerger: file deleted: %#", subItemToPath)
}
catch let error {
NSLog("ERROR FoldersMerger: %#", error.localizedDescription)
}
}
do {
try fileManager.moveItem(atPath: subItemAtPath, toPath: subItemToPath)
NSLog("FoldersMerger: file moved from %# to %#", subItemAtPath, subItemToPath)
}
catch let error {
NSLog("ERROR FoldersMerger: %#", error.localizedDescription)
}
}
}
if deleteEmptyFolders! {
folders.sort(by: { (path1, path2) -> Bool in
return path1.characters.split(separator: "/").count < path2.characters.split(separator: "/").count
})
while let folderPath = folders.popLast() {
if isDirEmpty(atPath: folderPath) {
do {
try fileManager.removeItem(atPath: folderPath)
NSLog("FoldersMerger: empty dir deleted: %#", folderPath)
}
catch {
NSLog("ERROR FoldersMerger: %#", error.localizedDescription)
}
}
}
}
}
private func isDir(atPath: String) -> Bool {
var isDir: ObjCBool = false
let exist = fileManager.fileExists(atPath: atPath, isDirectory: &isDir)
return exist && isDir.boolValue
}
private func isFile(atPath: String) -> Bool {
var isDir: ObjCBool = false
let exist = fileManager.fileExists(atPath: atPath, isDirectory: &isDir)
return exist && !isDir.boolValue
}
private func isDirEmpty(atPath: String) -> Bool {
do {
return try fileManager.contentsOfDirectory(atPath: atPath).count == 0
}
catch _ {
return false
}
}
}
Look at the file manager methods and instead of using the default file manager, create your own with alloc/init, set a delegate, and use the delegate methods.

Delete specified file from document directory

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

Swift 3: Upload Image to cloudkit [duplicate]

I have an image (UIImage and it's url too) and I'm trying to send it to CloudKit as a CKAsset but I'm having this error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Non-file URL'. Here is the code:
override func viewDidLoad() {
super.viewDidLoad()
send2Cloud()
}
func send2Cloud() {
let newUser = CKRecord(recordType: "User")
let url = NSURL(string: self.photoURL)
let asset = CKAsset(fileURL: url!)
newUser["name"] = self.name
newUser["photo"] = asset
let publicData = CKContainer.defaultContainer().publicCloudDatabase
publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("User saved")
})
} else {
print(error?.localizedDescription)
}
})
}
I have the URL, I can print it, copy and paste to my navigator and it will show my image! So, I don't know what is happening here...
It would be easier if I worked with an UIImage instead of it's URL? Because, as I sais before, I have both of them! Any help is very appreciated! Thanks, guys!!
In my experience, the only way to save upload UIImage as a CKAsset is to:
Save the image temporarily to disk
Create the CKAsset
Delete the temporary file
let data = UIImagePNGRepresentation(myImage); // UIImage -> NSData, see also UIImageJPEGRepresentation
let url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat")
do {
try data!.writeToURL(url, options: [])
} catch let e as NSError {
print("Error! \(e)");
return
}
newUser["photo"] = CKAsset(fileURL: url)
// ...
publicData.saveRecord(newUser, completionHandler: { (record: CKRecord?, error: NSError?) in
// Delete the temporary file
do { try NSFileManager.defaultManager().removeItemAtURL(url) }
catch let e { print("Error deleting temp file: \(e)") }
// ...
}
I filed a bug report a few months ago requesting the ability to initialize CKAsset from in-memory NSData, but it hasn't been done yet.
This is Objective C version of how to save an image to Cloudkit
This took quite a bit of digging as there is not much info to go on, but this works
if([results count] <= 0) {
NSLog(#"this Record doesnt exist so add it ok!! %#", error);
CKRecordID *wellKnownID = [[CKRecordID alloc]
initWithRecordName:idString];
CKRecord *entitiesName = [[CKRecord alloc] initWithRecordType:#"mySavedDetails"
recordID:wellKnownID];
[entitiesName setObject:idString
forKey:#"myDetailsId"];
[entitiesName setObject:self.myName.text
forKey:#"myName"];
if (myUIImage.image != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString* path = [documentsDirectory stringByAppendingPathComponent:
#"test.png" ];
NSData* data = UIImagePNGRepresentation(myUIImage.image.image);
[data writeToFile:path atomically:YES];
//so we get the full path of the uiimage
NSLog(#"Path details %#",path);
NSURL* myImagePath = nil;
myImagePath =
[[NSBundle mainBundle] URLForResource:path
withExtension:#"png"];
//here we change the path of Image which is a string to a URL
NSURL *yourURL = [NSURL fileURLWithPath:path];
CKAsset* myImageAsset = nil;
myImageAsset =
[[CKAsset alloc] initWithFileURL:yourURL];
[entitiesName setObject: myImageAsset
forKey:#"myImage"];
[publicDatabase saveRecord: entitiesName
completionHandler:^(CKRecord *savedState, NSError *error) {
if (error) {
NSLog(#"ERROR SAVING: %#", error);
}
}];
}
}
I did something a tad different: I made a class that you can use in multiple places, and thanks to the fact that Swift has deinitialization that works (unlike C++), it cleans up after itself:
//
// ImageAsset.swift
//
import CloudKit
import UIKit
class ImageAsset {
let image:UIImage
var url:NSURL?
var asset:CKAsset? {
get {
let data = UIImagePNGRepresentation(self.image)
self.url = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent(NSUUID().UUIDString+".dat")
if let url = self.url {
do {
try data!.writeToURL(url, options: [])
} catch let e as NSError {
print("Error! \(e)")
}
return CKAsset(fileURL: url)
}
return nil
}
}
init(image:UIImage){
self.image = image
}
deinit {
if let url = self.url {
do {
try NSFileManager.defaultManager().removeItemAtURL(url) }
catch let e {
print("Error deleting temp file: \(e)")
}
}
}
}
Here's a unit test that exercises it (presumes there is an image named stopwatch in the test target):
//
// ImageExtensionTests.swift
//
import CloudKit
import XCTest
#testable import BudgetImpactEstimator
class ImageExtensionTests: XCTestCase {
let testImageName = "stopwatch" // provide the name of an image in test bundle
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testConvertingImageToAsset() {
guard let image = UIImage(named: self.testImageName) else {
XCTFail("failed to load image")
return
}
let imageAsset = ImageAsset(image: image)
XCTAssertNotNil(imageAsset)
guard let asset = imageAsset.asset else {
XCTFail("failed to get asset from image")
return
}
print("constructed asset: \(asset)")
}
}
Was originally going to do it as an extension on UIImage but then the deinit made me move to a class.

Resources