Array of Multiple Url's Nsfilemanager Swift

Array of multiple URL's NSFileManager Swift

In this case I think you should use NSURLSession.sharedSession().dataTaskWithURL to do multiple downloads from your links but keeping the download operation asynchronous. You need to add a callback block to it. You should do as follow:

let documentsUrl =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL
let musicArray:[String] = ["http://freetone.org/ring/stan/iPhone_5-Alarm.mp3","http://freetone.org/ring/stan2/Samsung_Galaxy_S4-SMS.mp3","https://www.sounddogs.com/sound-effects/25/mp3/235178_SOUNDDOGS__al.mp3"]
var musicUrls:[NSURL!]!

// create a function to start the audio data download
func getAudioDataFromUrl(audioUrl:NSURL, completion: ((data: NSData?) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(audioUrl) { (data, response, error) in
completion(data: data)
}.resume()
}

// create another function to save the audio data
func saveAudioData(audio:NSData, destination:NSURL) -> Bool {
if audio.writeToURL(destination, atomically: true) {
println("The file \"\(destination.lastPathComponent!.stringByDeletingPathExtension)\" was successfully saved.")
return true
}
return false
}

// just convert your links to Urls
func linksToUrls(){
musicUrls = musicArray
.map() { NSURL(string: $0) }
.filter() { $0 != nil }
}

// create a loop to start downloading your urls
func startDownloadingUrls(){
for url in musicUrls {
let destinationUrl = documentsUrl.URLByAppendingPathComponent(url.lastPathComponent!)
if NSFileManager().fileExistsAtPath(destinationUrl.path!) {
println("The file \"\(destinationUrl.lastPathComponent!.stringByDeletingPathExtension)\" already exists at path.")
} else {
println("Started downloading \"\(url.lastPathComponent!.stringByDeletingPathExtension)\".")
getAudioDataFromUrl(url) { data in
dispatch_async(dispatch_get_main_queue()) {
println("Finished downloading \"\(url.lastPathComponent!.stringByDeletingPathExtension)\".")
println("Started saving \"\(url.lastPathComponent!.stringByDeletingPathExtension)\".")

if self.saveAudioData(data!, destination: self.documentsUrl.URLByAppendingPathComponent(url.lastPathComponent!) ) {
// do what ever if writeToURL was successful
} else {
println("The File \"\(url.lastPathComponent!.stringByDeletingPathExtension)\" was not saved.")
}
}
}
}
}
}

override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println("Begin of code")
linksToUrls()
startDownloadingUrls()
println("End of code")
}

Order a NSURL array

As you want to sort the files by the number you have to parse first the path to achieve it, so let's suppose we have the following array of NSURL objects:

var urls = [NSURL(string: "file:///path/to/user/folder/2.PNG")!, NSURL(string: "file:///path/to/user/folder/100.PNG")!, NSURL(string: "file:///path/to/user/folder/101.PNG")!, NSURL(string: "file:///path/to/user/folder/1.PNG")! ]

We can use the pathComponents property to extract an array with all the components in the path for a NSURL (e.g ["/", "path", "to", "user", "folder", "2.PNG"]).

If we see we can order the files by the last element in the array that is the filename removing the extension and the dot("."), in this case the number. Let's see how to do it in the following code:

urls.sortInPlace {

// number of elements in each array
let c1 = $0.pathComponents!.count - 1
let c2 = $1.pathComponents!.count - 1

// the filename of each file
var v1 = $0.pathComponents![c1].componentsSeparatedByString(".")
var v2 = $1.pathComponents![c2].componentsSeparatedByString(".")

return Int(v1[0]) < Int(v2[0])
}

In the above code we use the function sortInPlace to avoid create another array with the elements sorted, but can you use sort instead if you want. The another important point in the code is the line return Int(v1[0]) < Int(v2[0]), in this line we have to convert the number in the string to a real number, because if we compare the two strings "2" and "100" the second one is less than greater than because the string are compared lexicographically.

So the the array urls should be like the following one:

[file:///path/to/user/folder/1.PNG, file:///path/to/user/folder/2.PNG, file:///path/to/user/folder/100.PNG, file:///path/to/user/folder/101.PNG]

EDIT:

The two functions pathComponents and componentsSeparatedByString increase the space complexity of the sortInPlace algorithm, if you can asure that the path for the files always will be the same except it's filename that should be a number you can use instead this code:

urls.sortInPlace { $0.absoluteString.compare(
$1.absoluteString, options: .NumericSearch) == .OrderedAscending
}

I hope this help you.

Storing file names in an array Swift

Here's an example of how it works. This function returns an array of all the files URLs in a directory and all its subdirectories from a given path.

func files(atPath: String) -> [NSURL] {
var urls : [NSURL] = []
let dirUrl = NSURL(fileURLWithPath: atPath)
if dirUrl != nil {
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator? = fileManager.enumeratorAtURL(dirUrl!, includingPropertiesForKeys: nil, options: nil, errorHandler: nil)
while let url = enumerator?.nextObject() as! NSURL? {
if url.lastPathComponent == ".DS_Store" {
continue
}
urls.append(url)
}
}
return urls
}

let allFiles = files("/a/directory/somewhere")

How do I get an array of file names from the iOS File Manager

So, contentsOfFileManager is going to consist of NSURL objects. These objects have different fields you can pluck out and use. It looks like you're interested in just the filename so I'd like to draw your attention to the lastPathComponent field of NSURL. From the docs:

This property contains the last path component, unescaped using the replacingPercentEscapes(using:) method. For example, in the URL file:///path/to/file, the last path component is file.

In other words, calling myNsurl.lastPathComponent should yield you the filename. So you can loop through the array that's returned by myFileManager.contentsOfDirectory and get the lastPathComponent of each one and add them to another array which will contain just the filenames.

FileManager.default.contentsOfDirectory return array with different sorting in iphone 8

NSFileManager doesn't sort the list of files. But you can do it yourself using sorted method of array. The code will look like this:

let files: [String]? = try? FileManager.default.contentsOfDirectory(atPath: self.targetDirectory)
let sortedFiles = files?.sorted()

Sorting an array of NSURL objects by creation date

EDIT : Better answer

If that doesn't work, you will have to write your own comparator block and get the dates to compare manually :(

[cacheContents sortUsingComparator:^ (NSURL *a, NSURL *b) {
// get the two dates
id da = [[a resourceValuesForKeys:[NSArray arrayWithObject:NSURLCreationDateKey] error:nil] objectForKey:NSURLCreationDateKey];
id db = [[b resourceValuesForKeys:[NSArray arrayWithObject:NSURLCreationDateKey] error:nil] objectForKey:NSURLCreationDateKey];

// compare them
return [da compare:db];
}];

(Same disclaimer still applies but I'm not even sure that will compile ;) - you get the idea though!)


Here is my first answer (included here for posterity but mostly it just shows how important it is to read the question properly :)

It's because you're getting an array of NSURL objects; these don't have a NSURLCreationDateKey property.

Try this (disclaimer - not 100% it will work)

NSString *key = [NSString stringWithFormat:@"fileAttributes.%@", NSURLCreationDateKey];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:key ascending:YES];

Your key to sort by is a property of the fileAttributes dictionary which is, in turn, a property of your enumerator.

Finder algorithm for sort by name options

The Finder-like sort order can be realized with localizedStandardCompare

The documentation says:

This method should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate.

let sortedFileURLs = fileURLs.sorted{ $0.lastPathComponent.localizedStandardCompare($1.lastPathComponent) == .orderedAscending }

Note: lastPathComponent is preferable over pathComponents.last!



Related Topics



Leave a reply



Submit