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.
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.
How to get only the filename of a NSUrl array
First of all I have a déjà vu
Second of all do not get only the filename of a NSUrl array. You will lose the ability to sort the files by creation date.
You cannot filter an array of NSURL
with a predicate, you must filter the files in a loop.
To use the filtered array as a data source first create a property in the .h file
@property NSMutableArray<NSURL *> *files;
In the .m file create a separate method to sort the files
- (void)sortFilesByCreationDateAscending:(BOOL)ascending
{
[self.files sortUsingComparator:^(NSURL *lURL, NSURL *rURL) {
NSDate *lDate, *rDate;
[lURL getResourceValue:&lDate forKey:NSURLCreationDateKey error:nil];
[rURL getResourceValue:&rDate forKey:NSURLCreationDateKey error:nil];
return ascending ? [lDate compare:rDate] : [rDate compare:lDate];
}];
}
Get the files, filter them and sort them in viewDidLoad
. Then reload the table view
- (void)viewDidLoad {
[super viewDidLoad]:
self.files = [[NSMutableArray alloc] init];
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectoryURL = [fileManager URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:false
error:nil];
NSArray<NSURL *> *fileURLs = [fileManager contentsOfDirectoryAtURL:documentDirectoryURL
includingPropertiesForKeys:@[NSURLCreationDateKey]
options:0
error:&error];
if (error) {
NSLog(@"%@", error);
return;
}
for (NSURL *anURL in fileURLs) {
if ([anURL.pathExtension isEqualToString:@"csv"]) {
[self.files addObject: anURL];
}
}
[self sortFilesByCreationDateAscending:YES];
[self.tableView reloadData];
}
In numberOfRowsInSection
return self.files.count
In cellForRowAtIndexPath
get the URL for the index path and display the file name
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier forIndexPath: indexPath];
NSURL *url = self.files[indexPath.row];
cell.textLabel.text = url.lastPathComponent;
return cell;
}
To sort the files in the other direction call sortFilesByCreationDateAscending
with appropriate BOOL value and reload the table view.
Sorting arrays of file attributes by their creation date in Swift
You should not use multiple arrays for this but instead wrap your values in a custom struct
struct FileInfo {
let url: URL
let name: String
let path: String //this is not really needed, you can get it from the url
let date: Date
}
and have one array for this
var files: [FileInfo]()
and create your struct instance and append it
files.append(FileInfo(url: fileURL, name: name, path: path, date: date)
Sorting will now be trivial so after the for loop you do
files.sort(by: { $0.date < $1.date })
This sorts in ascending order, not sure which one you want.
Finding the index of 'NSURL item' in 'NSURL array'
let index = array2.indexOf { $0.absoluteString == array1[2].absoluteString }
Swift - Sorting url content into an array
The preferred way is enumerateLinesUsingBlock
with NSString
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding)!
var lines:[String] = []
urlContent.enumerateLinesUsingBlock { line, _ in
lines.append(line)
}
println(lines)
In this specific case, you can simply split by "\n"
:
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as String
var lines = urlContent.componentsSeparatedByString("\n")
if lines.last == "" {
// The last one is empty string
lines.removeLast()
}
But in general, the line separator may not be "\n"
. see this document:
A line is delimited by any of these characters, the longest possible
sequence being preferred to any shorter:
U+000D
(\r
orCR
)U+2028
(Unicode line separator)U+000A
(\n
orLF
)U+2029
(Unicode paragraph separator)\r\n
, in that order (also known asCRLF
)
enumerateLinesUsingBlock
can handle all of them.
How get Single Url From an Array of urls?
As Julian Kniephoff rightly mentioned, you are printing each URL in the for loop, thus you cannot access one particular one. However, there is also another issue, in that you are replacing the urls
array with the latest url each time.
To solve this, simply replace the line self.urls = [urimage]
with self.urls.append(urimage)
.
You can then access a particular image outside the for
loop by doing something like self.urls[1]
.
This is also why print
ing the count of the array returns 1, since each time around you are setting the array to just the one latest element in the loop.
In the end, your code may look something like this
url = NSURL(string: "http://xxxxxxxxxxx.com/api/?slider=uij6sdnb")
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url) {(data, response, error) -> Void in
do {
let records = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
for record in records {
//let urlid = Int(record["slide_id"] as! String)
let urimage = record["slide_url"] as! String
self.urls.append(urimage)
}
print(self.urls[1]) //Prints http://sdkladlkasjd2.jpg
}
catch {
print("Json Error")
}
//print(self.urls[1])
}
task.resume()
Related Topics
Swift Ensembles Set Up & Ubiquitycontaineridentifier
Scanning Ble Peripheral and Connecting to It
Swiching Between 2 Diferent Nsviewcontrollers with Data
How to Observe Torchlevel in Swift
Programmatically Setting Texture in Scene Generated by Reality Composer
Xcode Swift: Could Not Insert New Outlet Connection
How to Update User Interface on Core Data
Post Urlrequest Doesn't Work in Swift 4
Swift Spritekit Get Visible Frame Size
Tab Bar Item Icons Appear Darker
Call Function on App Termination in Swift
Skphysicscontact Not Detecting Categorybitmask Collision
Calling Asynchronous Method Inside For-Loop
Having Trouble with Musickit Sample App Provided by Apple
Get Out of Navigation Controller and Go Back to Tab Bar View