Error while using .copyItemAtPath - ios

I am trying to copy a file (.plist) to a new directory but I am getting an error saying : Extra argument "error" in call. My code is below.
I searched apple's swift documentation. I guess .copyItemAtPath code changed and I need to use throws but I cant implement throws apperantly.
var folder = NSBundle.mainBundle().pathForResource(folderName, ofType: folderType)
//this is where i get error
NSFileManager.defaultManager().copyItemAtPath(folder, toPath: folderPath, error:nil)
print("Coppied")

With Swift2 you need to do something like this:
do{
try NSFileManager.defaultManager().copyItemAtPath(folder, toPath: folderPath)
print("Coppied")
}catch let error as NSError{
print(error.localizedDescription);
}

Related

How do I write a file in iOS using FileManager?

I have the following code with the results of the print statements in comments beside the statements:
let myImageData = FileManager.default.contents(atPath: myURL.absoluteString)
var mySaveToURL: URL = FileManager.default.url(forUbiquityContainerIdentifier: nil)!
mySaveToURL.appendPathComponent(myURL.pathComponents.last!)
print("mySaveToURL=", mySaveToURL) // mySaveToURL= file:///Users/shinehah/Library/Developer/CoreSimulator/Devices/693D4940-1B91-43E1-B5AD-88E9763046C7/data/Library/Mobile%20Documents/iCloud~us~gnolaum~TrialNotifications/ABF236AE-A6E7-403E-ADC4-5BAA5DC734B3.jpeg
let resultCreateFile = FileManager.default.createFile(atPath: mySaveToURL.absoluteString, contents: myImageData, attributes: nil)
print("resultCreateFile=", resultCreateFile) // resultCreateFile= false
do {
try FileManager.default.copyItem(at: myURL, to: mySaveToURL)
print("copy success!") // copy success!
} catch {
print(error.localizedDescription)
}
As you can see I am not able to successfully execute the createFile() method of FileManager but was able to successfully execute the copyItem() method to the same URL.
What do I check to be able to figure out how to get the createFile() method to work?
The error occurs because you are using the wrong API. To get the path of a file system URL you have to use path.
let resultCreateFile = FileManager.default.createFile(atPath: mySaveToURL.path, contents: myImageData, attributes: nil)
However there is no reason to create the file explicitly. Just copy the other file.

Error when attempting to move item using FileManager

I have a few items that are saved to the documents directory. I currently need those to be moved programmatically to another directory. I created the new directory successfully, but it doesn't seem to be looking at that when using FileManager.default.moveItem.
Code used to created directory.
let path = getDocumentsDirectory().appendingPathComponent("Media").path
do{
try FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: false, attributes: nil)
print("\nDIRECTORY 'Media' CREATED")
}catch {
print("\nDIRECTORY 'Media' WAS NOT ABLE TO BE CREATED")
print("ERROR - \(error)")
}
I use this code to check my URL.
let mediaURL = getDocumentsDirectory().appendingPathComponent("Media")
print("\nMEDIA URL: \(mediaURL)")
Which outputs this.
MEDIA URL:file:///Users/joseph/Library/Developer/CoreSimulator/Devices/552B72BF-8929-40EE-A75B-4574D3D2918A/data/Containers/Data/Application/E168B872-6A1D-4D78-B460-D45194088E5B/Documents/Media/
Here is the code I'm using to move the items.
do{
try FileManager.default.moveItem(at: url, to: mediaURL)
print("\nFILE MOVED TO NEW MEDIA PATH SUCCESSFULLY")
}catch {
print("\nCOULDN'T MOVE FILE TO NEW MEDIA PATH")
print("ERROR - \(error)")
}
Here is the error I'm receiving for each item that I try to move.
COULDN'T MOVE FILE TO NEW MEDIA PATH
ERROR - Error Domain=NSCocoaErrorDomain Code=516 "“image_5” couldn’t be moved to “Documents” because an item with the same name already exists." UserInfo= {NSSourceFilePathErrorKey=/Users/joseph/Library/Developer/CoreSimulator/Devices/552B72BF-8929-40EE-A75B-4574D3D2918A/data/Containers/Data/Application/E168B872-6A1D-4D78-B460-D45194088E5B/Documents/image_5, NSUserStringVariant=(
Move
), NSDestinationFilePath=/Users/joseph/Library/Developer/CoreSimulator/Devices/552B72BF-8929-40EE-A75B-4574D3D2918A/data/Containers/Data/Application/E168B872-6A1D-4D78-B460-D45194088E5B/Documents/Media, NSFilePath=/Users/joseph/Library/Developer/CoreSimulator/Devices/552B72BF-8929-40EE-A75B-4574D3D2918A/data/Containers/Data/Application/E168B872-6A1D-4D78-B460-D45194088E5B/Documents/image_5, NSUnderlyingError=0x60000024fff0 {Error Domain=NSPOSIXErrorDomain Code=17 "File exists"}}
The media directory should be empty, as it is newly created, so the error I'm receiving is a bit confusing. It's also saying it's trying to move it to 'Documents', but it should be moving to 'Media'.What is causing this issue, and how can I resolve it? I'm just trying to move the items saved in 'Documents' to the new directory, 'Media'.
You must append the file name to the destination URL. Per the docs:
The new location for the item in srcURL. The URL in this parameter must not be a file reference URL and must include the name of the file or directory in its new location. This parameter must not be nil.
Delete the old file if exist
let url = NSUrl(string: "...")
if NSFileManager.defaultManager().fileExistsAtPath(url.path!) {
try! NSFileManager.defaultManager().removeItemAtURL(url)
}
Update:
Swift 5.1.2
let url = URL(string: mp3FilePath)
if FileManager.default.fileExists(atPath: url!.path) {
try! FileManager.default.removeItem(at: url!)
}
This worked for me - Add the name of file too in destination path
let nameFile = (songPath as NSString).lastPathComponent
let fileDest = destinationDirectoryPath + "/" + nameFile
//Now move the song files
try fileManager.moveItem(atPath: sourceFilePath, toPath: fileDest)

