14

Ich bin etwas unklar in Bezug auf die Objektbesitzmuster für die folgenden Instanzen erforderlich. Wenn mein UIViewController einen Popover-Controller, ein Action-Sheet oder einen anderen View-Controller als modal darstellt, muss ich mich an einen zurückbehaltenen Verweis auf diesen Kind-Controller halten, bis er beendet wird?Muster für UIPopoverController-, UIActionSheet- und Modal View-Controller beibehalten/freigeben?

Mit anderen Worten, führen die folgenden Codezeilen die Eigentumsrechte effektiv "übertragen" oder nicht?

[aPopoverController presentPopoverFromBarButtonItem:someButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO]; 

[anActionSheet showFromBarButtonItem:someButtonItem animated:NO]; 

[aViewController presentModalViewController:someOtherViewController animated:YES]; 

Kann mir jemand auf explizite Dokumentation zu diesem Thema hinweisen?

Antwort

26

UIPopoverViewController hat eine geringfügig andere Speicherverwaltung/Besitz. Präsentieren ein Popover speichert den Speicher nicht, sodass Sie den Besitz des popviewcontrollers nicht auf das präsentierende Objekt übertragen können.

Speicherverlust zu vermeiden, müssen Sie die UIPopoverControllerDelegate nehmen und das DidDismissPopOver Verfahren wie folgt zu implementieren:

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { 
    [popoverController release]; 
} 

Auf diese Weise können Sie sicher alloc und popover präsentieren:

-(void)showSearch:(id)sender { 
    SearchViewController *searchVC = [[SearchViewController alloc] init]; 
    UIPopoverController *popVC = [[UIPopoverController alloc] initWithContentViewController:searchVC]; 
    popVC.delegate = self; 
    [popVC setPopoverContentSize:CGSizeMake(320, 100)]; 
    [popVC presentPopoverFromRect:CGRectMake(200, 200, 320, 100) inView:self.view permittedArrowDirections:0 animated:YES]; 
    [searchVC release]; 
} 
+1

Vorsicht, SearchVC ist undicht, wenn Sie es auf diese Weise tun. Fügen Sie eine Autorelease hinzu. – steipete

+0

Ja, searchVC ist durchgesickert. Anstelle einer Autorelease wird auch eine einfache Version funktionieren. Fügen Sie diese zur letzten Zeile hinzu: '[searchVC release];' –

+1

Als Dokumentation für 'popoverControllerDidDismissPopover:' sagt: _ "Der Popover-Controller ruft diese Methode nicht als Reaktion auf programmatische Aufrufe an die Methode displacePopoverAnimated: Wenn Sie das Popover programmatisch ablehnen, sollten Sie alle Bereinigungsaktionen sofort nach dem Aufruf der Methode "displacePopoverAnimated:" ausführen. "_. Also, wenn Sie 'disposePopoverAnimated:' verwenden, müssen Sie auch Release danach aufrufen, sonst erhalten Sie ein Leck. – ivanzoid

1

Die Anzeige eines Modal View-Controllers behält den UIViewController bei. Dies ist aus den Dokumenten nicht ersichtlich. Allerdings habe ich getestet es mit dem folgenden Code ...

NSLog(@"BEFORE %d", [self.setupViewController retainCount]); 
[self.navigationController presentModalViewController:self.setupViewController animated:YES]; 
NSLog(@"AFTER %d", [self.setupViewController retainCount]); 

Die self.setupViewController bereits lokal beibehalten wird, sondern stellt es Ausgabe wie folgt vor:

2010-05-19 10:07:36.687 LocateMe[27716:207] BEFORE 1 
2010-05-19 10:07:36.762 LocateMe[27716:207] AFTER 3 

So wird es wahrscheinlich in der festgehalten wird lokale modalViewController -Eigenschaft, sowie in der View-Hierarchie. Die Entlassung wird diese ausgleichen.

So unter dem Strich ist, behalten Sie es, wenn Sie es direkt steuern möchten, aber Sie müssen nicht.

EDIT - Nur um klar zu sein, das korrekte Muster ist immer ein Objekt zu behalten, wenn Sie sich als seinen Delegaten festlegen. Das liegt daran, dass Sie den Delegaten aus Sicherheitsgründen auf Null setzen sollten. In der Praxis wird ein Modal-Controller jedoch immer vor dem Dealloc gelöscht, also ist das kein Problem. Sie werden feststellen, dass Apple diese Regel auch in [UIView setAnimationDelegate:] bricht, wodurch der von Ihnen festgelegte Delegat tatsächlich beibehalten wird.

+0

würde ich fügen Sie auch hinzu, dass ein großer Teil von Apples Beispielcode einen UIViewController initialisiert, modal präsentiert und dann freigibt. Sehen Sie sich das AddMusic-Beispiel an. – DougW

+0

Gilt das auch für Popovers und Action-Sheets? –

+0

Ja, Sie können UIAlertView auslösen und dann freigeben. Oder Sie können es behalten, wenn Sie etwas tun wollen. So oder so ist es in Ordnung, stellen Sie sicher, dass Sie Ihre Retain/Releases ausgleichen. – DougW