2011-12-12 10 views
7

मैं एक अलग ऐप में एक फ़ाइल कैसे भेजूं यह जानकर कि कौन सा यूटीआई ऐप का समर्थन करता है? आइए कहें कि फ़ाइल में कोई फ़ाइल एक्सटेंशन नहीं है, लेकिन मुझे फ़ाइल के यूटीआई को पता है।UIDocumentInteractionController, कोई फ़ाइल एक्सटेंशन नहीं लेकिन यूटीआई

मैं निम्नलिखित की कोशिश की:

// target is a NSURL with the location of the extension less file on the system 
// knownUTI is a NSString containing the UTI of the file 
    UIDocumentInteractionController* dic = [UIDocumentInteractionController interactionControllerWithURL:target]; 
    [dic retain]; 

    dic.delegate = self; 
    dic.UTI = knownUTI; 
    [dic presentOpenInMenuFromRect:CGRectZero inView:superController.view animated:YES] 

यह समर्थित अनुप्रयोग से पता चलता है, तथापि, अगर मैं उसका चयन करें, यह ऐप स्विच नहीं होंगे। प्रतिनिधि

- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application 

लेकिन

- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application 

कभी नहीं कहा जाता है कॉल करता है और आवेदन कभी नहीं स्विचन है।

लक्ष्य अनुप्रयोग निम्नलिखित में अपनी यूटीआई का निर्यात करता है:

<key>CFBundleDocumentTypes</key> 
    <array> 
     <dict> 
      <key>CFBundleTypeIconFiles</key> 
      <array/> 
      <key>CFBundleTypeName</key> 
      <string>Migration DocType</string> 
      <key>CFBundleTypeRol</key> 
      <string>Shell</string> 
      <key>LSHandlerRank</key> 
      <string>Owner</string> 
      <key>LSItemContentTypes</key> 
      <array> 
       <string>com.mycomp.customstring</string> 
      </array> 
     </dict> 
    </array> 

... 

<key>UTExportedTypeDeclarations</key> 
    <array> 
     <dict> 
      <key>UTTypeConformsTo</key> 
      <array> 
       <string>public.data</string> 
      </array> 
      <key>UTTypeDescription</key> 
      <string>My custom UTI</string> 
      <key>UTTypeIdentifier</key> 
      <string>com.mycomp.customstring</string> 
     </dict> 
    </array> 

इस के रूप में काम नहीं किया, मैं भी एक कस्टम एक्सटेंशन जोड़ की कोशिश की। फिर भी, यह इस तरह से काम नहीं करेगा। फ़ाइल में कस्टम एक्सटेंशन जोड़ते समय मैं DocumentInteractionController पर सौंपता हूं और यह काम करता है। हालांकि, अनुप्रयोगों की सूची यूटीआई प्रकार I आपूर्ति के बावजूद एक ही फ़ाइल एक्सटेंशन का समर्थन करने वाले सभी अन्य अनुप्रयोगों को दिखाती है।

मैं 2 अलग अनुप्रयोगों में 2 यूटीआई घोषित कहते हैं:

App1 with UTI1: com.mycomp.a with extension .abc 
App2 with UTI2: com.mycomp.b with extension .abc 

जब DocumentInteractionController करने के लिए फ़ाइल सौंपने, और com.mycomp.a लिए यूटीआई की स्थापना यह भी फ़ाइल को संभालने के लिए सक्षम किया जा रहा एक संभव आवेदन के रूप में App2 दिखाएगा ।

मैं निम्नलिखित तरीके से विस्तार के साथ एक यूटीआई परिभाषित:

<key>UTExportedTypeDeclarations</key> 
    <array> 
     <dict> 
      <key>UTTypeConformsTo</key> 
      <array> 
       <string>public.data</string> 
      </array> 
      <key>UTTypeDescription</key> 
      <string>My UTI Type</string> 
      <key>UTTypeIdentifier</key> 
      <string>com.mycomp.a</string> 
      <key>UTTypeTagSpecification</key> 
      <dict> 
       <key>public.filename-extension</key> 
       <string>abc</string> 
       <key>public.mime-type</key> 
       <string>application/abc</string> 
      </dict> 
     </dict> 
    </array> 

मैं आपकी मदद वास्तव में सराहना करेंगे, मैं एक तरह से अटक कर रहा हूँ। तो, फिर से सवाल: मैं बिना किसी एक्सटेंशन के ज्ञात यूटीआई के साथ एक ऐप में एक फाइल कैसे भेजूं या अन्य फाइलों के समान एक्सटेंशन रखूं, जिनमें से मैं दस्तावेज़ इंटरेक्शन कंट्रोलर में पसंद के रूप में एप्लिकेशन नहीं दिखाना चाहता हूं?

धन्यवाद

उत्तर

2

मुझे इस समस्या का समाधान मिला। हालांकि, मुझे लगता है कि यह बहुत अच्छा नहीं है।

परीक्षण के दौरान मुझे पता चला कि फ़ाइल एक्सटेंशन को छोड़ते समय, UIDocumentInteractionController निर्दिष्ट किए गए UTI के आधार पर एप्लिकेशन दिखाएगा। लक्ष्य एप्लिकेशन पर फ़ाइल भेजते समय कुछ भी नहीं होगा। मैंने निष्कर्ष निकाला कि मुझे अंतिम प्रेषण करने के लिए फ़ाइल एक्सटेंशन की आवश्यकता है।