Try and Catch with NSUrl(fileURLWithPath)

I've been trying to implement try and catch in the following code
if let s = songId {
let track: NSURL!
track = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(s, ofType: "mp3")!)
.............
}
I came up with the following code:
do {
track = try NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(s, ofType: "mp3")!)
}
catch let error as NSError {
print("NSURL Error: \(error.localizedDescription)")
}
But I get the following warnings:
No calls to throwing functions occur within 'try' expression
and
'catch' block is unreachable because no errors are thrown in 'do' block
And this is strange to me, because this construction usually works.
Only with NSURL this construction isn't working. And I can't figure out why this is happening. Maybe it has something to do with it being an optional, but im not sure.
I can't figure out how to solve this. I need to use a try/catch or something similar, but I can't figure it out how to make it work.
I saw some similar problems on Google, but it didnt gave me an answer.
So my question is: How can I implement a try/catch construction or something similar with NSURL?
Thanks in advance.
There are no methods used that marked with throws keyword at the definition. So it really does not make much sense to wrap your code with try-catch. I would recommend to consider this:
let s = "song"
guard let trackURL = NSBundle.mainBundle().URLForResource(s, withExtension: "mp3") else {
print("File not found in the app bundle: \(s).mp3")
return false
}
Does it help?
That initializer doesn't fail and doesn't throw or fail so a try/catch block is unnecessary. The declaration is:
public init(fileURLWithPath path: String)
If it could throw an error is would be declared as:
public init(fileURLWithPath path: String) throws
Or if it might fail without throwing an error it would be declared as:
public init?(fileURLWithPath path: String)
If you're certain that the bundle will always contain the track you're looking for then you can just use
let track = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource(s, ofType: "mp3")!)

NSFileManager fileExistsAtPath unable to overwrite existing file in Swift 2

