打开(FileManager.default.fileSystemRepresentation(withPath:路径),O_EVTONLY)returns -1
open(FileManager.default.fileSystemRepresentation(withPath: path), O_EVTONLY) returns -1
我正在使用 SKQueue 来监控 mac 文件系统中的一些文件夹。根据文档,我已将目录路径添加到队列中,但我注意到在添加路径时,SKQueue 中的以下代码行返回 -1,因此无法监视我的文件夹。
以下是文档中的代码,写在控制器中class。
import SKQueue
class SomeClass: SKQueueDelegate {
func receivedNotification(_ notification: SKQueueNotification, path: String, queue: SKQueue) {
print("\(notification.toStrings().map { [=13=].rawValue }) @ \(path)")
}
}
let delegate = SomeClass()
let queue = SKQueue(delegate: delegate)!
queue.addPath("/Users/steve/Documents")
queue.addPath("/Users/steve/Documents/dog.jpg")
以下是SKQueue依赖中的代码。
public func addPath(_ path: String, notifyingAbout notification: SKQueueNotification = SKQueueNotification.Default) {
var fileDescriptor: Int32! = watchedPaths[path]
if fileDescriptor == nil {
fileDescriptor = open(FileManager.default.fileSystemRepresentation(withPath: path), O_EVTONLY)
guard fileDescriptor >= 0 else { return }
watchedPaths[path] = fileDescriptor
}
fileDescriptor =
open(FileManager.default.fileSystemRepresentation(withPath: path),
O_EVTONLY)
以上代码返回 -1,因此失败。
调用 open()
失败,可能是由于权限不足。自 macOS 10.15 起,应用无法在未经许可的情况下访问某些文件和文件夹(例如,用户的主目录)。 Read more here.
我得到了相同的 -1 return 代码,但不明白为什么。在寻找解决方案时,我在 https://github.com/MartinJNash/SwiftFolderMonitor 偶然发现了 SwiftFolderMonitor。 class 有效,所以我知道这不是权限问题。
SwiftFolderMonitor 使用 DispatchSource.makeFileSystemObjectSource 而不是 kevent,但它也采用 URL 参数而不是字符串路径。我修改了 SKQueue 以使用 URL 而不是 String 并且它有效。
这是我修改后的 addPath:
public func addPath(url: URL, notifyingAbout notification: SKQueueNotification = SKQueueNotification.Default) {
let path = url.absoluteString
var fileDescriptor: Int32! = watchedPaths[path]
if fileDescriptor == nil {
fileDescriptor = open((url as NSURL).fileSystemRepresentation, O_EVTONLY)
guard fileDescriptor >= 0 else { return }
watchedPaths[path] = fileDescriptor
}
var edit = kevent(
ident: UInt(fileDescriptor),
filter: Int16(EVFILT_VNODE),
flags: UInt16(EV_ADD | EV_CLEAR),
fflags: notification.rawValue,
data: 0,
udata: nil
)
kevent(kqueueId, &edit, 1, nil, 0, nil)
if !keepWatcherThreadRunning {
keepWatcherThreadRunning = true
DispatchQueue.global().async(execute: watcherThread)
}
}
我不知道为什么会这样,也许其他人可以对此有所启发。
我仍在尝试这两种解决方案,但看起来 SwiftFolderMonitor 可以满足我的所有需求(我只需要知道特定文件何时更改),而且它的代码简洁明了,所以我想我会使用它通过 SKQueue.
希望对您有所帮助。
我正在使用 SKQueue 来监控 mac 文件系统中的一些文件夹。根据文档,我已将目录路径添加到队列中,但我注意到在添加路径时,SKQueue 中的以下代码行返回 -1,因此无法监视我的文件夹。
以下是文档中的代码,写在控制器中class。
import SKQueue
class SomeClass: SKQueueDelegate {
func receivedNotification(_ notification: SKQueueNotification, path: String, queue: SKQueue) {
print("\(notification.toStrings().map { [=13=].rawValue }) @ \(path)")
}
}
let delegate = SomeClass()
let queue = SKQueue(delegate: delegate)!
queue.addPath("/Users/steve/Documents")
queue.addPath("/Users/steve/Documents/dog.jpg")
以下是SKQueue依赖中的代码。
public func addPath(_ path: String, notifyingAbout notification: SKQueueNotification = SKQueueNotification.Default) {
var fileDescriptor: Int32! = watchedPaths[path]
if fileDescriptor == nil {
fileDescriptor = open(FileManager.default.fileSystemRepresentation(withPath: path), O_EVTONLY)
guard fileDescriptor >= 0 else { return }
watchedPaths[path] = fileDescriptor
}
fileDescriptor = open(FileManager.default.fileSystemRepresentation(withPath: path), O_EVTONLY)
以上代码返回 -1,因此失败。
调用 open()
失败,可能是由于权限不足。自 macOS 10.15 起,应用无法在未经许可的情况下访问某些文件和文件夹(例如,用户的主目录)。 Read more here.
我得到了相同的 -1 return 代码,但不明白为什么。在寻找解决方案时,我在 https://github.com/MartinJNash/SwiftFolderMonitor 偶然发现了 SwiftFolderMonitor。 class 有效,所以我知道这不是权限问题。
SwiftFolderMonitor 使用 DispatchSource.makeFileSystemObjectSource 而不是 kevent,但它也采用 URL 参数而不是字符串路径。我修改了 SKQueue 以使用 URL 而不是 String 并且它有效。
这是我修改后的 addPath:
public func addPath(url: URL, notifyingAbout notification: SKQueueNotification = SKQueueNotification.Default) {
let path = url.absoluteString
var fileDescriptor: Int32! = watchedPaths[path]
if fileDescriptor == nil {
fileDescriptor = open((url as NSURL).fileSystemRepresentation, O_EVTONLY)
guard fileDescriptor >= 0 else { return }
watchedPaths[path] = fileDescriptor
}
var edit = kevent(
ident: UInt(fileDescriptor),
filter: Int16(EVFILT_VNODE),
flags: UInt16(EV_ADD | EV_CLEAR),
fflags: notification.rawValue,
data: 0,
udata: nil
)
kevent(kqueueId, &edit, 1, nil, 0, nil)
if !keepWatcherThreadRunning {
keepWatcherThreadRunning = true
DispatchQueue.global().async(execute: watcherThread)
}
}
我不知道为什么会这样,也许其他人可以对此有所启发。
我仍在尝试这两种解决方案,但看起来 SwiftFolderMonitor 可以满足我的所有需求(我只需要知道特定文件何时更改),而且它的代码简洁明了,所以我想我会使用它通过 SKQueue.
希望对您有所帮助。