Writing String gives me error, writing image not - swift

I have this code:
let image = UIImage(data: downloadedImage!)
let convertImage = UIImagePNGRepresentation(image!)
let pathUIDImage = self.getDocumentsDirectory().appendingPathComponent(playersUID + "Image")
try? convertImage!.write(to: pathUIDImage) //working
let playersUIDImageVersion = "1"
var pathUIDImageVersion = self.getDocumentsDirectory().appendingPathComponent(playersUID + "ImageVersion")
try? playersUIDImageVersion.write(to: pathUIDImageVersion) //error
The error is:
Cannot convert value of type "URL" to expected instrument type "inout_"
When I replace try? playersUIDImageVersion to try? convertImage! the error is gone. Is there a difference between writing different types of values to the directory? Thank you. Below the function getDocumentsDirectory
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}

The write function of String is different, it requires additional parameters atomically and encoding.
try? playersUIDImageVersion.write(to: pathUIDImageVersion, atomically: true, encoding: .utf8)
In such a case retype the function and see what Xcode suggests for code completion.
Besides it's highly recommended to use always an appropriate file extension (.png, .txt).

Related

swift save file after download Alamofire

download and save file
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
// var fileURL = self.createFolder(folderName: downloadFolderName)
var fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileName = URL(string : currentFile.link )
fileURL = fileURL.appendingPathComponent((fileName?.lastPathComponent)!)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(currentDownloadedFile.link , to: destination).response(completionHandler: { (DefaultDownloadResponse) in
print("res ",DefaultDownloadResponse.destinationURL!);
completion(true)
})
but when i wont to check file in this dirrectory i get nil
let filemanager:FileManager = FileManager()
let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let files = filemanager.enumerator(atPath: fileURL.absoluteString) // = nil
while let file = files?.nextObject() {
print(file)
}
if i save local path to file and after reload app wont to share it -> "share" app cant send file (mb cant found it)
can u pls help me. how it works ? why when i print all files he didnt find it? how to save file who after reboot app it will be saved in same link
You are using the wrong API
For file system URLs use always path, absoluteString returns the full string including the scheme (e. g. file:// or http://)
let files = filemanager.enumerator(atPath: fileURL.path)

Get the Contents of multiple files in directory

I need to get the contents from multiple plist files and bring them into a single dictionary which is then displayed in a tableView
Using this code I can manually get each path and the contents of the file but I need to be able to do this for all plist files in the directory not just these predefined ones.
func getFiles() {
let documentDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let path = documentDirectory.appending("/MainFolder/File1.plist")
let path1 = documentDirectory.appending("/MainFolder/File2.plist")
let path2 = documentDirectory.appending("/MainFolder/File3.plist")
tableViewData = [NSDictionary(contentsOfFile: path) as! [String : String], NSDictionary(contentsOfFile: path1) as! [String : String], NSDictionary(contentsOfFile: path2) as! [String : String]]
print(tableViewData)
}
I the display tableViewData in my tableView which gives me each files contents on its own row.
I am guessing I probably need an array of file urls filtered by .plist and then some way to get the contents of each file into a [String : String] dictionary.
I am new to swift, any help or a better way to do this would be great
First of all don't use outdated and objective-c-ish NSSearchPathForDirectoriesInDomains in Swift. Use the modernFileManager API.
Second of all don't use objective-c-ish NSDictionary(contentsOf to read property list data. Use PropertyListSerialization.
The function throws that means it hands over all possible errors to the caller. It filters the URLs in the directory by the plist extension and uses the map function to get the dictionary for each URL.
func getFiles() throws {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let subFolderURL = documentDirectory.appendingPathComponent("MainFolder")
let allFiles = try FileManager.default.contentsOfDirectory(at: subFolderURL, includingPropertiesForKeys: nil)
let properListFiles = allFiles.filter{$0.pathExtension == "plist"}
tableViewData = try properListFiles.compactMap { url -> [String:String]? in
let data = try Data(contentsOf: url)
return try PropertyListSerialization.propertyList(from: data, format: nil) as? [String:String]
}
print(tableViewData)
}
Be aware that in sandboxed apps the Documents folder is located in the application container.
You can read all the plists and iterate over them adding their contents either to 1 array, or to an already kept dictionary.
do {
let directoryContents = try FileManager.default.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil, options: [])
let allPlistFiles = directoryContents.filter{ $0.pathExtension == "plist" }
var aPlistArray = []
for aPlist in allPlistFiles {
aPlistArray.append(NSDictionary(contentsOfFile: path) as! [String : String])
}
} catch {
print(error)
}