Hello I'm upgrading my existing code to Swift 2, and I need some help with the copy of a file inside the DocumentDirectoy.
This is converted code I'm using to check if the file exists, and if it does, we should copy it either way, but it keeps returning an error saying the file exists, which it is true, but we need to overwrite it.
func copyXMLFile()
{
// Get a reference for the Document directory
let rootPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, .UserDomainMask, true)[0]
// Get a reference for the data.xml file
xmlPathInDocument = rootPath.stringByAppendingString("data.xml")
if NSFileManager.defaultManager().fileExistsAtPath(xmlPathInDocument){
print("xml file exists")
let xmlPathInBundle = NSBundle.mainBundle().pathForResource("data", ofType: "xml")!
do {
// copy file from main bundle to documents directory
print("copy")
try NSFileManager.defaultManager().copyItemAtPath(xmlPathInBundle, toPath: xmlPathInDocument)
} catch let error as NSError {
// Catch fires here, with an NSErrro being thrown
print("error occurred, here are the details:\n \(error)")
}
}
else
{
// copy the file either way
let xmlPathInBundle = NSBundle.mainBundle().pathForResource("data", ofType: "xml")!
do {
// copy file from main bundle to documents directory
print("copy")
try NSFileManager.defaultManager().copyItemAtPath(xmlPathInBundle, toPath: xmlPathInDocument)
} catch let error as NSError {
// Catch fires here, with an NSErrro being thrown
print("error occurred, here are the details:\n \(error)")
}
}
}
error occurred, here are the details:
Error Domain=NSCocoaErrorDomain Code=516 "The operation couldn’t be
completed. (Cocoa error 516.)" UserInfo=0x7a67b680
{NSSourceFilePathErrorKey=/Users/User1/Library/Developer/CoreSimulator/Devices/0E591E5B-2E2F-4CCB-9099-95CE1EA3F557/data/Containers/Bundle/Application/E3C8FAE4-703D-46CA-AC37-A1C96A74E6BE/myApp.app/data.xml,
NSUserStringVariant=(
Copy ), NSFilePath=/Users/User1/Library/Developer/CoreSimulator/Devices/0E591E5B-2E2F-4CCB-9099-95CE1EA3F557/data/Containers/Bundle/Application/E3C8FAE4-703D-46CA-AC37-A1C96A74E6BE/myApp.app/data.xml,
NSDestinationFilePath=/Users/User1/Library/Developer/CoreSimulator/Devices/0E591E5B-2E2F-4CCB-9099-95CE1EA3F557/data/Containers/Data/Application/09F690B3-BDD8-4482-ADDE-E33F30D4B873/Documentsdata.xml,
NSUnderlyingError=0x7a67dd80 "The operation couldn’t be completed.
File exists"}
Please HELP!
Implement NSFileManagerDelegate and the delegate method
optional func fileManager(_ fileManager: NSFileManager,
shouldProceedAfterError error: NSError,
copyingItemAtURL srcURL: NSURL,
toURL dstURL: NSURL) -> Bool
and return true
Alternatively you could use
func replaceItemAtURL(_ originalItemURL: NSURL,
withItemAtURL newItemURL: NSURL,
backupItemName backupItemName: String?,
options options: NSFileManagerItemReplacementOptions,
resultingItemURL resultingURL: AutoreleasingUnsafeMutablePointer<NSURL?>) throws

Swift: copying files gives Cocoa Error 262

I'm trying to move my files up a level in some random directory in the default Documents directory. But when copying, Swift gave me the error Cocoa Error 262: NSFileReadUnsupportedSchemeError. Why did I get this error? I ran a quick search and pretty much everyone who'd encountered this problem was trying to copy files out of the camera roll, but I'm not. Any thoughts? Thanks in advance.
Code here:
private func copyFilesInDirectory(fromDir: String, toDirectory toDir: String, withCompletionHandler handler: ()->()){
println("from: \(fromDir)\nto: \(toDir)")
var error: NSError?
var contents = fileManager.contentsOfDirectoryAtPath(fromDir, error: &error)
if let dirContents = contents{
let enumerator = (dirContents as NSArray).objectEnumerator()
while let file = enumerator.nextObject() as? String{
let filePath = fromDir.stringByAppendingString("/\(file)")
println("copying \(filePath)")
if(fileManager.copyItemAtURL(NSURL(fileURLWithPath: filePath)!, toURL: NSURL(string: toDir)!, error: &error)){
println("COPIED")
}
else{
println("COPY ERROR: \(error!.localizedDescription)")
}
}
handler()
}
}
and here's the log if anyone's interested:
from: /Users/dolce/Library/Developer/CoreSimulator/Devices/05566649-BABB-44BE-BE6F-AFF7B41E3065/data/Containers/Data/Application/F5A83C94-C177-4826-BDD5-3A50E7508239/Documents/Hello/tmp
to: /Users/dolce/Library/Developer/CoreSimulator/Devices/05566649-BABB-44BE-BE6F-AFF7B41E3065/data/Containers/Data/Application/F5A83C94-C177-4826-BDD5-3A50E7508239/Documents/Hello
copying /Users/dolce/Library/Developer/CoreSimulator/Devices/05566649-BABB-44BE-BE6F-AFF7B41E3065/data/Containers/Data/Application/F5A83C94-C177-4826-BDD5-3A50E7508239/Documents/Hello/tmp/test.png
COPY ERROR: The operation couldn’t be completed. (Cocoa error 262.)
The toURL parameter of copyItemAtURL() must not be the destination
directory, but the URL of the destination file. This can be
created with
let destPath = toDir.stringByAppendingPathComponent(file)
You should also replace
let filePath = fromDir.stringByAppendingString("/\(file)")
with
let filePath = fromDir.stringByAppendingPathComponent(file)
There is also a copyItemAtPath() method which saves you from
converting the paths to URLs.
On an iOS device, the simple answer is you can't do that. On the simulator things are little different. What you're probably dealing with is file permissions on the directory you're trying to write to.
As a general rule on iOS, you can write to the designated directories like the documents/caches and nothing else.

Resources