How to Get the File Creation Date Using Url Resourcevalues Method in Swift 3

How can I get the file creation date using URL resourceValues method in Swift 3?

You can extend URL as follow:

extension URL {
/// The time at which the resource was created.
/// This key corresponds to an Date value, or nil if the volume doesn't support creation dates.
/// A resource’s creationDateKey value should be less than or equal to the resource’s contentModificationDateKey and contentAccessDateKey values. Otherwise, the file system may change the creationDateKey to the lesser of those values.
var creation: Date? {
get {
return (try? resourceValues(forKeys: [.creationDateKey]))?.creationDate
}
set {
var resourceValues = URLResourceValues()
resourceValues.creationDate = newValue
try? setResourceValues(resourceValues)
}
}
/// The time at which the resource was most recently modified.
/// This key corresponds to an Date value, or nil if the volume doesn't support modification dates.
var contentModification: Date? {
get {
return (try? resourceValues(forKeys: [.contentModificationDateKey]))?.contentModificationDate
}
set {
var resourceValues = URLResourceValues()
resourceValues.contentModificationDate = newValue
try? setResourceValues(resourceValues)
}
}
/// The time at which the resource was most recently accessed.
/// This key corresponds to an Date value, or nil if the volume doesn't support access dates.
/// When you set the contentAccessDateKey for a resource, also set contentModificationDateKey in the same call to the setResourceValues(_:) method. Otherwise, the file system may set the contentAccessDateKey value to the current contentModificationDateKey value.
var contentAccess: Date? {
get {
return (try? resourceValues(forKeys: [.contentAccessDateKey]))?.contentAccessDate
}
// Beginning in macOS 10.13, iOS 11, watchOS 4, tvOS 11, and later, contentAccessDateKey is read-write. Attempts to set a value for this file resource property on earlier systems are ignored.
set {
var resourceValues = URLResourceValues()
resourceValues.contentAccessDate = newValue
try? setResourceValues(resourceValues)
}
}
}

usage:

print(yourURL.creationDate)

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.

How to get iOS APP archive date using Swift

You can get the url of your app using Bundle property executableURL and use url method resourceValues to get the bundle creation date:

if let executableURL = Bundle.main.executableURL,
let creation = (try? executableURL.resourceValues(forKeys: [.creationDateKey]))?.creationDate {
print(creation)
}

Swift 2 iOS - get file list sorted by creation date - more concise solution?

A possible solution:

if let urlArray = try? NSFileManager.defaultManager().contentsOfDirectoryAtURL(directory,
includingPropertiesForKeys: properties, options:.SkipsHiddenFiles) {

return urlArray.map { url -> (String, NSTimeInterval) in
var lastModified : AnyObject?
_ = try? url.getResourceValue(&lastModified, forKey: NSURLContentModificationDateKey)
return (url.lastPathComponent!, lastModified?.timeIntervalSinceReferenceDate ?? 0)
}
.sort({ $0.1 > $1.1 }) // sort descending modification dates
.map { $0.0 } // extract file names

} else {
return nil
}

The array of URLs is mapped to an array of (lastPathComponent, lastModificationDate) tuples first, then sorted according to the
last modification date, and finally the path name extracted.

The attributesDictionary can be avoided by using
getResourceValue(_ : forKey) to retrieve only the last modification date.

Update for Swift 3:

let directory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
if let urlArray = try? FileManager.default.contentsOfDirectory(at: directory,
includingPropertiesForKeys: [.contentModificationDateKey],
options:.skipsHiddenFiles) {

return urlArray.map { url in
(url.lastPathComponent, (try? url.resourceValues(forKeys: [.contentModificationDateKey]))?.contentModificationDate ?? Date.distantPast)
}
.sorted(by: { $0.1 > $1.1 }) // sort descending modification dates
.map { $0.0 } // extract file names

} else {
return nil
}

How to sort the filemanager array by creation date

You need to declare a struct that has a URL (or filename String) and a Date. Populate an array of this struct from the files (and their creation dates) you query from FileManager.

Use that array of struct as your data model for the table view. You can sort the array on filename or date (or any other attributes you might add in the future).

You can get the creation date of each file by first adding [.creationDateKey] to the includingPropertiesForKeys parameter of contentsOfDirectory. Then access the creation date using resourceValues on each URL. See How can I get the file creation date using URL resourceValues method in Swift 3? for more details on getting the creation date.

It may help to use the enumerator method of FileManager instead of contentsOfDirectory. This will make it easier to get the needs URL attributes and populate the array of struct.

Files date from directory folder

It's highly recommended to use the URL related API of FileManager to get the file attributes in a very efficient way.

This code prints all URLs of the specified directory with a creation date older than a week ago.

let calendar = Calendar.current
let aWeekAgo = calendar.date(byAdding: .day, value: -7, to: Date())!

do {
let directoryContent = try fileManager.contentsOfDirectory(at: directoryURL, includingPropertiesForKeys: [.creationDateKey], options: .skipsHiddenFiles)
for url in directoryContent {
let resources = try url.resourceValues(forKeys: [.creationDateKey])
let creationDate = resources.creationDate!
if creationDate < aWeekAgo {
print(url)
// do somthing with the found files
}
}
}
catch {
print(error)
}

If you want finer control of the workflow for example an URL is invalid and you want to print the bad URL and the associated error but continue precessing the other URLs use an enumerator, the syntax is quite similar:

do {
let enumerator = fileManager.enumerator(at: directoryURL, includingPropertiesForKeys: [.creationDateKey], options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles], errorHandler: { (url, error) -> Bool in
print("An error \(error) occurred at \(url)")
return true
})
while let url = enumerator?.nextObject() as? URL {
let resources = try url.resourceValues(forKeys: [.creationDateKey])
let creationDate = resources.creationDate!
if creationDate < last7Days {
print(url)
// do somthing with the found files
}
}

}
catch {
print(error)
}

Get file size in Swift

Use attributesOfItemAtPath instead of attributesOfFileSystemForPath
+ call .fileSize() on your attr.

var filePath: NSString = "your path here"
var fileSize : UInt64
var attr:NSDictionary? = NSFileManager.defaultManager().attributesOfItemAtPath(filePath, error: nil)
if let _attr = attr {
fileSize = _attr.fileSize();
}

In Swift 2.0, we use do try catch pattern, like this:

let filePath = "your path here"
var fileSize : UInt64 = 0

do {
let attr : NSDictionary? = try NSFileManager.defaultManager().attributesOfItemAtPath(filePath)

if let _attr = attr {
fileSize = _attr.fileSize();
}
} catch {
print("Error: \(error)")
}

In Swift 3.x/4.0:

let filePath = "your path here"
var fileSize : UInt64

do {
//return [FileAttributeKey : Any]
let attr = try FileManager.default.attributesOfItem(atPath: filePath)
fileSize = attr[FileAttributeKey.size] as! UInt64

//if you convert to NSDictionary, you can get file size old way as well.
let dict = attr as NSDictionary
fileSize = dict.fileSize()
} catch {
print("Error: \(error)")
}

Check if NSURL is a directory

that is working quote well on my side:

var error: NSError?
let documentURL : NSURL = NSFileManager.defaultManager().URLForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomain: NSSearchPathDomainMask.UserDomainMask, appropriateForURL: nil, create: true, error: &error)
var isDirectory: ObjCBool = ObjCBool(0)
if NSFileManager.defaultManager().fileExistsAtPath(documentURL.path, isDirectory: &isDirectory) {
println(isDirectory)
}

NOTE: it checks whether the Documents folder is a folder. you can replace the URL with anything, of course.



Related Topics



Leave a reply



Submit