2010-01-28 12 views
8

मैं FSEvents का उपयोग कर कोको प्रोजेक्ट में निर्देशिका और डिस्क परिवर्तनों को सुन रहा हूं। जब रूट फ़ोल्डर का नाम बदल दिया जाता है या हटा दिया जाता है तो मुझे ईवेंट प्राप्त करने की आवश्यकता होती है। तो, FSEventStream बनाते समय, मैंने kFSEventStreamCreateFlagWatchRoot पारित किया। लेकिन अगर मैं रूट फ़ोल्डर को हटा या नाम बदलता हूं तो मुझे संबंधित FSEventStreamEventFlags नहीं मिल रहा है। कोई विचार क्या संभवतः मुद्दा हो सकता है। मैं एक यूएसबी माउंटेड डिवाइस में बदलावों के लिए सुन रहा हूँ। मैंने FSEventStreamCreate और FSEventStreamCreateRelativeToDevice दोनों का उपयोग किया। एक बात मैं नोटिस है जब मैं FSEventStreamCreate मैं निम्न त्रुटि संदेश मिलता है के साथ की कोशिश करते हुए FSEventStream बनाने:फ़ाइल सिस्टम के लिए कैसे सुनें मैक - केएफएसईवेंटस्ट्रीमक्रेटफ्लैगवैच रूट

(CarbonCore.framework) FSEventStreamCreate: watch_all_parents:
त्रुटि fd 7 के लिए kqueue जोड़ने की कोशिश कर (/Volumes/NO NAME; कार्रवाई समर्थित नहीं)

लेकिन FSEventStreamCreateRelativeToDevice के साथ कोई त्रुटि नहीं है लेकिन अभी भी kFSEventStreamEventFlagRootChanged ईवेंट झंडे में नहीं मिल रही है। साथ ही, FSEventStreamCreateRelativeToDevice सेब का उपयोग करते हुए सृजन का कहना है कि अगर मैं रूट पथ परिवर्तनों को सुनना चाहता हूं तो emty string "" पास करें। लेकिन मैं खाली स्ट्रिंग पास करके रूट पथ परिवर्तनों को सुनने में सक्षम नहीं हूं। लेकिन जब मैं "/" पास करता हूं तो यह काम करता है। लेकिन "/" के लिए भी मुझे कोई उचित FSEventStreamEventFlags नहीं मिलता है। मैं कोड यहाँ चिपकाने हूँ:

-(void) subscribeFileSystemChanges:(NSString*) path 
{ 
    PRINT_FUNCTION_BEGIN; 

    // if already subscribed then unsubscribe 
    if (stream) 
    { 
     FSEventStreamStop(stream); 
     FSEventStreamInvalidate(stream); /* will remove from runloop */ 
     FSEventStreamRelease(stream); 
    } 

    FSEventStreamContext cntxt = {0}; 
    cntxt.info = self; 

    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void**)&path, 1, NULL); 


    stream = FSEventStreamCreate(NULL, &feCallback, &cntxt, 
           pathsToWatch, kFSEventStreamEventIdSinceNow, 1, 
           kFSEventStreamCreateFlagWatchRoot); 


    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), 
            kCFRunLoopDefaultMode); 

    FSEventStreamStart(stream); 


} 

कॉल वापस समारोह:

static void feCallback(ConstFSEventStreamRef streamRef, void* pClientCallBackInfo, 
         size_t numEvents, void* pEventPaths, const FSEventStreamEventFlags eventFlags[], 
         const FSEventStreamEventId eventIds[]) 

{ 
char** ppPaths = (char**)pEventPaths; int i; 

    for (i = 0; i < numEvents; i++) 
    { 
     NSLog(@"Event Flags %lu Event Id %llu", eventFlags[i], eventIds[i]); 
     NSLog(@"Path changed: %@", 
       [NSString stringWithUTF8String:ppPaths[i]]); 
    }  
} 

धन्यवाद अग्रिम में एक बहुत।

+0

मुझे यकीन नहीं है कि वहां क्या गलत है क्योंकि मैंने कभी भी FSEvents का उपयोग नहीं किया है। ऐसा कहकर, ऐसा लगता है कि आप जो करने की कोशिश कर रहे हैं वह डिस्क आर्बिट्रेशन फ्रेमवर्क का उपयोग करके बेहतर किया जा सकता है। –

