J'ai besoin que mes applications ouvrent des documents à partir des applications Safari et Mail avec cette fonction "Ouvrir dans ..." dans la classe UIDocumentInteractionController
. Comment puis-je accomplir ceci?
Réponses
Trop de publicités?Je sais que c'est extrêmement frustrant pour moi comme un programmeur débutant, ou même en tant que moyennement qualifiés-en un maintenant. Fichier I/O par le biais du Mail et Safari apps est très... intéressant nommé conventions au sein de l'application elle-même. Donc, nous allons obtenir nos mains sales avec un projet Xcode pour iPhone. Ouvrez Xcode (je serai à l'aide de 4.2 pour ce Tutoriel) et sélectionnez le " Single View application de modèle (ou de créer un projet vide, puis ajouter une vue unique avec un .xib).
Dans cette nouvelle application, renommez-la-vue-contrôleur (et associés xib) OfflineReaderViewController
, et puis nous allons entrer dans le code. (Nous allons toucher tous les fichiers, mais le préfixe en-tête et de la main.m, donc être conscient de ce que vous aurez besoin de tout ce qui est devant vous!)
Entrez le AppDelegate en-tête et collez le code suivant:
#import <UIKit/UIKit.h>
@class OfflineReaderViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) OfflineReaderViewController *viewController;
@end
Ensuite, entrez le Délégué .m fichier et collez le code suivant dans textuellement:
#import "AppDelegate.h"
#import "OfflineReaderViewController.h"
@implementation AppDelegate
@synthesize window;
@synthesize viewController;
-(BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
// Make sure url indicates a file (as opposed to, e.g., http://)
if (url != nil && [url isFileURL]) {
// Tell our OfflineReaderViewController to process the URL
[self.viewController handleDocumentOpenURL:url];
}
// Indicate that we have successfully opened the URL
return YES;
}
- (void)dealloc
{
[window release];
[viewController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[OfflineReaderViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
@end
Ce:
-(BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
if (url != nil && [url isFileURL]) {
[self.viewController handleDocumentOpenURL:url];
}
return YES;
}
Singulière la plus importante partie de ce tutoriel. De le décomposer en ses parties respectives: -(BOOL)application:(UIApplication *)application
est notre exemple d'application; openURL:(NSURL *)url
est l'URL qui est envoyé pour nous dire ce qui pour ouvrir, sourceApplication:(NSString *)sourceApplication
, c'est l'application qui a envoyé le lien; annotation:(id)annotation
est une fonction supplémentaire, nous n'aborderons pas.
Maintenant, nous devons disposition de nos xib. Entrez le xib (qui devrait être intitulé "OfflineReaderViewController", mais il n'a pas d'importance avec un xib, à moins que nous appelons initWithNibName:
(dont nous ne ferons pas)), et la faire ressembler à l'image ci-dessous:
Il est TRÈS important que vous allez dans l' UIWebView
s'Attributs et cochez la case "Échelles de Pages afin De les Adapter", car cela nous fait un zoom avant et arrière sur les pages web avec des pincées. Ne vous inquiétez pas sur les connexions pour l'instant, nous allons être de la création de ces sous peu.
Entrez le OfflineReaderViewController
- tête et le coller dans le suivant:
#import <UIKit/UIKit.h>
@interface OfflineReaderViewController : UIViewController
<UIDocumentInteractionControllerDelegate> {
IBOutlet UIWebView *webView;
}
-(void)openDocumentIn;
-(void)handleDocumentOpenURL:(NSURL *)url;
-(void)displayAlert:(NSString *) str;
-(void)loadFileFromDocumentsFolder:(NSString *) filename;
-(void)listFilesFromDocumentsFolder;
- (IBAction) btnDisplayFiles;
@end
Maintenant, la .m:
#import "OfflineReaderViewController.h"
@implementation OfflineReaderViewController
UIDocumentInteractionController *documentController;
-(void)openDocumentIn {
NSString * filePath =
[[NSBundle mainBundle]
pathForResource:@"Minore" ofType:@"pdf"];
documentController =
[UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
documentController.delegate = self;
[documentController retain];
documentController.UTI = @"com.adobe.pdf";
[documentController presentOpenInMenuFromRect:CGRectZero
inView:self.view
animated:YES];
}
-(void)documentInteractionController:(UIDocumentInteractionController *)controller
willBeginSendingToApplication:(NSString *)application {
}
-(void)documentInteractionController:(UIDocumentInteractionController *)controller
didEndSendingToApplication:(NSString *)application {
}
-(void)documentInteractionControllerDidDismissOpenInMenu:
(UIDocumentInteractionController *)controller {
}
-(void) displayAlert:(NSString *) str {
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:@"Alert"
message:str
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
}
- (void)handleDocumentOpenURL:(NSURL *)url {
[self displayAlert:[url absoluteString]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[webView setUserInteractionEnabled:YES];
[webView loadRequest:requestObj];
}
-(void)loadFileFromDocumentsFolder:(NSString *) filename {
//---get the path of the Documents folder---
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory
stringByAppendingPathComponent:filename];
NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
[self handleDocumentOpenURL:fileUrl];
}
-(void)listFilesFromDocumentsFolder {
//---get the path of the Documents folder---
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList =
[manager contentsOfDirectoryAtPath:documentsDirectory error:nil];
NSMutableString *filesStr =
[NSMutableString stringWithString:@"Files in Documents folder \n"];
for (NSString *s in fileList){
[filesStr appendFormat:@"%@ \n", s];
}
[self displayAlert:filesStr];
[self loadFileFromDocumentsFolder:@"0470918020.pdf"];
}
- (IBAction) btnDisplayFiles {
[self listFilesFromDocumentsFolder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[self openDocumentIn];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
@end
Ceux d'entre vous qui sont activement regarder et pas une simple copie de tout je vous le dis (je plaisante) sachez que cette ligne: [[NSBundle mainBundle] pathForResource:@"Minore" ofType:@"pdf"];
va nous donner un SIGABRT parce que, eh bien, le fichier n'existe pas! Alors, faites-le glisser dans générique PDF que vous avez tiré à partir de la mesure (je recommande ici parce que qui ne passent leur temps libre à la lecture des quantités massives de la documentation?), ensuite copie de son titre et de le coller dans avec le suffixe (.pdf) supprimé; l' ofType:@"pdf"
partie prend en charge pour nous. La ligne devrait ressembler à ceci lorsque vous avez terminé avec elle: [[NSBundle mainBundle] pathForResource:@"//file name//" ofType:@"pdf"];
Maintenant, retournez dans le xib et d'accrocher ces IBOutlets
! Pour tout dire, voici ce que votre "propriétaire du Fichier" onglet devrait ressembler à:
Il semble que nous sommes en fait...mais attendez! Nous n'avons rien fait pour obtenir une "Ouvrir Dans..." du menu en haut et en cours d'exécution! Eh bien, il s'avère qu'il y a de curage autour de dans la .fichier plist nécessaire. Ouvrir l'application .plist (rapide avec un clic droit, puis sélectionnez Ouvrir > Code Source) et collez-y le texte suivant:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFiles</key>
<array/>
<key>CFBundleIdentifier</key>
<string>CodaFi.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIFileSharingEnabled</key>
<true/>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>PDF Document</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
</dict>
</array>
</dict>
</plist>
[Remarque: soyez prudent autour de déblayage dans le code source de tout plist, si vous ne savez pas ce que vous faites, vous pourriez obtenir le redouté "Ce fichier a été corrompu" erreur de Xcode]
Si l'on devait faire un clic droit et sélectionnez Ouvrir > Liste Propriété, il devrait ressembler à ceci:
Il y a un autre domaine TRÈS important dans qu'il s'appelle 'Application prend en charge le partage de fichiers iTunes'. Qui doit être défini sur "OUI", ou que votre application s'affiche pas dans iTunes que de soutenir le partage de fichiers.
Les "Types de documents" champ spécifie les types de documents sur notre exemple peut ouvrir. Étendre la flèche pour trouver son rôle et UTI. Ce sont des identificateurs uniques (Unique Type Identificateur; semble évident que cet acronyme signifie maintenant, n'est-ce pas?) que chaque type de fichier. Les infections urinaires sont ce que laisser le finder remplacer un document générique de l'image avec un bel localisée image du type de fichier (ne me croyez pas, renommer une importance extension de fichier .ouhbasdvluhb et essayer d'obtenir une belle image!) Si j'ai voulu ouvrir mon propre format personnalisé (disons un .le fichier de code), alors je voudrais mettre quelque chose comme com.CodaFi.code
(reverse DNS notation pour ceux qui n'ont aucune idée) dans l'UTI domaine et Type de Document Nom serait "CodaFi Document". Gestionnaire de Rang et le Rôle doit être simple comme notre gestionnaire de rang est alternatif (car nous ne possédons pas le fichier) et c'est notre rôle de spectateur (car nous n'avons pas besoin de quelque chose de plus important. Notre exemple est simplement un spectateur et non pas un éditeur, alors nous le laisserons comme tel.
Pour référence future, UTI ont de système officiel-a déclaré schémas de nommage quand ils viennent de respecté les sources (Oracle, Microsoft, même Apple lui-même) qui peut être trouvé dans l' Uniforme de l'Identificateur de Type de Guide de Référence, mais sont répertoriés ici de pédantisme.
Maintenant, passons à l'exécution " er! Le code devrait compiler sans erreurs, en supposant que vous avez copié mot à mot et a obtenu ces sacrément xib raccordements à droite. Maintenant, lors du premier lancement de votre application, vous devriez être présenté avec l'option d'ouvrir un document dans iBooks. Désélectionner, de la vraie chair de code est l'ouverture d'autres documents! Lancez Safari et de recherche pour n'importe quel fichier PDF en Safari peut QuickLook ou ouvert. Puis dans le "Ouvrir dans..." dans le menu, notre application se présente! Cliquez sur elle. Vous obtiendrez le petit switcheroo animation et une alerte viendra avec l'emplacement du fichier. Lorsque vous rejeter, l' UIWebView
va avoir chargé le fichier PDF. L'application de Messagerie a les mêmes fonctionnalités avec des pièces jointes. Vous pouvez aussi appeler ces fichiers Pdf jusqu'à votre application.
Ça y est, c'est fait. Profitez et amusez-vous!
Il y a une superbe réponse à cette question ici. J'ai copié certains de la réponse ci-dessous pour plus de clarté, mais vous devez vous référer à cette question pour la réponse complète.
Type de fichier de la manipulation est de nouveau avec l'iPhone OS 3.2, et est différent de celui déjà existant personnalisé schémas d'URL. Vous pouvez enregistrer votre application pour gérer des types de documents particuliers, et toute application qui utilise un contrôleur de document peut confier le traitement de ces documents à votre propre application.
Pour vous inscrire soutien, vous aurez besoin d'avoir quelque chose comme ce qui suit dans votre Info.plist:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array>
<string>Document-molecules-320.png</string>
<string>Document-molecules-64.png</string>
</array>
<key>CFBundleTypeName</key>
<string>Molecules Structure File</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.sunsetlakesoftware.molecules.pdb</string>
<string>org.gnu.gnu-zip-archive</string>
</array>
</dict>
</array>
L'une des infections urinaires utilisé dans l'exemple ci-dessus a été définie par le système, mais l'autre était spécifique à une application UTI. L'application spécifique de l'UTI devra être exporté afin que d'autres applications sur le système peut être mis au courant de cela. Pour ce faire, vous ajoutez un article à votre Info.plist comme suit:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.plain-text</string>
<string>public.text</string>
</array>
<key>UTTypeDescription</key>
<string>Molecules Structure File</string>
<key>UTTypeIdentifier</key>
<string>com.sunsetlakesoftware.molecules.pdb</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>pdb</string>
<key>public.mime-type</key>
<string>chemical/x-pdb</string>
</dict>
</dict>
</array>
Cet exemple en particulier, les exportations de l' com.sunsetlakesoftware.molecules.pdb
UTI avec le .apb extension de fichier, correspondant au type MIME chemical/x-pdb
.
Avec ce lieu, votre application sera en mesure de gérer les documents attachés aux e-mails ou d'autres applications sur le système. Dans Mail, vous pouvez appuyez et maintenez pour afficher une liste des applications qui peuvent ouvrir un attachement particulier.
Lorsque la pièce jointe est ouverte, votre demande sera lancé et vous aurez besoin pour gérer le traitement de ce fichier dans votre dossier -application:didFinishLaunchingWithOptions:
le délégué d'application de la méthode. Il semble que les fichiers chargés de cette manière à partir de la Messagerie sont copiés dans votre demande les Documents du répertoire dans un sous-répertoire correspondant à ce que la boîte e-mail qu'ils sont arrivés.