ios - 监视文件更改时打开太多文件

标签 ios swift monitoring grand-central-dispatch ipados

我正在为 iPad 开发一个基于文档浏览器的应用程序。我一直用SKQueue监视文件的更改,以确保当用户在文档浏览器中执行操作时其元数据保持最新。启动监控代码:

    // Set up the queue
    let delegate = self
    queue = SKQueue(delegate: delegate)!
    // Remove all existing paths
    queue?.removeAllPaths()

    // Get the list of PDF URLs using a function that enumerates a folder's contents
    let pdfFiles = getFolderContents(rootFolder: myDocumentsFolder, extensionWanted: "pdf")
    for pdfFilePath in pdfFiles.filePaths {
        queue?.addPath(pdfFilePath.path)
    }
    for pdfFolderPath in pdfFiles.folderPaths {
        queue?.addPath(pdfFolderPath.path)
    }

我开发了自己的逻辑来响应来自该队列的通知,但我不会在应用运行时从队列中删除任何项目。

问题 - 似乎当观看的项目数量超过 200 个(文件和文件夹)时,系统会崩溃,控制台报告错误 24:打开的文件过多。之后就无法再进行任何文件的读写操作。

根据我从搜索中收集到的信息,iOS 和 iPadOS 似乎不允许同时访问超过 256 个文件描述符,这意味着监视文件更改的 GCD 方法将受到影响同样的限制。

是否有任何方法可以监视文件更改而不受此类限制?还有其他建议吗?

最佳答案

经过大量研究和实验,我终于可以验证,对于 MacOS、iOS 和 iPadOS,允许打开的文件描述符的默认最大数量确实是 256。这可以在 MacOS 中轻松更改 - 请参阅文章 here 。但是,iOS 和 iPadOS 本质上更加封闭,因此没有可靠的方法来更改这些平台上的此限制。

因此,良好的做法是:

  1. 尽量避免设计需要打开如此多文件描述符的应用。
  2. 监视目录,而不是单个文件。使用大多数可用于监视文件系统的工具,您会收到受监视目录中任何文件更改的通知。只需从那里实现您的逻辑,通过枚举文件夹并将其新状态与保存的状态进行比较。您可以在这个 SO thread 的前两个答案中找到很好的代码。 .

注意:我建议使用枚举而不是其他方法来获取文件系统状态,因为其他方法往往会在模拟器和实际设备之间给出不兼容的结果(符号链接(symbolic link)解析的不同处理)。

  • 确保您选择的文件系统监控方法可以查询正在监控的项目数量,并在用户接近设定限制时发出警报。请记住,256 个打开的文件还必须包括应用程序使用的所有文件,包括应用程序 bundle 中的文件和实际使用的文件。所以要留有足够的安全裕度。
  • 就我而言,我的应用程序使用 UIDocumentBrowserViewController,或者换句话说 - Apple 自己的文件应用程序,以允许用户管理他们的文件。我必须使元数据与文件系统状态保持同步,并且我无法控制用户的文件管理习惯。更复杂的是,"file"应用程序本身可用于修改应用程序的文件系统 - 当我的应用程序未处于事件状态时。

    因此,我做了两件事:

    1. 我将应用程序委托(delegate)的 applicationDidEnterBackground 和 applicationWillTerminate 方法中的文件系统详细状态保存到应用程序支持中的 json 文件中,并在应用程序启动时将其与文件系统的新枚举进行比较 - 并提醒用户如有不匹配,建议下次使用应用自带的文件浏览器。
    2. 我创建了自己的 swift 包,名为 SFSMonitor ,用于监视文件系统。它基于非常方便的SKQueue (我强烈推荐),但它不使用监控 kevent,而是使用 Dispatch Sources - Apple 提倡的一种更现代的方法。它类似于 Apple 自己的目录监视器(您可以找到 here ),但它不是监视一个目录,而是允许您创建和管理它们的整个队列。此类允许您设置受监视文件描述符的最大数量,并在达到该限制时收到通知。

    关于ios - 监视文件更改时打开太多文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61452583/

    相关文章:

    ios - 如何在没有手机轮廓的 .xib 文件中创建新 View ?

    ios - 如何在 UIButton 之外编辑 UIButton 属性

    ios - Swift:在标签周围画一个圆圈

    java - 如何知道java进程等待了多少时间

    iphone - 当 wifi 源失去连接时如何检测互联网可达性丢失?

    ios - 在 Swift 或 Objective-C 中打印原始 HTTP 请求的便捷方式?

    ios - 如果 subscribeOn 背景,RxSwift TestScheduler 不工作

    ios - Swift - collectionView 首次加载时如何自动选择单元格?

    containers - 如何衡量Mesos中每个容器的CPU利用率?

    MySQL 不将慢速查询记录到表中