When previewing files in PDF or other formats, we can share the file or print it through the built-in UIDocumentInteractionController
software . as the picture shows:QLPreviewController
UIActivityViewController
The first line AirDrop
is a shortcut for users to share files between Apple devices after iOS7, which is similar to Bluetooth wireless transfer files on Android.
The second line is a list of Apps identified by the document type association technique.
The third line is a list identified by document association technology Action
, indicating some operations that can be performed on the file, such as copying, printing, saving, etc.
We know that there is a security system under the iOS system -- 沙盒机制
each iOS application is an independent file system, and can only be operated in its own file system, so the iOS system cannot easily access other files like Android. files under the application.
Since we can share files to other apps when previewing files in our own apps, how can we allow other apps to share files to our app?
info.plist registration file type
We need to info.plist
add a new attribute CFBundleDocumentTypes
(actually entered Document type
) in the file, which is an array type attribute, which means that we can register multiple types at the same time. For each element in the array, there are many attributes that can be specified. We can find the detailed attribute list from the official document: Core Foundation Keys ---- CFBundleDocumentTypes . Here are the attributes we commonly use when doing iOS development:
-
CFBundleTypeName
The string type specifies an alias of a certain type, that is, an alias used to refer to the type we specify. Generally, in order to maintain uniqueness, we use UTI to identify it.
-
CFBundleTypeIconFiles
Array type, containing the file name of the specified png icon, specifying an icon representing a certain type, and the icon has a specific size identification:
Device | Sizes |
---|---|
iPad | 64 x 64 pixels, 320 x 320 pixels |
iPhone and iPod touch | 22 x 29 pixels, 44 x 58 pixels (high resolution) |
- LSItemContentTypes
Array type, containing UTI strings, specifying a collection of all file types that our application can recognize
- LSHandlerRank
string type, includingOwner
,Default
,Alternate
,None
four optional values, specifies the priority level for a certain type, andLauncher Service
the order of the displayed App will be arranged according to this priority level. The order of priority from high to low isOwner
,Alternate
,Default
.None
Indicates that this type is not accepted.
We choose Source code
the way to open info.plist
the file and add the following code:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>PDF</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Microsoft Word</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.word.doc</string>
<string>com.microsoft.word.wordml</string>
<string>org.openxmlformats.wordprocessingml.document</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Microsoft Excel</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.excel.xls</string>
<string>org.openxmlformats.spreadsheetml.sheet</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>Microsoft PowerPoint</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.powerpoint.ppt</string>
<string>org.openxmlformats.presentationml.presentation</string>
<string>public.presentation</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Text</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.text</string>
<string>public.plain-text</string>
<string>public.utf8-plain-text</string>
<string>public.utf16-external-plain-text</string>
<string>public.utf16-plain-text</string>
<string>com.apple.traditional-mac-plain-text</string>
<string>public.source-code</string>
<string>public.c-source</string>
<string>public.objective-c-source</string>
<string>public.c-plus-plus-source</string>
<string>public.objective-c-plus-plus-source</string>
<string>public.c-header</string>
<string>public.c-plus-plus-header</string>
<string>com.sun.java-source</string>
<string>public.script</string>
<string>public.shell-script</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Rich Text</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.rtf</string>
<string>com.apple.rtfd</string>
<string>com.apple.flat-rtfd</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>HTML</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.html</string>
<string>public.xhtml</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Web Archive</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.webarchive</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Image</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.image</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>iWork Pages</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.page.pages</string>
<string>com.apple.iwork.pages.pages</string>
<string>com.apple.iwork.pages.template</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>iWork Numbers</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.numbers.numbers</string>
<string>com.apple.iwork.numbers.numbers</string>
<string>com.apple.iwork.numbers.template</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>iWork Keynote</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.keynote.key</string>
<string>com.apple.iwork.keynote.key</string>
<string>com.apple.iwork.keynote.kth</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Audio</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.audio</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Movie</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.movie</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Archive</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.archive</string>
</array>
</dict>
</array>
Add these codes, and your app can support most file types. You can add related types of codes according to your own project needs. My own project only needs to support PDF and word format files. After adding these codes, we choose Property list
to open the info.plist file:
Or info
open Document types
the list on the page:
At this time, it means that we have successfully registered the file types supported by the app. At this time, we are compiling and running, and then go to other apps (QQ I use here) to open the downloaded file. The page that comes out at this time is like this of:
We can see that our App icon has appeared in the list in the second column. At this time, we can click the icon button to share the file to our App.
What to do with shared files
When the icon button is clicked, it will jump to our own application, and this callback method AppDelegate.m
will be used at this time.- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
But the callback is before iOS9 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation
, so we need to make changes for different device versions.
We can perform file processing operations in the callback method, such as uploading files, previewing files, and saving files. When doing file preview, we must jump to the corresponding controller. At this time, we must first obtain the current view controller
//获取当前屏幕显示的viewcontroller
- (UIViewController *)getCurrentVC
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
return currentVC;
}
- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
UIViewController *currentVC;
if ([rootVC presentedViewController]) {
// 视图是被presented出来的
rootVC = [rootVC presentedViewController];
}
if ([rootVC isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
} else if ([rootVC isKindOfClass:[UINavigationController class]]){
// 根视图为UINavigationController
currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
} else {
// 根视图为非导航类
currentVC = rootVC;
}
return currentVC;
}
After getting the controller, we can go back to the callback method to perform the jump work. I still use it UIDocumentInteractionController
for file preview
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation{
// 判断传过来的url是否为文件类型
if ([url.scheme isEqualToString:@"file"]) {
_docVc = [UIDocumentInteractionController interactionControllerWithURL:url];
_docVc.delegate = self;
[_docVc presentPreviewAnimated:YES];
}
}
#else
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
// 判断传过来的url是否为文件类型
if ([url.scheme isEqualToString:@"file"]) {
_docVc = [UIDocumentInteractionController interactionControllerWithURL:url];
_docVc.delegate = self;
[_docVc presentPreviewAnimated:YES];
}
return YES;
}
#endif
#pragma mark -- UIDocumentInteractionControllerDelegate
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
// 返回当前控制器
return [self getCurrentVC];
}