将缩略图附加到通知时,文件在哪里?

Sti*_*Sti 7 notifications ios uilocalnotification swift

我正在为丰富的通知添加缩略图.我生成的图像用作附件,如下所示:

let url = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let fileURL = url.appendingPathComponent("someImageName", isDirectory: false).appendingPathExtension("png")
do{
    try UIImagePNGRepresentation(image)?.write(to: fileURL)
}catch{
    print("Could not write: ", error)
}
Run Code Online (Sandbox Code Playgroud)

这很成功.如果我现在运行此代码:

let content = try? FileManager.default.contentsOfDirectory(atPath: NSTemporaryDirectory())
print(content ?? "error")
Run Code Online (Sandbox Code Playgroud)

它打印出来:["someImageName.png"].

然后我创建附件,如下所示:

let attachment = try? UNNotificationAttachment(identifier: "image", url: url, options: nil)
let content = UNMutableNotificationContent()
content.title = "Test"
content.attachments = [attachment!]
let request = UNNotificationRequest(identifier: "someID", content:content, trigger: /*someTrigger*/)
UNUserNotificationCenter.current().add(request, withCompletionHandler:...)
Run Code Online (Sandbox Code Playgroud)

这一切都有效.通知已发送,附件已附加.但是,如果我现在打印出临时文件夹的内容,它就是空的!我之前保存的图像已从此文件夹中删除.

经过大量的反复试验,我发现在添加通知的时候图像被删除了.为什么我的通知会删除我的图片?我找不到任何关于此的文档!

如果我执行上述所有操作,但注释掉这一行://content.attachments = [attachment!]表示我的存储图像不会作为附件添加到我的通知中,那么我的图像不会从临时文件夹中删除!

这些文件在使用后是否被清理?或者在通知消失后我是否必须查看其他文件夹并手动清理它们?我不希望我的应用程序创建数百个永远不会再次使用的图像,而无法删除它们.

Meh*_*ufi 3

这些天我面临同样的问题,答案就在文档中,乍一看不太容易看到,但它就在那里:

关于UNNotificationAttachment

...一旦验证,附加文件将被移至附件数据存储中,以便所有适当的进程都可以访问它们。

关于init方法:

当您安排包含附件的通知请求时,附件的文件将移动到新位置,以便于适当的进程进行访问。移动后,访问该文件的唯一方法是使用 UNUserNotificationCenter 对象的方法。

请注意:

位于应用程序包内的附件将被复制而不是移动。

所以我决定:

像您一样编写文件并在 a 中编写它的副本NSTemporaryDirectory()我使用此示例轻松创建和删除 TempDirectory (Swift 4.0)(感谢Ole Begemman):

import Foundation

/// A wrapper around a temporary file in a temporary directory. The directory
/// has been especially created for the file, so it's safe to delete when you're
/// done working with the file.
///
/// Call `deleteDirectory` when you no longer need the file.
struct TemporaryFile {
    let directoryURL: URL
    let fileURL: URL
    /// Deletes the temporary directory and all files in it.
    let deleteDirectory: () throws -> Void
    
    /// Creates a temporary directory with a unique name and initializes the
    /// receiver with a `fileURL` representing a file named `filename` in that
    /// directory.
    ///
    /// - Note: This doesn't create the file!
    init(creatingTempDirectoryForFilename filename: String) throws {
        let (directory, deleteDirectory) = try FileManager.default
            .urlForUniqueTemporaryDirectory()
        self.directoryURL = directory
        self.fileURL = directory.appendingPathComponent(filename)
        self.deleteDirectory = deleteDirectory
    }
}

extension FileManager {
    /// Creates a temporary directory with a unique name and returns its URL.
    ///
    /// - Returns: A tuple of the directory's URL and a delete function.
    ///   Call the function to delete the directory after you're done with it.
    ///
    /// - Note: You should not rely on the existence of the temporary directory
    ///   after the app is exited.
    func urlForUniqueTemporaryDirectory(preferredName: String? = nil) throws
        -> (url: URL, deleteDirectory: () throws -> Void)
    {
        let basename = preferredName ?? UUID().uuidString
        
        var counter = 0
        var createdSubdirectory: URL? = nil
        repeat {
            do {
                let subdirName = counter == 0 ? basename : "\(basename)-\(counter)"
                let subdirectory = temporaryDirectory
                    .appendingPathComponent(subdirName, isDirectory: true)
                try createDirectory(at: subdirectory, withIntermediateDirectories: false)
                createdSubdirectory = subdirectory
            } catch CocoaError.fileWriteFileExists {
                // Catch file exists error and try again with another name.
                // Other errors propagate to the caller.
                counter += 1
            }
        } while createdSubdirectory == nil
        
        let directory = createdSubdirectory!
        let deleteDirectory: () throws -> Void = {
            try self.removeItem(at: directory)
        }
        return (directory, deleteDirectory)
    }
}
Run Code Online (Sandbox Code Playgroud)

将文件附加到 TempURL 后,文件将被移动,您可以删除 TempDirectory。

后来进行了一些测试,可以肯定的是,我终于发现我的文件(在我的例子中是图像)存储在这里:

URL: file:///var/mobile/Library/SpringBoard/PushStore/Attachments/com.YourApp.Name/8e52c6673f6e735f83535486bf750ba1118a3ade.png
Run Code Online (Sandbox Code Playgroud)

显示或清理通知中心后,文件将被删除是的。

为什么这一切?-> 沙箱!当我将我的文件附加到触发器(此处为 UNCalendarNotificationTrigger)时,我命名了负责我的文件的日历以将其显示在我的通知中,但要处理它,它必须将文件放在 HIS 目录中。

希望它有帮助,我花了一段时间才发现所有这些谜团!