更改iPhone/Documents目录的通知
问题描述:
我们有一个使用文件共享的应用程序。 UIFileSharingEnable设置等,它似乎工作正常,但我正在寻找某种类型的文件已被添加/删除iPhone端的通知。任何人都可以建议吗?更改iPhone/Documents目录的通知
提前欢呼。
答
This thread在Apple开发者论坛上可能会感兴趣,其中建议您在其自己的线程中运行kqueue,跟踪应用程序的Documents文件夹。
苹果公司的技术跟进一些sample code here:
- (void)kqueueFired
{
int kq;
struct kevent event;
struct timespec timeout = { 0, 0 };
int eventCount;
kq = CFFileDescriptorGetNativeDescriptor(self->_kqRef);
assert(kq >= 0);
eventCount = kevent(kq, NULL, 0, &event, 1, &timeout);
assert((eventCount >= 0) && (eventCount < 2));
if (eventCount == 1) {
NSLog(@"dir changed");
}
CFFileDescriptorEnableCallBacks(self->_kqRef, kCFFileDescriptorReadCallBack);
}
static void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info)
{
ViewController * obj;
obj = (ViewController *) info;
assert([obj isKindOfClass:[ViewController class]]);
assert(kqRef == obj->_kqRef);
assert(callBackTypes == kCFFileDescriptorReadCallBack);
[obj kqueueFired];
}
- (IBAction)testAction:(id)sender
{
#pragma unused(sender)
NSString * docPath;
int dirFD;
int kq;
int retVal;
struct kevent eventToAdd;
CFFileDescriptorContext context = { 0, self, NULL, NULL, NULL };
CFRunLoopSourceRef rls;
docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
assert(docPath != 0);
NSLog(@"%@", docPath);
dirFD = open([docPath fileSystemRepresentation], O_EVTONLY);
assert(dirFD >= 0);
kq = kqueue();
assert(kq >= 0);
eventToAdd.ident = dirFD;
eventToAdd.filter = EVFILT_VNODE;
eventToAdd.flags = EV_ADD | EV_CLEAR;
eventToAdd.fflags = NOTE_WRITE;
eventToAdd.data = 0;
eventToAdd.udata = NULL;
retVal = kevent(kq, &eventToAdd, 1, NULL, 0, NULL);
assert(retVal == 0);
assert(self->_kqRef == NULL);
self->_kqRef = CFFileDescriptorCreate(NULL, kq, true, KQCallback, &context);
assert(self->_kqRef != NULL);
rls = CFFileDescriptorCreateRunLoopSource(NULL, self->_kqRef, 0);
assert(rls != NULL);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
CFRelease(rls);
CFFileDescriptorEnableCallBacks(self->_kqRef, kCFFileDescriptorReadCallBack);
}
答
下面是使用大中央调度(GCD),它允许你从NSNotificationCenter收到文件更改通知的替代解决方案:
这些变量添加到类的接口:
// Dispatch queue
dispatch_queue_t _dispatchQueue;
// A source of potential notifications
dispatch_source_t _source;
下面的代码添加到执行:
#define fileChangedNotification @"fileChangedNotification"
// Get the path to the home directory
NSString * homeDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
// Create a new file descriptor - we need to convert the NSString to a char * i.e. C style string
int filedes = open([homeDirectory cStringUsingEncoding:NSASCIIStringEncoding], O_EVTONLY);
// Create a dispatch queue - when a file changes the event will be sent to this queue
_dispatchQueue = dispatch_queue_create("FileMonitorQueue", 0);
// Create a GCD source. This will monitor the file descriptor to see if a write command is detected
// The following options are available
/*!
* @typedef dispatch_source_vnode_flags_t
* Type of dispatch_source_vnode flags
*
* @constant DISPATCH_VNODE_DELETE
* The filesystem object was deleted from the namespace.
*
* @constant DISPATCH_VNODE_WRITE
* The filesystem object data changed.
*
* @constant DISPATCH_VNODE_EXTEND
* The filesystem object changed in size.
*
* @constant DISPATCH_VNODE_ATTRIB
* The filesystem object metadata changed.
*
* @constant DISPATCH_VNODE_LINK
* The filesystem object link count changed.
*
* @constant DISPATCH_VNODE_RENAME
* The filesystem object was renamed in the namespace.
*
* @constant DISPATCH_VNODE_REVOKE
* The filesystem object was revoked.
*/
// Write covers - adding a file, renaming a file and deleting a file...
_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,filedes,
DISPATCH_VNODE_WRITE,
_dispatchQueue);
// This block will be called when teh file changes
dispatch_source_set_event_handler(_source, ^(){
// We call an NSNotification so the file can change can be detected anywhere
[[NSNotificationCenter defaultCenter] postNotificationName:fileChangedNotification object:Nil];
});
// When we stop monitoring the file this will be called and it will close the file descriptor
dispatch_source_set_cancel_handler(_source, ^() {
close(filedes);
});
// Start monitoring the file...
dispatch_resume(_source);
//...
// When we want to stop monitoring the file we call this
//dispatch_source_cancel(source);
// To recieve a notification about the file change we can use the NSNotificationCenter
[[NSNotificationCenter defaultCenter] addObserverForName:fileChangedNotification object:Nil queue:Nil usingBlock:^(NSNotification * notification) {
NSLog(@"File change detected!");
}];
+0
非常感谢!简单和完美的作品。 – Ravi 2014-06-26 15:08:39
作品一种享受! 谢谢亚历克斯。 – 2010-07-07 14:53:10
你需要包括这些标题: '#包括 的#include 的#include 的#include 的#include ' –
Dustin
2011-05-06 15:14:45
什么,如果我想在监测和发现文档文件夹中调用某个函数的文件,还有我把这三个功能放在appdelegate类或什么 – AMH 2011-07-18 07:13:26