【问题标题】:How can I get the file creation date using URL resourceValues method in Swift 3?如何在 Swift 3 中使用 URL resourceValues 方法获取文件创建日期?
【发布时间】:2017-01-22 20:45:01
【问题描述】:

感谢这个论坛中的各种有用的帖子,我有一些代码可用于获取单个用户选择的 NSURL 的创建日期。但是,我无法让代码为硬编码的 NSURL 工作,也不能在通过 NSFileManager 枚举器的循环中工作。

我不是专业程序员;我制作的应用程序是办公工具。我的最终目标是简单地根据创建日期对 NSURL 对象数组进行排序。

我正在使用的代码如下,功能正常,但如果我尝试使用注释行来评估特定的 PDF 文件,我会收到以下错误:

当我尝试将此代码添加到通过 NSFileManager 枚举器获取的 NSURL 对象循环时,我得到了完全相同的错误。

我不知道如何使用错误指令来解决问题。如果有人可以提供帮助,那将是巨大的。谢谢。

let chosenURL = NSOpenPanel().selectFile

    //let chosenURL = NSURL.fileURL(withPath: "/Users/craigsmith/Desktop/PDFRotator Introduction.pdf")

    do
    {
        var cr:AnyObject?
        try chosenURL?.getResourceValue(&cr, forKey: URLResourceKey.creationDateKey)

        if (cr != nil)
        {
            if let createDate = cr as? NSDate
            {
                print("Seems to be a date: \(createDate)")

                let theComparison = createDate.compare(NSDate() as Date)

                print("Result of Comparison: \(theComparison)")  // Useless

                let interval = createDate.timeIntervalSinceNow

                print("Interval: \(interval)")

                if interval < (60*60*24*7*(-1))
                {
                    print("More than a week ago")

                }
                else
                {
                    print("Less than a week ago")
                }
            }
            else
            {
                print("Not a Date")
            }
        }
    }
    catch
    {

    }

【问题讨论】:

    标签: swift nsurl nsfilemanager swift3


    【解决方案1】:

    您可以按如下方式扩展 URL:

    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)
            }
        }
    }
    

    用法:

    print(yourURL.creationDate)
    

    【讨论】:

    • 效果很好,但代码看起来与@OOPer 发布的非常相似,我仍然不清楚为什么这个特定的排列函数,而其他的(包括我的)没有。
    • 对于 iOS 你应该使用 documentDirectory 而不是用户目录
    • 在 iOS 中,应用程序总是被沙盒化。每次运行应用程序时,它都会位于不同的文件夹中。所以即使它有一个有效的日期,它也不会是你要找的。这实际上与在应用启动时获取 Date() 相同。
    • @fs_tigre in iOS URL(fileURLWithPath: NSHomeDirectory()) 指向捆绑包的位置。这是您的 documentDirectory 所在的位置(类似于 file:///var/mobile/Containers/Data/Application/FBD3746E-2530-4A82-AAA4-B3FFC329600D/),每次启动应用程序时,最后一个路径组件都会更改(此称为沙箱)。这是您试图获取创建日期的目录,但没有任何意义。您需要获取其子目录 Documents 的创建日期。
    • FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.creation
    【解决方案2】:

    根据URL和URLResourceValues的header doc,你可能需要这样写:

    (此代码假设chosenURL 的类型为URL?。)

    do {
        if
            let resValues = try chosenURL?.resourceValues(forKeys: [.creationDateKey]),
            let createDate = resValues.creationDate
        {
            //Use createDate here...
        }
    } catch {
        //...
    }
    

    (如果您的 chosenURL 是 NSURL? 类型,请尝试此代码。)

    do {
        if
            let resValues = try (chosenURL as URL?)?.resourceValues(forKeys: [.creationDateKey]),
            let createDate = resValues.creationDate
        {
            //Use createDate here...
            print(createDate)
        }
    } catch {
        //...
    }
    

    我建议您尽可能使用URL 而不是NSURL。

    【讨论】:

    • 谢谢,但编译器抱怨 Value of type [URLResourceKey:Any] has no member 'creationDate' 对我来说似乎很疯狂。
    • @CraigSmith,对不起,我错过了你在标题和评论中指定NSURL,我的代码假设chosenURL 是URL? 类型。当我将chosenURL 声明为URL? 时,它实际上在我的Xcode 8 (8A218a) 中编译没有错误。请尝试。
    • 这个 URL v NSURL 的东西太疯狂了。您是正确的,您的代码确实可以使用单个 URL 或 NSURL,但是,当我尝试在 NSFileManager 派生的 Enumerator(我相信是 NSURL)中使用它时,编译器会抱怨 Initializer for conditional binding must have Optional type, no URLResourceValues. 与任一排列相同的错误,事实上,Xcode(8) 在两种情况下都会提示代码更正到相同的错误。这让我很抓狂。
    【解决方案3】:

    在 swift 5 中,我使用以下代码:

    let attributes = try! FileManager.default.attributesOfItem(atPath: item.path)
    let creationDate = attributes[.creationDate] as! Date
    

    使用以下代码对数组进行排序

    fileArray = fileArray.sorted(by: {
            $0.creationDate.compare($1.creationDate) == .orderedDescending
        })
    

    更多关于 FileAttributeKey 的信息在这里:https://developer.apple.com/documentation/foundation/fileattributekey

    【讨论】:

    • 自 Swift 3 以来日期符合 Comparable 协议
    猜你喜欢
    • 1970-01-01
    • 2011-05-23
    • 2015-04-21
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多