15 Stimmen

Seltsames Problem mit UIDocumentInteractionController

Ich weiß nicht, was mit diesem Code falsch ist, aber jedes Mal, wenn ich die App ausführe, stürzt sie ab, nachdem das Menü angezeigt wurde.

NSString * path = [[NSBundle mainBundle] pathForResource:@"tung" ofType:@"doc"];

UIDocumentInteractionController *docController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];

docController.delegate = self;

//[docController presentPreviewAnimated:YES];

CGRect rect = CGRectMake(0, 0, 300, 300);
[docController presentOptionsMenuFromRect:rect inView:self.view animated:YES];

Den Fehler, den ich erhalten habe:

*** Beenden der App aufgrund einer unbehandelten Ausnahme 'NSGenericException', Grund: '-[UIPopoverController dealloc] erreicht, während das Popover noch sichtbar ist.'

Was sollte ich jetzt tun?

0 Stimmen

Auf welcher Zeile wird der Fehler geworfen?

0 Stimmen

Auf dieser Linie: [docController presentOptionsMenuFromRect:rect inView:self.view animated:YES];

24voto

Christian Fries Punkte 14995

Um ein Dokument über einen "wegwerfbaren" UIDocumentInteractionController zu betrachten, sollten Sie es nach interactionControllerWithURL behalten und es in der UIDocumentInteractionControllerDelegate-Methode documentInteractionControllerDidDismissOptionsMenu freigeben. Wie von David Liu bemerkt, wird ein Freigeben zu einem Absturz führen. Aber Autoreleasing funktioniert. Ich habe überprüft, dass dealloc tatsächlich aufgerufen wird.

Der folgende Code sollte funktionieren:

- (void)previewDocumentWithURL:(NSURL*)url
{
    UIDocumentInteractionController* Vorschau = [UIDocumentInteractionController interactionControllerWithURL:url];
    preview.delegate = self;
    [Vorschau presentPreviewAnimated:YES];
    [Vorschau retain];
}
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller
{
    [controller autorelease];
}

2 Stimmen

Für alle von Ihnen, die das "Öffnen in..."-Dialogfeld verwenden, verwenden Sie die Delegatenmethode documentInteractionControllerDidDismissOpenInMenu:

8voto

David Liu Punkte 9157

Es handelt sich im Grunde um das alte Speicherverwaltungsproblem.

[UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]] gibt ein automatisch freigegebenes Objekt zurück, sodass es bald nach Abschluss Ihres Codeblocks automatisch freigegeben wird. Ich vermute, dass dies anders ist als presentModalViewController, das eine Kopie für Sie behält, aber das ist eine Nebensache.

Grundsätzlich müssen Sie es behalten, bevor Ihr Codeblock endet. Der nervigere Teil ist, im Auge zu behalten, was der docController tut, damit Sie keinen Speicher verlieren. Sie müssen das Ergebnis von
[docController presentOptionsMenuFromRect:rect inView:self.view animated:YES]; überprüfen.

Wenn es NO zurückgibt, bedeutet dies, dass das Menü nie angezeigt wurde, und Sie sollten es sofort freigeben (wenn Sie bereits das Retain durchgeführt haben).

Wenn es jedoch YES zurückgibt, müssen Sie die Delegate-Methoden für docController implementieren und es freigeben, wenn das Menü geschlossen wird (in diesem Fall wäre das, wenn:
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller aufgerufen wird.

BEARBEITEN: Ich möchte hier eine Korrektur vornehmen:

Die vorherige Antwort wird abstürzen, wenn das Popup-Menü geschlossen wird. Im Grunde gibt es wirklich keine gute Möglichkeit, einen wegwerfbaren DocController zu erstellen. Stattdessen denke ich, es ist am besten, einfach einen für jede Datei, die Sie im ViewController benötigen, zu erstellen, und deallokieren, wenn Sie komplett fertig sind. Andernfalls werden Sie in eine Vielzahl von möglichen Fällen geraten, in denen der DocController zu früh freigegeben wird und abstürzt.

2voto

Anthony Mattox Punkte 6938

Dieser Fehler wird (wie bereits von anderen erwähnt) durch die Freigabe des UIDocumentInteractionController verursacht, während der angezeigte Ansichtscontroller weiterhin darauf angewiesen ist. Das ist ein einfacher Fehler und das Erstellen eines starken Verweises auf diesen Ansichtscontroller, in einer umgebungsbedingten Referenzzählumgebung, wird das Problem lösen. Das Objekt kann freigegeben werden, wenn es nicht mehr benötigt wird, indem auf Delegatenmethoden reagiert wird.

Der Grund, warum dies verwirrend ist, liegt darin, dass einige andere Tools in Cocoa, die ähnlich aussehen, nicht auf die gleiche Weise beibehalten werden müssen. Beispielsweise können UIImagePickerController oder UIActivityViewController ohne Probleme innerhalb einer Methode erstellt und angezeigt werden.

Der Unterschied zwischen diesen anderen Beispielen und UIDocumentInteractionController besteht darin, dass die anderen Komponenten alle Unterklassen von UIViewController sind. Wenn sie auf einen Navigationsstapel gepusht oder angezeigt werden, werden sie vom Navigationsstapel oder vom präsentierenden Ansichtscontroller beibehalten. Wenn sie entlassen werden, wird diese Referenz entfernt und sie werden freigegeben. UIDocumentInteractionController ist kein UIViewController. Stattdessen bietet er Ansichtscontroller, die die entsprechende Benutzeroberfläche anzeigen können, aber wichtig ist, dass sie (aus gutem Grund, da es einen Retain-Zyklus verursachen würde) den Dokumentinteraktionscontroller nicht beibehalten. Aus diesem Grund muss jeder, der den Dokumentcontroller erstellt, auch einen starken Verweis darauf aufrechterhalten, solange er von der angezeigten Benutzeroberfläche benötigt wird.


Dieses Beispiel ist im Wesentlichen dasselbe wie die akzeptierte Antwort, aber im ARC-freundlichen Stil zur Beibehaltung eines Objekts.

@interface MYViewController : UIViewController 

@property (nonatomic, strong) UIDocumentInteractionController *documentInteractionController;

@end

@implementation MYViewController

- (void)presentDocumentWithURL:(NSURL*)url {
    self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:url];
    self.documentInteractionController.delegate = self;
    [self.documentInteractionController presentPreviewAnimated:YES];
}

- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller {
    self.documentInteractionController = nil;
}

@end

1voto

Mikel Sanchez Punkte 2790

SWIFT 3

Controller Variable:

var documentIteratorController: UIDocumentInteractionController?

Method aufrufen:

documentIteratorController = UIDocumentInteractionController(url: reportURL)
documentIteratorController?.delegate = self
documentIteratorController?.presentOptionsMenu(from: self.printButton.frame, in: self.view, animated: true)

0voto

JulianB Punkte 1676

Mit Christians Technik...

Wenn Sie sich entscheiden, verschiedene PDFs von verschiedenen Schaltflächen in der Ansicht zu starten anstelle der Navigationsleiste, verwenden Sie nicht:

[controller autorelease];

Weil es den Controller entfernen wird, so dass weitere Instanzen nach der ersten Verwendung nicht mehr funktionieren.

Aber wenn Sie es verwenden, möchten Sie vielleicht sagen

[self.controller autorelease];

0 Stimmen

Meine Delegatenmethoden werden nicht aufgerufen, wenn ich auf "Mail" im Dokument-Interaktionscontroller drücke. Können Sie mir bitte helfen?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X