उत्तर

3

मैं एक ही समस्या थी की तरह हैंडलर इंस्टॉल और मुझे लगता है कि मैं इसे समझ से बाहर। स्पष्ट रूप से FSEventStreamCreateRelativeToDevice का उपयोग करते समय बस बस बस्ट किया गया है। आपको FSEventStreamCreate का उपयोग करना होगा। चूंकि यदि आप ऐतिहासिक घटना आईडी पर भरोसा कर रहे हैं, तो पूर्व फॉर्म बेहतर है, इसलिए आपको 2 स्ट्रीम बनाने की आवश्यकता हो सकती है। साथ ही, ध्यान दें कि ऐसा लगता है कि यदि आपका ऐप नहीं चल रहा है तो आपको kEventFlagChangedRoot नहीं मिला है, इसलिए जब आप शुरू करते हैं तो आपको निर्देशिका को स्टेट करना होगा।

3

मुझे लगता है कि वॉल्यूम नाम में परिवर्तन FSEvents द्वारा रिपोर्ट की गई फ़ाइल सिस्टम में बदलाव के रूप में नहीं गिना जाता है। याद रखें, वॉल्यूम नाम स्वयं फ़ाइल सिस्टम एंट्री के रूप में वास्तव में मौजूद नहीं है। /Volumes के तहत वाले ओएस द्वारा पकाया जाता है।

इसके बजाय Disk Arbitration द्वारा कवर किया गया है।

एक संक्षिप्त नमूना कोड निम्नानुसार है। सबसे पहले, कॉलबैक

#import <DiskArbitration/DiskArbitration.h> 
void callBack(DADiskRef disk,CFArrayRef keys,void *context) 
{ 
    CFDictionaryRef dict=DADiskCopyDescription(disk); 
    NSString*mountPoint=[(NSDictionary*)dict objectForKey:(NSString*)kDADiskDescriptionVolumePathKey]; 
    NSLog(@"disk at %@:",mountPoint); 
    for(NSString*key in (NSArray*)keys){ 
    NSLog(@"key %@ changed: %@",key,[(NSDictionary*)dict objectForKey:key]);  
    } 
    CFRelease(dict); 
} 

को परिभाषित करने और फिर इस

DASessionRef session=DASessionCreate(NULL); 
DARegisterDiskDescriptionChangedCallback(session, NULL, NULL, callBack, NULL); 
DASessionScheduleWithRunLoop(session, [[NSRunLoop currentRunLoop] getCFRunLoop], kCFRunLoopCommonModes); 
+0

HI उत्तर के लिए धन्यवाद। लेकिन मैं FSEVENTS के साथ एक समाधान की तलाश में हूं क्योंकि वास्तव में मुझे परेशान करता है कि अगर मैं रूट पथ "/" या किसी उपनिर्देशिका देता हूं और फिर इसे हटा या नाम बदलता हूं तो मुझे कॉल में उचित घटना झंडे नहीं मिल रहे हैं। मैंने प्रश्न में कोड चिपकाया है। एक अन्य प्रश्न, मुझे डिस्क मध्यस्थता का पूरा संदर्भ कहां मिल सकता है क्योंकि मुझे नहीं पता कि मुझे कौन सी चाबियाँ देखना चाहिए या देखना चाहिए।या इनशॉर्ट, आप kDADiskDescriptionVolumePathKey या kDADiskDescriptionWatchVolumeName के teh स्पष्टीकरण को कहां से भरते हैं। – wantro

+0

कुंजी http://developer.apple.com/mac/library/documentation/Darwin/Reference/DiscArbitrationFramework/index.html पर पाई जा सकती है ... ठीक है, आप जानते हैं कि एडीसी वेबसाइट में एक खोज बॉक्स है, दाएं ? क्या आपने वहां निरंतर खोज की थी? मुझे अपने पहले प्रश्न के बारे में सोचने दो। – Yuji

+0

मैंने आपके कोड की प्रतिलिपि बनाई और चिपकाया, और यह मेरी मशीन (10.6.2) पर काम किया। क्या आप अपना कॉलबैक दिनचर्या पोस्ट कर सकते हैं, और आप लौटे हुए ईवेंट फ़्लैग की जांच कैसे कर रहे हैं? – Yuji

संबंधित मुद्दे