Swift 3: Reading content of folder? [duplicate] - swift

What is wrong with my code for getting the filenames in the document folder?
func listFilesFromDocumentsFolder() -> [NSString]?{
var theError = NSErrorPointer()
let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if dirs != nil {
let dir = dirs![0] as NSString
let fileList = NSFileManager.defaultManager().contentsOfDirectoryAtPath(dir, error: theError) as [NSString]
return fileList
}else{
return nil
}
}
I thought I read the documents correctly and I am very sure about what is in the documents folder, but "fileList" does not show anything? "dir" shows the path to the folder.

Swift 5
do {
// Get the document directory url
let documentDirectory = try FileManager.default.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true
)
print("documentDirectory", documentDirectory.path)
// Get the directory contents urls (including subfolders urls)
let directoryContents = try FileManager.default.contentsOfDirectory(
at: documentDirectory,
includingPropertiesForKeys: nil
)
print("directoryContents:", directoryContents.map { $0.localizedName ?? $0.lastPathComponent })
for url in directoryContents {
print(url.localizedName ?? url.lastPathComponent)
}
// if you would like to hide the file extension
for var url in directoryContents {
url.hasHiddenExtension = true
}
for url in directoryContents {
print(url.localizedName ?? url.lastPathComponent)
}
// if you want to get all mp3 files located at the documents directory:
let mp3s = directoryContents.filter(\.isMP3).map { $0.localizedName ?? $0.lastPathComponent }
print("mp3s:", mp3s)
} catch {
print(error)
}
You would need to add those extensions to your project
extension URL {
var typeIdentifier: String? { (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier }
var isMP3: Bool { typeIdentifier == "public.mp3" }
var localizedName: String? { (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName }
var hasHiddenExtension: Bool {
get { (try? resourceValues(forKeys: [.hasHiddenExtensionKey]))?.hasHiddenExtension == true }
set {
var resourceValues = URLResourceValues()
resourceValues.hasHiddenExtension = newValue
try? setResourceValues(resourceValues)
}
}
}

This solution works with Swift 4 (Xcode 9.2) and also with Swift 5 (Xcode 10.2.1+):
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
do {
let fileURLs = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil)
// process files
} catch {
print("Error while enumerating files \(documentsURL.path): \(error.localizedDescription)")
}
Here's a reusable FileManager extension that also lets you skip or include hidden files in the results:
import Foundation
extension FileManager {
func urls(for directory: FileManager.SearchPathDirectory, skipsHiddenFiles: Bool = true ) -> [URL]? {
let documentsURL = urls(for: directory, in: .userDomainMask)[0]
let fileURLs = try? contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil, options: skipsHiddenFiles ? .skipsHiddenFiles : [] )
return fileURLs
}
}
// Usage
print(FileManager.default.urls(for: .documentDirectory) ?? "none")

A shorter syntax for SWIFT 3
func listFilesFromDocumentsFolder() -> [String]?
{
let fileMngr = FileManager.default;
// Full path to documents directory
let docs = fileMngr.urls(for: .documentDirectory, in: .userDomainMask)[0].path
// List all contents of directory and return as [String] OR nil if failed
return try? fileMngr.contentsOfDirectory(atPath:docs)
}
Usage example:
override func viewDidLoad()
{
print(listFilesFromDocumentsFolder())
}
Tested on xCode 8.2.3 for iPhone 7 with iOS 10.2 & iPad with iOS 9.3

