在我的代码中,我正在返回一个[String]?
,其中包含lastPathComponent
中存储的文件名/Documents/
- 按上次修改日期排序。
我相信我可能正在使用太多步骤,我在这里寻求建议如何减少代码。
为了达到目前所需的结果 - 我创建了两个中间词典:var attributesDictionary: [String : AnyObject]?
和var urlDictionary = [NSURL:NSDate]()
。循环使用最初的[NSURL]
我正在使用两个步骤 - .resourceValuesForKeys
初始化attributesDictionary
。然后我填充urlDictionary
,使其包含网址和密钥NSURLContentModificationDateKey
的值。
我确信应该有一种方法可以在不创建urlDictionary
和attributesDictionary
且无需循环的情况下实现此结果。也许直接来自urlArray
。这是我目前的代码:
编辑:do{}
不需要Arthur Gevorkyan在第一条评论中指出。
func getFileList() -> [String]? {
let directory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let properties = [NSURLLocalizedNameKey, NSURLCreationDateKey, NSURLContentModificationDateKey, NSURLLocalizedTypeDescriptionKey]
// no catch required - contentsOfDirectoryAtURL returns nil if there is an error
if let urlArray = try? NSFileManager.defaultManager().contentsOfDirectoryAtURL(directory, includingPropertiesForKeys: properties, options:NSDirectoryEnumerationOptions.SkipsHiddenFiles) {
var attributesDictionary: [String:AnyObject]?
var dateLastModified: NSDate
var urlDictionary = [NSURL:NSDate]()
for URLs in urlArray {
// no catch required - resourceValuesForKeys returns nil if there is an error
attributesDictionary = try? URLs.resourceValuesForKeys(properties)
dateLastModified = attributesDictionary?[NSURLContentModificationDateKey] as! NSDate
urlDictionary[URLs] = dateLastModified
}
// this approach to sort is used because NSDate cannot be directly compared with </>
return urlDictionary.filter{$0 != nil}.sort{$0.1.compare($1.1) == NSComparisonResult.OrderedDescending }.map{$0.0}.map{$0.lastPathComponent!}
} else {
return nil
}
}
答案 0 :(得分:20)
可能的解决方案:
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
}
首先将URL数组映射到(lastPathComponent, lastModificationDate)
元组的数组,然后根据
最后修改日期,最后提取路径名。
使用可以避免attributesDictionary
getResourceValue(_ : forKey)
仅检索上次修改日期。
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
}
答案 1 :(得分:5)
完整解决方案的Swift 3代码: 根据@ ingconti的回答。此方法返回提供的URL路径中的项目名称列表。
func filesSortedList(atPath: URL) -> [String]? {
var fileNames = [String]()
let keys = [URLResourceKey.contentModificationDateKey]
guard let fullPaths = try? FileManager.default.contentsOfDirectory(at: atPath, includingPropertiesForKeys:keys, options: FileManager.DirectoryEnumerationOptions.skipsHiddenFiles) else {
return [""]
}
let orderedFullPaths = fullPaths.sorted(by: { (url1: URL, url2: URL) -> Bool in
do {
let values1 = try url1.resourceValues(forKeys: [.creationDateKey, .contentModificationDateKey])
let values2 = try url2.resourceValues(forKeys: [.creationDateKey, .contentModificationDateKey])
if let date1 = values1.creationDate, let date2 = values2.creationDate {
//if let date1 = values1.contentModificationDate, let date2 = values2.contentModificationDate {
return date1.compare(date2) == ComparisonResult.orderedDescending
}
} catch _{
}
return true
})
for fileName in orderedFullPaths {
do {
let values = try fileName.resourceValues(forKeys: [.creationDateKey, .contentModificationDateKey])
if let date = values.creationDate{
//let date : Date? = values.contentModificationDate
print(fileName.lastPathComponent, " ", date)
let theFileName = fileName.lastPathComponent
fileNames.append(theFileName)
}
}
catch _{
}
}
return fileNames
}
答案 2 :(得分:3)
return urlDictionary.filter{$0 != nil}.sort{$0.1.compare($1.1) == NSComparisonResult.OrderedDescending }.map{$0.0}.map{$0.lastPathComponent!}
绝对是一个过度的代码行:) 您可以使用另一种NSFileManager方法跳过几个过滤器/映射步骤:
func contentsOfDirectoryAtPath(_ path: String) throws -> [String]
和
func attributesOfItemAtPath(_ path: String) throws -> [String : AnyObject].
最后,你最终得到的东西与你已经完成的东西相当。我认为你的代码有点复杂,但方法非常好。
答案 3 :(得分:1)
Swift 5.0使用ModificationDate进行过滤和排序
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
guard let directoryURL = URL(string: paths.path) else {return}
do {
let contents = try
FileManager.default.contentsOfDirectory(at: directoryURL,
includingPropertiesForKeys:[.contentModificationDateKey],
options: [.skipsHiddenFiles, .skipsSubdirectoryDescendants])
.filter { $0.lastPathComponent.hasSuffix(".swift") }
.sorted(by: {
let date0 = try $0.promisedItemResourceValues(forKeys:[.contentModificationDateKey]).contentModificationDate!
let date1 = try $1.promisedItemResourceValues(forKeys:[.contentModificationDateKey]).contentModificationDate!
return date0.compare(date1) == .orderedDescending
})
// Print results
for item in contents {
guard let t = try? item.promisedItemResourceValues(forKeys:[.contentModificationDateKey]).contentModificationDate
else {return}
print ("\(t) \(item.lastPathComponent)")
}
} catch {
print (error)
}
答案 4 :(得分:0)
// MARK: - String
extension String {
func stringByAppendingPathComponent(path: String) -> String {
let nsSt = self as NSString
return nsSt.appendingPathComponent(path)
}
}
// MARK: - File manager
let fileManagerController = FileManager.default
// MARK: - Application Document Directory
// NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] return an array of String, we will catch just the first item from array
let applicationDocumentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
// MARK: - File path
// Combined with helpers from String extension
let filePath = applicationDocumentsDirectory.stringByAppendingPathComponent(path: name)
do {
let atributes = try fileManagerController.attributesOfItem(atPath: filePath)
// File creation date
if let fileDate = atributes[FileAttributeKey.creationDate] as? Date {
// fileDate has a String value
print(fileDate)
// Will print a creation date of file
}
} catch let error as NSError {
print("Failure to know creation date \(error.description)")
}
答案 5 :(得分:0)
Swift 3.0 Sierra 10.12
获取日期(创建或修改)的排序数组:
func enumAndSortFilesAt(path: String){
let fm = FileManager.default
let url = URL(fileURLWithPath: path)
let optionMask: FileManager.DirectoryEnumerationOptions = [
.skipsHiddenFiles
]
let keys = [URLResourceKey.contentModificationDateKey]
guard let files = try? fm.contentsOfDirectory(at: url,
includingPropertiesForKeys : keys,
options: optionMask ) else {
return
}
let ordered = files.sorted { ( u1: URL, u2: URL) -> Bool in
do{
let values1 = try u1.resourceValues(forKeys: [.creationDateKey, .contentModificationDateKey])
let values2 = try u2.resourceValues(forKeys: [.creationDateKey, .contentModificationDateKey])
// if let date1 = values1.creationDate, let date2 = values2.creationDate {
if let date1 = values1.contentModificationDate, let date2 = values2.contentModificationDate {
return date1.compare(date2) == ComparisonResult.orderedAscending
}
}catch _{
}
return true
}
for f in ordered {
do {
let values = try f.resourceValues(forKeys: [.creationDateKey, .contentModificationDateKey])
if let date = values.creationDate{
//let date : Date? = values.contentModificationDate
print(f.lastPathComponent, " ", date)
}
}
catch _{
}
}
}
答案 6 :(得分:0)
Swift 5.0。根据先前的答案进行简单扩展:
extension FileManager {
enum ContentDate {
case created, modified, accessed
var resourceKey: URLResourceKey {
switch self {
case .created: return .creationDateKey
case .modified: return .contentModificationDateKey
case .accessed: return .contentAccessDateKey
}
}
}
func contentsOfDirectory(atURL url: URL, sortedBy: ContentDate, ascending: Bool = true, options: FileManager.DirectoryEnumerationOptions = [.skipsHiddenFiles]) throws -> [String]? {
let key = sortedBy.resourceKey
var files = try contentsOfDirectory(at: url, includingPropertiesForKeys: [key], options: options)
try files.sort {
let values1 = try $0.resourceValues(forKeys: [key])
let values2 = try $1.resourceValues(forKeys: [key])
if let date1 = values1.allValues.first?.value as? Date, let date2 = values2.allValues.first?.value as? Date {
return date1.compare(date2) == (ascending ? .orderedAscending : .orderedDescending)
}
return true
}
return files.map { $0.lastPathComponent }
}
}