cannot convert value of type "String" to expected argument type "URL"

The statement in do is not being executed. Anyone can help me with this problem? Thanks a lot!
class func copyFile(fileName: NSString){
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
guard documentsURL.count != 0 else{
return
}
let finalDatabaseURL = documentsURL.first!.appendingPathComponent(fileName as String)
if !((try? finalDatabaseURL.checkResourceIsReachable()) ?? false){
print("Database does not exist in documents")
let documentsURL = Bundle.main.resourceURL?.appendingPathComponent(fileName as String)
do{
try fileManager.copyItem(at: (documentsURL?.path)!, to: finalDatabaseURL.path)
}catch let error as NSError{
print("Couldn't copy file to final location!Error:\(error.description)")
}
}else{
print("Database file found at path:\(finalDatabaseURL.path)")
}
}
copyItem(at srcURL: URL, to dstURL: URL) takes both URL parameters and you are passing strings.
Either you use this.
try fileManager.copyItem(at: documentsURL!, to: finalDatabaseURL)
or
try fileManager.copyItem(atPath: (documentsURL?.path)!, toPath: finalDatabaseURL.path)

How to start recoding a AVCaptureSession in Swift 3?

This is the method I'm trying to fire:
mMovieFileOutput?.startRecording(toOutputFileURL: URL(mov_path), recordingDelegate: self)
I'm getting this error:
Argument labels '(_:)' do not match any available overloads
Dose anyone know what arguments I need?
You need to use one of the valid initializers for URL.
Here is some basic Swift 3 code to demonstrate this.
var videoFileOutput = AVCaptureMovieFileOutput()
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let filename = NSUUID().uuidString + ".mov"
let filePath = documentsURL.appendingPathComponent(filename)
videoFileOutput.startRecording(toOutputFileURL: filePath, recordingDelegate: self)
If you want to use some other URL initializer for some reason, just use a valid one. As #Anton said, URL(fileURLWithPath: "") is correct initializer for a path.
Cheers

How to get user home directory path (Users/"user name") without knowing the username in Swift3

I am making a func that edits a text file in the Users/johnDoe Dir.
let filename = "random.txt"
let filePath = "/Users/johnDoe"
let replacementText = "random bits of text"
do {
try replacementText.write(toFile: filePath, atomically: true, encoding: .utf8)
}catch let error as NSError {
print(error: + error.localizedDescription)
}
But I want to be able to have the path universal. Something like
let fileManager = FileManager.default
let downloadsURL = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first! as NSURL
let downloadsPath = downloadsURL.path
but for the JohnDoe folder. I haven't been able to find any documentation on how to do this. The closest thing I could find mentioned using NSHomeDirectory(). And I am not sure how to use it in this context.
when I try adding it like...
let fileManager = FileManager.default
let downloadsURL = FileManager.default.urls(for: NSHomeDirectory, in: .userDomainMask).first! as NSURL
let downloadsPath = downloadsURL.path
I get an error:
"Cannot Convert value of type 'String' to expected argument type 'FileManager.SearchPathDirectory'"
I've tried it .NSHomeDirectory, .NSHomeDirectory(), NShomeDirectory, NShomeDirectory()
You can use FileManager property homeDirectoryForCurrentUser
let homeDirURL = FileManager.default.homeDirectoryForCurrentUser
If you need it to work with earlier OS versions than 10.12 you can use
let homeDirURL = URL(fileURLWithPath: NSHomeDirectory())
print(homeDirURL.path)
There should be an easier way but -- at worst -- this should work:
let filePath = NSString(string: "~").expandingTildeInPath
Swift 5 (and maybe lower)
let directoryString: String = NSHomeDirectory()
let directoryURL: URL = FileManager.default.homeDirectoryForCurrentUser
Maybe
FileManager.homeDirectoryForCurrentUser: URL
It's listed as "beta" for 10.12, though.