Apple states about NSSearchPathForDirectoriesInDomains(_:_:_:):
You should consider using the FileManager methods urls(for:in:) and url(for:in:appropriateFor:create:) which return URLs, which are the preferred format.
With Swift 5, FileManager has a method called contentsOfDirectory(at:includingPropertiesForKeys:options:). contentsOfDirectory(at:includingPropertiesForKeys:options:) has the following declaration:
Performs a shallow search of the specified directory and returns URLs for the contained items.
func contentsOfDirectory(at url: URL, includingPropertiesForKeys keys: [URLResourceKey]?, options mask: FileManager.DirectoryEnumerationOptions = []) throws -> [URL]
Therefore, in order to retrieve the urls of the files contained in documents directory, you can use the following code snippet that uses FileManager's urls(for:in:) and contentsOfDirectory(at:includingPropertiesForKeys:options:) methods:
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
do {
let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: [])
// Print the urls of the files contained in the documents directory
print(directoryContents)
} catch {
print("Could not search for urls of files in documents directory: \(error)")
}
As an example, the UIViewController implementation below shows how to save a file from app bundle to documents directory and how to get the urls of the files saved in documents directory:
import UIKit
class ViewController: UIViewController {
#IBAction func copyFile(_ sender: UIButton) {
// Get file url
guard let fileUrl = Bundle.main.url(forResource: "Movie", withExtension: "mov") else { return }
// Create a destination url in document directory for file
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let documentDirectoryFileUrl = documentsDirectory.appendingPathComponent("Movie.mov")
// Copy file to document directory
if !FileManager.default.fileExists(atPath: documentDirectoryFileUrl.path) {
do {
try FileManager.default.copyItem(at: fileUrl, to: documentDirectoryFileUrl)
print("Copy item succeeded")
} catch {
print("Could not copy file: \(error)")
}
}
}
#IBAction func displayUrls(_ sender: UIButton) {
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
do {
let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil, options: [])
// Print the urls of the files contained in the documents directory
print(directoryContents) // may print [] or [file:///private/var/mobile/Containers/Data/Application/.../Documents/Movie.mov]
} catch {
print("Could not search for urls of files in documents directory: \(error)")
}
}
}

Simple and dynamic solution (Swift 5):
extension FileManager {
class func directoryUrl() -> URL? {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
return paths.first
}
class func allRecordedData() -> [URL]? {
if let documentsUrl = FileManager.directoryUrl() {
do {
let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil)
return directoryContents.filter{ $0.pathExtension == "m4a" }
} catch {
return nil
}
}
return nil
}}

This code prints out all the directories and files in my documents directory:
Some modification of your function:
func listFilesFromDocumentsFolder() -> [String]
{
let dirs = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true)
if dirs != [] {
let dir = dirs[0]
let fileList = try! FileManager.default.contentsOfDirectory(atPath: dir)
return fileList
}else{
let fileList = [""]
return fileList
}
}
Which gets called by:
let fileManager:FileManager = FileManager.default
let fileList = listFilesFromDocumentsFolder()
let count = fileList.count
for i in 0..<count
{
if fileManager.fileExists(atPath: fileList[i]) != true
{
print("File is \(fileList[i])")
}
}

Swift 2.0 Compability
func listWithFilter () {
let fileManager = NSFileManager.defaultManager()
// We need just to get the documents folder url
let documentsUrl = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0] as NSURL
do {
// if you want to filter the directory contents you can do like this:
if let directoryUrls = try? NSFileManager.defaultManager().contentsOfDirectoryAtURL(documentsUrl, includingPropertiesForKeys: nil, options: NSDirectoryEnumerationOptions.SkipsSubdirectoryDescendants) {
print(directoryUrls)
........
}
}
}
OR
func listFiles() -> [String] {
var theError = NSErrorPointer()
let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if dirs != nil {
let dir = dirs![0]
do {
let fileList = try NSFileManager.defaultManager().contentsOfDirectoryAtPath(dir)
return fileList as [String]
}catch {
}
}else{
let fileList = [""]
return fileList
}
let fileList = [""]
return fileList
}

Related

How to move a file in swift

