動作する私のコードでは、_[String]?
_に格納されているファイル(lastPathComponent
)の名前を含む_/Documents/
_を返します-最後に変更された日付順に並べられています。
私はおそらくあまりにも多くのステップを使用していると思います。コードを減らす方法についてここでアドバイスを探しています。
現在必要な結果を達成するために、私は2つの中間辞書_var attributesDictionary: [String : AnyObject]?
_とvar urlDictionary = [NSURL:NSDate]()
を作成しています。最初の_[NSURL]
_をループする2つのステップを使用しています-_.resourceValuesForKeys
_はattributesDictionary
を初期化します。次に、urlDictionary
にデータを入力して、キーNSURLContentModificationDateKey
のURLと値が含まれるようにします。
urlDictionary
とattributesDictionary
を作成せずに、ループを必要とせずに、この結果を達成する方法があるはずだと私はかなり確信しています。おそらくurlArray
から直接。これが私の現在のコードです:
編集:最初のコメントでArthur Gevorkyanが指摘したように、_do{}
_ sは必要ありませんでした。
_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
}
}
_
考えられる解決策:
_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
}
_
完全なソリューションを備えた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
}
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].
結局、あなたはあなたがすでにしたことと同等の何かに終わるでしょう。あなたのコードは少し洗練されていると思いますが、アプローチはかなり良いです。
Swift5.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 }
}
}
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 _{
}
}
}
// 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)")
}