मेरा दृष्टिकोण लक्ष्य एप्लिकेशन पर फ़ाइल भेजने से पहले URL संपत्ति को संशोधित करना था और इसे एक ही फ़ाइल की आपूर्ति करना था, लेकिन फ़ाइल एक्सटेंशन के साथ लक्ष्य एप्लिकेशन स्वीकार करता है। फिर भी, मेरा आवेदन बस दुर्घटनाग्रस्त हो गया। मैंने इसे इंस्ट्रूमेंट्स के साथ प्रोफाइल किया और पाया कि समस्या UIDocumentInteractionController कुछ प्रॉक्सी ऑब्जेक्ट को ओवरराइज़ करने के कारण हुई थी। मैंने यह भी देखा कि अंतिम ओवरराइज UIDocumentInteractionController(Private) श्रेणी के _invalidate नामक विधि में था जिसे ऑब्जेक्ट जारी किया गया था।

श्रेणियों अन्य श्रेणियों के द्वारा ओवरराइड नहीं किया जा सकता है के रूप में मैं अपने खुद के कार्यान्वयन की जाँच के लिए कि URL एक फाइल एक्सटेंशन युक्त है या नहीं और वे वास्तविक _invalidate विधि करने के लिए कॉल पुनर्निर्देशित या बस कुछ नहीं कर रहा था के साथ श्रेणी विधि धूर्तता का फैसला किया।

निम्नलिखित कोड से पता चलता है कि मैं क्या किया: _invalidateMY साथ

#include <objc/runtime.h> 

@interface UIDocumentInteractionController(InvalidationRedirect) 

-(void)_invalidateMY; 
+(void)load; 
void Swizzle(Class c, SEL orig, SEL newSEL); 
@end 

@implementation UIDocumentInteractionController(InvalidationRedirect) 

void Swizzle(Class c, SEL orig, SEL newSEL) 
{ 
    Method origMethod = class_getInstanceMethod(c, orig); 
    Method newMethod = class_getInstanceMethod(c, newSEL); 
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) 
     class_replaceMethod(c, newSEL, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); 
    else 
     method_exchangeImplementations(origMethod, newMethod); 
} 

-(void)_invalidateMY{ 
    @synchronized(self) { 
     if(![[[[self.URL lastPathComponent] componentsSeparatedByString:@"."] lastObject] isEqualToString:@"extension"]) { 
      [self _invalidateMY]; 
     } 
    } 
} 

+(void)load 
{ 
    Swizzle([UIDocumentInteractionController class], @selector(_invalidate), @selector(_invalidateMY)); 
} 

@end 

इस कोड को आदान-प्रदान मूल _invalidate विधि, _invalidate के लिए हर कॉल में _invalidateMY और इसके विपरीत करार दिया।

निम्न कोड दिखाता है कि कैसे मैं UIDocumentInteractionController संभाल:

// create a file without extension 
    NSString *fileName = @"myFile"; 

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

    NSString *documentsDirectory = [paths objectAtIndex:0]; 

    NSURL* target = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@", documentsDirectory, fileName]]; 

    if([[@"THIS IS JUST A TEST STRING" dataUsingEncoding:NSUTF8StringEncoding] writeToURL:target atomically:NO]) { 
     NSLog(@"file written successfully"); 
    }else { 
     NSLog(@"Error.. file writing failed"); 
    } 

    UIDocumentInteractionController* dic = [UIDocumentInteractionController interactionControllerWithURL:target]; 
    [dic retain]; 
    dic.delegate = self; 


    // set the UTI to the known UTI we want to list applications for 
    dic.UTI = @"com.mycomp.a"; 

    [dic presentOpenInMenuFromRect:CGRectZero inView:superController.view animated:YES]; 

और यह कोड UIDocumentInteractionController के प्रतिनिधि विधि है जो यूआरएल आदान पता चलता है:

- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application 
{ 
    NSFileManager *fileMgr = [NSFileManager defaultManager]; 
    NSError *error; 
    NSURL* newTarget = [NSURL URLWithString:[NSString stringWithFormat:@"%@.extension", controller.URL]]; 
    // rename file to file with extension 
    if (![fileMgr moveItemAtURL:controller.URL toURL:newTarget error:&error] && error) { 
     NSLog(@"Error moving file: %@", [error localizedDescription]); 
    } 
    @synchronized(controller) { 
     //exchange URL with URL+extension 
     controller.URL = newTarget; //<- this results in calling _invalidate 
    } 
    NSLog(@"%@", [NSString stringWithContentsOfURL:controller.URL encoding:NSUTF8StringEncoding error:nil]); 
} 

यह समाधान काम करता है, लेकिन में मेरी राय यह एक गंदे हैक है, एक बेहतर समाधान होना चाहिए।

+0

मुझे एक आसान समाधान मिला। 'WillBeginSendingToAplication:' से कोड को खुले मेनू में सफलतापूर्वक बुलाए जाने के बाद पहले ही निष्पादित किया जा सकता है, इससे विधियों को तेज करने की आवश्यकता समाप्त हो जाती है! – Jan

+2

कृपया इसके लिए कोड प्रदान करें। मैंने नाम संपत्ति सेट करने का प्रयास किया है लेकिन यह तृतीय पक्ष ऐप में प्रतिबिंबित नहीं होता है। – slott

+0

हां, * असली * समाधान का एक विस्तृत लेखन सबसे उपयोगी होगा। – buildsucceeded

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