I'm trying to move a file to documents directory after I choose the file by using UIDocumentPickerViewController.
I don't see any error, but the file doesn't move to the directory.
I'd like to know how can I move the file.
class MyClassController: UIViewController,UIDocumentPickerDelegate {
var thisURL:URL?
#IBAction func add(_ sender: Any) {
let add = UIAlertAction(title: "add", style: .default, handler: {(alert: UIAlertAction!) in
do {
let myURL = URL(string:"\(self.thisURL!)")!
let path = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let MyDesPath = path.appendingPathComponent(myURL.lastPathComponent)
print(path)
do {
if FileManager.default.fileExists(atPath: “\(MyDesPath)") == false {
try FileManager.default.moveItem(at: myURL, to: URL(string:”\(MyDesPath)")!)
}
else {
}
}
catch let error {
print(error)
}
}
catch let error{
print(error)
return
}
})
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
NSLog("documentPicker executed")
thisURL = urls[0]
self.fileName.text = "\(thisURL!.lastPathComponent)"
}
}
I have done the same thing earlier, Please refer below steps and code:
Create a file URL to the temporary folder
var tempURL = URL(fileURLWithPath: NSTemporaryDirectory())
Append filename and extension to URL
tempURL.appendPathComponent(url.lastPathComponent)
If the file with the same name exists remove it (replace a file with the new one)
Full Code:
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
let newUrls = urls.flatMap { (url: URL) -> URL? in
var tempURL = URL(fileURLWithPath: NSTemporaryDirectory())
tempURL.appendPathComponent(url.lastPathComponent)
do {
if FileManager.default.fileExists(atPath: tempURL.path) {
try FileManager.default.removeItem(atPath: tempURL.path)
}
try FileManager.default.moveItem(atPath: url.path, toPath: tempURL.path)
return tempURL
} catch {
print(error.localizedDescription)
return nil
}
}
}
Full credit to #COVID19 for the answer though in my case using UIDocumentPickerViewController put the file in the temp folder already and some may like to place it in the documents directory. This is a way of going about that with a single file being selected.
guard let url = urls.first else { return }
var newURL = FileManager.getDocumentsDirectory()
newURL.appendPathComponent(url.lastPathComponent)
do {
if FileManager.default.fileExists(atPath: newURL.path) {
try FileManager.default.removeItem(atPath: newURL.path)
}
try FileManager.default.moveItem(atPath: url.path, toPath: newURL.path)
print("The new URL: \(newURL)")
} catch {
print(error.localizedDescription)
}
and my handy helper method
extension FileManager {
static func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
}

Swift writing log file in yosemite

I have a program that writes string to a file. It works perfectly in macos mojave but not in yosemite.
Using Xcode 11 and Swift 5
The code is
(Log.swift)
import Foundation
open class Log {
open var maxFileSize: UInt64 = 102400
open var maxFileCount = 365
///The directory in which the log files will be written
open var directory = Log.defaultDirectory() {
didSet {
directory = NSString(string: directory).expandingTildeInPath
let fileManager = FileManager.default
if !fileManager.fileExists(atPath: directory) {
do {
try fileManager.createDirectory(atPath: directory, withIntermediateDirectories: true, attributes: nil)
} catch {
NSLog("Couldn't create directory at \(directory)")
}
}
}
}
open var currentPath: String {
return "\(directory)/\(logName(0))"
}
///The name of the log files
open var name = "logfile"
///Whether or not logging also prints to the console
open var printToConsole = true
///logging singleton
open class var logger: Log {
struct Static {
static let instance: Log = Log()
}
return Static.instance
}
//the date formatter
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.timeStyle = .medium
formatter.dateStyle = .medium
return formatter
}
///write content to the current log file.
open func write(_ text: String) {
let path = currentPath
let fileManager = FileManager.default
if !fileManager.fileExists(atPath: path) {
do {
try "".write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
} catch _ {
}
}
if let fileHandle = FileHandle(forWritingAtPath: path) {
let dateStr = dateFormatter.string(from: Date())
let writeText = "[\(dateStr)]: \(text)\n"
fileHandle.seekToEndOfFile()
fileHandle.write(writeText.data(using: String.Encoding.utf8)!)
fileHandle.closeFile()
}
}
///Recursive method call to rename log files
func rename(_ index: Int) {
let fileManager = FileManager.default
let path = "\(directory)/\(logName(index))"
let newPath = "\(directory)/\(logName(index+1))"
if fileManager.fileExists(atPath: newPath) {
rename(index+1)
}
do {
try fileManager.moveItem(atPath: path, toPath: newPath)
} catch _ {
}
}
///gets the log name
func logName(_ num :Int) -> String {
return "\(name)-\(num).log"
}
///get the default log directory
class func defaultDirectory() -> String {
var path = ""
let fileManager = FileManager.default
let urls = fileManager.urls(for: .libraryDirectory, in: .userDomainMask)
//let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let url = urls.last {
path = "\(url.path)/TestingLog/Logs"
}
if !fileManager.fileExists(atPath: path) && path != "" {
do {
try fileManager.createDirectory(atPath: path, withIntermediateDirectories: false, attributes: nil)
} catch _ {
}
}
return path
}
}
///Writes content to the current log file
public func logw(_ text: String) {
Log.logger.write(text)
}
In another swift file I use logw("test1") to print test1 in a file in applicationsupport directory.
Whats wrong that makes it not write in yosemite?
I need it to not delete the file or the text inside the file and make it keep appending it when writing the log.
i can see from the code above in your
open func write(_ text: String) {
let path = currentPath
let fileManager = FileManager.default
if !fileManager.fileExists(atPath: path) {
do {
try "".write(toFile: path, atomically: true, encoding: String.Encoding.utf8)
} catch _ {
}
}
}
method the string value passed to log is not used anywhere. . Can you please clarify this

Could not open obj file

so I'm working on a project that pulls zip files which include .obj files, unzips them and displays them using ARkit. At the moment I've been able to unzip and save the file in my documents directory as a .obj file and it says the file exists, but when I try to convert it into a scn it says "Could not open OBJ file". Here is my code and I'm trying to figure out where I went wrong. The file size is 314 KB so I know that's not the issue and the obj file isn't corrupted because I can download it to my computer and open it up.
class ViewController: UIViewController {
var testData: Store?
var logoImage: UIImage?
var urlForObject: String?
var tempDirectoryString: String?
var tempDirectoryURL: URL?
var testModelData: Data?
var testData2: Data?
var testData3: Models?
var tempDocumentsURL: URL?
#IBOutlet weak var logoImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.clearCowZipFolder()
self.clearCowFolder()
self.requestZipFile(){ response in
self.testData2 = response
do{
let json = try? JSONSerialization.jsonObject(with: response, options: [])
if let array = json as? [String] {
if let firstObject = array.first {
//print(firstObject)
}
for object in array {
// access all objects in array
}
for case let string as String in array {
// access only string values in array
}
}
}catch{
print("errorrrr")
}
}
self.tempDocumentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = self.tempDocumentsURL!.appendingPathComponent("Man.zip")
var destPath = self.tempDocumentsURL!.appendingPathComponent("Man")
//Create URL to the source file you want to download
let fileURL = URL(string: "http://markitapi.com/stores/TestStore/models/Man")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
let task = session.downloadTask(with: request) { (tempLocalUrl, response3, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response3 as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
do{
let unzipDirectory = try Zip.quickUnzipFile(destinationFileUrl) //Unzip
print("HHERHERHEHRE")
destPath = unzipDirectory
}catch{
print("error while unzipping")
}
print("UNZIPPED PATH")
//print(destPath)
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let url = NSURL(fileURLWithPath: path)
if let pathComponent = url.appendingPathComponent("Man/Man.obj") {
let filePath = pathComponent.path
//print(filePath)
let fileManager = FileManager.default
if fileManager.fileExists(atPath: filePath) {
print("FILE AVAILABLE")
} else {
print("FILE NOT AVAILABLE")
}
} else {
print("FILE PATH NOT AVAILABLE")
}
let url2 = (String(describing: destPath) + "Man.obj")
let url3 = URL(fileURLWithPath: url2)
print(url3.pathExtension)
let asset = MDLAsset(url: url3)
//print(asset)
let object = asset.object(at: 0)
let node = SCNNode(mdlObject: object)
//print(node)
}
} else {
//print("Error took place while downloading a file. Error description: %#", error?.localizedDescription);
}
}
task.resume()
}
func clearCowZipFolder() {
let fileNameToDelete = "Man.zip"
var filePath = ""
// Fine documents directory on device
let dirs : [String] = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true)
if dirs.count > 0 {
let dir = dirs[0] //documents directory
filePath = dir.appendingFormat("/" + fileNameToDelete)
//print("Local path = \(filePath)")
} else {
print("Could not find local directory to store file")
return
}
do {
let fileManager = FileManager.default
// Check if file exists
if fileManager.fileExists(atPath: filePath) {
// Delete file
try fileManager.removeItem(atPath: filePath)
} else {
print("File does not exist")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
}
func clearCowFolder() {
let fileNameToDelete = "Man"
var filePath = ""
// Fine documents directory on device
let dirs : [String] = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true)
if dirs.count > 0 {
let dir = dirs[0] //documents directory
filePath = dir.appendingFormat("/" + fileNameToDelete)
//print("Local path = \(filePath)")
} else {
print("Could not find local directory to store file")
return
}
do {
let fileManager = FileManager.default
// Check if file exists
if fileManager.fileExists(atPath: filePath) {
// Delete file
try fileManager.removeItem(atPath: filePath)
} else {
print("File does not exist")
}
}
catch let error as NSError {
print("An error took place: \(error)")
}
}
func requestZipFile(success successBlock: #escaping (Data) -> Void){
Alamofire.request("http://markitapi.com/stores/TestStore/models").responseJSON { (response) in
do{
if(response.result.isSuccess){
successBlock(response.data!)
}
}catch{
print("error")
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The first part of the code checks to see if the file is available and it does print that statement, so I know the file is there.

Trying to clear document folder Swift

I use following method to add file (download) to document directory:
static func downloadFileWithLink(linkString : String){
// Create destination URL
let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent("downloadedFile")
//Create URL to the source file you want to download
let fileURL = URL(string: linkString)
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
} catch (let writeError) {
print("Error creating a file \(destinationFileUrl) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription);
}
}
task.resume()
}
It simply download file to document folder in sandbox. I looked for method that delete files in documents folder, and tried following:
static func deleteFiledInDocDirectory(){
let fileManager = FileManager.default
let tempFolderPath = NSTemporaryDirectory()
do {
let filePaths = try fileManager.contentsOfDirectory(atPath: tempFolderPath)
for filePath in filePaths {
try fileManager.removeItem(atPath: tempFolderPath + filePath)
}
} catch {
print("Could not clear temp folder: \(error)")
}
}
However, when i inspect sandbox, downloaded file is still here. How to delete it?
In deleteFiledInDocDirectory() you're using NSTemporaryDirectory instead of the documents directory that you originally saved the file to.
Change tempFolderPath to be set using following:
guard let tempFolderPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
return // documents directory not found for some reason
}
The full method:
static func deleteFiledInDocDirectory(){
guard let tempFolderPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first?.absoluteString else {
return // documents directory not found for some reason
}
let fileManager = FileManager.default
do {
let filePaths = try fileManager.contentsOfDirectory(atPath: tempFolderPath)
for filePath in filePaths {
try fileManager.removeItem(atPath: tempFolderPath + filePath)
}
} catch {
print("Could not clear temp folder: \(error)")
}
}

Documents folder working in Simulator but not iPad - Swift 2.1

The below code unzips a folder of images into a folder I create. and then loops through it and adds the names to an array, then loops through this array and retrieves those file names into an array of images.
It works perfectly on the simulator, but the data is empty when I do it on the iPad, it prints out nothing. I can only assume the folder isn't accessible or is being searched before the unzip has completed, but It shouldnt as I am using NSOperationQueue with a completion block.
func unzipData(objectData: NSManagedObject) {
var paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentsDir = paths[0]
let zipPath = documentsDir.stringByAppendingString("MyZipFiles")
let folderPath = documentsDir.stringByAppendingString("/docLibFiles") // My folder name in document directory
var optData = NSData(data: objectData.valueForKey("image") as! NSData)
print(objectData.valueForKey("imageUrl") as! String)
optData.writeToFile(zipPath, atomically: true)
let success = fileManager.fileExistsAtPath(zipPath) as Bool
if success == false {
do {
try! fileManager.createDirectoryAtPath(folderPath, withIntermediateDirectories: true, attributes: nil)
}
}
queue.addOperationWithBlock { () -> Void in
let operation1 = NSBlockOperation(block: {
let unZipped = SSZipArchive.unzipFileAtPath(zipPath, toDestination: folderPath)
})
operation1.completionBlock = {
dispatch_async(dispatch_get_main_queue(), {
if queue.operationCount == 0 {
self.retrieveFiles()
}
})
}
queue.addOperation(operation1)
}
}
func getDocumentsURL() -> NSURL {
let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
return documentsURL
}
func fileInDocumentsDirectory(filename: String) -> String {
let fileURL = getDocumentsURL().URLByAppendingPathComponent(filename)
return fileURL.path!
}
func retrieveFiles() {
var paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentsDir = paths[0]
let zipPath = documentsDir.stringByAppendingString("MyZipFiles")
let folderPath = documentsDir.stringByAppendingString("/docLibFiles") // My folder name in document directory
do {
let filelist = try fileManager.contentsOfDirectoryAtPath(folderPath)
print(filelist)
print("filename")
for filename in filelist {
fileNameArray.append(filename)
}
} catch let error as NSError {
print("Could not save \(error)")
}
do {
for item in fileNameArray {
print("item \(item)")
let imagePath = fileInDocumentsDirectory("docLibFiles/\(item)")
imageArray.append(UIImage(contentsOfFile: imagePath)!)
}
print("filename array \(fileNameArray)")
print("image array \(imageArray)")
unzipDelegate!.unzipSet(imageArray)
}
}
In case of avoiding an error is generated by some trivial typos. Probably process paths in NSURL form
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentsDir = paths[0]
let url = NSURL(fileURLWithPath: documentsDir)
url.URLByAppendingPathComponent("MyZipFiles")
url.URLByAppendingPathComponent("docLibFiles")
Im not exactly sure why the initial problem was there, but my code was definitely overcomplicated. Ive sorted it now, hopefully it will help someone else in swift 2.1
class UnzipDocument {
let queue = NSOperationQueue() // BACKGROUND THREAD
var imageArray = [UIImage]()
var fileNameArray = [String]()
var fileManager = NSFileManager.defaultManager()
let compressedFile = NSTemporaryDirectory().stringByAppendingString("MyZipFiles")
let uncompressedFolder = NSTemporaryDirectory().stringByAppendingString("MyUnzippedFiles")
func unzipData(objectData: NSManagedObject){ // THIS IS BASICALLY NSDATA FROM CORE DATA FOR ME
let optData = NSData(data: objectData.valueForKey("image") as! NSData)
let success = fileManager.fileExistsAtPath(uncompressedFolder) as Bool // CREATES THE FOLDER IF IT DOESNT EXIST
if success == false {
do {
try! fileManager.createDirectoryAtPath(uncompressedFolder, withIntermediateDirectories: true, attributes: nil)
}
}
optData.writeToFile(compressedFile, atomically: true)
queue.addOperationWithBlock { () -> Void in
let operation1 = NSBlockOperation(block: {
SSZipArchive.unzipFileAtPath(self.compressedFile, toDestination: self.uncompressedFolder)
})
operation1.completionBlock = {
if queue.operationCount == 0 {
dispatch_async(dispatch_get_main_queue(), {
if queue.operationCount == 0 {
self.retrieveFiles()
}
})
}
}
queue.addOperation(operation1)
}
}
func retrieveFiles() {
do {
let filelist = try fileManager.contentsOfDirectoryAtPath(uncompressedFolder)
print(filelist)
print("filename")
for filename in filelist {
self.fileNameArray.append(filename)
}
} catch let error as NSError {
print("Could not save \(error)")
}
do {
for item in fileNameArray {
print("item \(item)")
let imagePath = uncompressedFolder.stringByAppendingString("/\(item)")
imageArray.append(UIImage(contentsOfFile: imagePath)!)
}
print("filename array \(fileNameArray)")
print("image array \(imageArray)")
unzipDelegate!.unzipSet(imageArray)
} catch {
}
}
}
and to delete the temp file/folder after use, so that it can be reused without any old documents remaining
var fileManager = NSFileManager.defaultManager()
let compressedFile = NSTemporaryDirectory().stringByAppendingString("MyZipFiles")
let uncompressedFolder = NSTemporaryDirectory().stringByAppendingString("MyUnzippedFiles")
do {
try fileManager.removeItemAtPath(compressedFile)
try fileManager.removeItemAtPath(uncompressedFolder)
} catch let error as NSError {
print("Could not save \(error)")
}