2010-04-13 8 views
8

Ich habe eine Schaltfläche innerhalb des Inhalts eines UIPopoverController. Diese Schaltfläche führt eine Methode namens myAction aus.ipad - einen UIPopoverController verwerfen

MyAction hat die Form

- (void) myAction:(id)sender 

so, MyAction die ID des Anrufers Taste empfängt.

Nun möchte ich innerhalb dieser Methode den UIPopoverController ablehnen, aber das einzige, was ich habe, ist die ID der Anrufer-Taste. Denken Sie daran, dass sich die Schaltfläche innerhalb des UIPopoverControllers befindet.

Gibt es eine Möglichkeit, die ID des UIPopoverController zu ermitteln, da die Schaltfläche ID bereits vorhanden ist?

danke.

Antwort

19

Leider nicht. Zumindest nicht innerhalb der Standard-Praktiken. Sie können vielleicht den Responder-Stack aufsuchen, um ihn zu finden, aber es ist ein Hack, es ist fehlerhaft, und es ist wirklich, wirklich chaotisch.

Wenn Sie ein Popover durch Drücken einer Schaltfläche ablehnen möchten, sollten einige relevante Orte einen Verweis auf das Popover behalten. Normalerweise wäre das der Besitzer des Popover (nicht der Controller zeigte innerhalb der Popover). Wenn die Taste gedrückt wird, kann eine Nachricht an den Eigentümer-Controller gesendet werden, der das Popover dann abweisen kann.

Sie könnten versucht sein, den Controller im Popover angezeigt zu haben, der Besitzer des eigenen Popover ist, aber Codierung auf diese Weise ist brüchig, kann unordentlich (wieder), und kann in Retain-Schleifen führen, so dass keiner jemals bekommt freigegeben.

+0

danke. Ich werde den Code ändern! – SpaceDog

+3

Der zweite Absatz ist in dieser Antwort extrem wichtig. Denken Sie daran, gemäß dem iPad-Programmierhandbuch: "Beachten Sie jedoch, dass es in Ihrer Verantwortung liegt, einen Verweis auf den Popover-Controller zu speichern, damit Sie ihn ablehnen können. Das System stellt standardmäßig kein solches bereit." Machen Sie also kein "release]" (wird trotzdem einen Absturz verursachen), bis die übergeordnete Ansicht in die Dealloc-Phase eingetreten ist. (das ist meine Sicherheitsmethode). – Jann

+0

verwenden Sie einfach [self entlassenViewControllerAnimated: YES completion: nil]; "Der präsentierende View-Controller ist dafür zuständig, den von ihm präsentierten View-Controller zu verwerfen. Wenn Sie diese Methode auf dem vorgestellten View-Controller selbst aufrufen, leitet er die Nachricht automatisch an den präsentierenden View-Controller weiter." –

4

Ich habe das funktioniert, und ich denke nicht, dass es ein Hack ist. Ich habe eine Standard-Split-View-iPad-App. Ich habe dann eine Methode auf meinem Detail-Controller (der Besitzer des Pop-over) hinzugefügt, um die Entlassung zu behandeln.

Auf der Standard-Split-Ansicht architechture sind sowohl die Stamm- als auch die Detailansicht-Controller über den App-Delegaten verfügbar. Also habe ich einen Knopfklick innerhalb des Pop-Over gebunden, um eine Methode aufzurufen, die den App-Delegaten ruft. Von dort aus rufe ich die Methode auf dem Detail-Controller auf, um den Popover zu verwerfen.

Dies ist der Code für die Methode auf den View-Controller, die innerhalb des popover angezeigt:

- (void) exitView: (id)sender { 
    MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate]; 

    [appDelegate.detailViewController exitDrill]; 
} 

Dann ist die einfache Methode auf den Detailansicht-Controller zu entlassen:

- (void) exitDrill { 
    if(dtController != nil){ 
     [dtController dismissPopoverAnimated: YES]; 
     [dtController release]; 
    } 
} 

Ich mag die Möglichkeit, dies zu tun, weil es mir eine Möglichkeit gibt, einem Benutzer zu zeigen, wie er einen Popover beenden kann. Dies ist möglicherweise in zukünftigen Versionen der App nicht erforderlich. Im Moment, während dieses Paradigma noch neu für die Plattform ist, möchte ich es den Benutzern erlauben, eine Anzeige in einem Paar auf verschiedene Arten zu platzieren, um sicherzustellen, dass ich Frustration minimieren kann.

5

Sie können auf den presenting popoverController zugreifen, indem Sie mit KVC auf "popoverController" zugreifen.

[[self valueForKey:@"popoverController"] dismissPopoverAnimated:YES] 
+1

Smart, aber jede Chance, dass dies als "private API verwenden" getaggt wird und App abgelehnt wird, obwohl es technisch keine private API verwendet? –

+0

Ja @ Chintin. Es wird möglicherweise von AppStore abgelehnt, wenn Sie feststellen, dass Ihr Code die "private API" verwendet. –

+0

@JasonMing Dies ist das einzige, was für mich funktioniert hat, und ich habe den besten Teil von 5 Stunden damit verbracht, eine Lösung zu finden. Vielen Dank ... –

0

Wie Ed Marty schrieb bereits

Wenn Sie eine popover entlassen per Knopfdruck, einen Ort relevant einen Verweis auf die popover halten sollte

Das ist sehr wahr ; Wenn jedoch ein UIPopoverController angezeigt wird, behält die Klasse, die den Popovercontroller öffnet, diese Ressource bereits bei. Sie könnten also diese Klasse als Delegate-Klasse für Ihren Popover-Controller verwenden.

Um dies zu tun, könnten Sie Folgendes tun, die ich in meinem Code verwende. In der Klasse der popover öffnen, dies ist mein Code:

- (void)showInformationForView:(Booking*)booking frame:(CGRect)rect 
{ 
    BookingDetailsViewController *bookingView = [[BookingDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped booking:booking]; 
    [bookingView setDelegate:self]; 

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:bookingView]; 

    self.popController = [[UIPopoverController alloc] initWithContentViewController:navController]; 
    [self.popController setDelegate:self]; 
    [self.popController setPopoverContentSize:CGSizeMake(320, 320)]; 

    rect.size.width = 0; 

    [self.popController presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES]; 
} 

- (void)dismissPopoverAnimated:(BOOL)animated 
{ 
    [self.popController dismissPopoverAnimated:animated]; 
} 

Also, was ich hier mache ein UINavigationController und Einstellen eines BookingDetailsViewController als rootViewController schafft. Dann füge ich auch die aktuelle Klasse als Stellvertreter zu dieser BookingDetailsViewController hinzu.

Die zweite Sache, die ich hinzugefügt habe, ist eine Entlassungsmethode namens dismissPopoverAnimated:animated.

In meinem BookingDetailsViewController.h Ich habe den folgenden Code:

[...] 
@property (nonatomic, strong) id delegate; 
[...] 

Und in meinem BookingDetailsViewController.m ich diesen Code hinzugefügt:

[...] 

@synthesize delegate = _delegate; 

- (void)viewDidLoad 

{ 
    UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeView)]; 
    [self.navigationItem setRightBarButtonItem:closeButton]; 

    [super viewDidLoad]; 
} 

- (void)closeView 
{ 
    if ([self.delegate respondsToSelector:@selector(dismissPopoverAnimated:)]) { 
     [self.delegate dismissPopoverAnimated:YES]; 
    } 
    else { 
     NSLog(@"Cannot close the view, nu such dismiss method"); 
    } 
} 

[...] 

Was passiert, ist, dass, wenn die Schaltfläche "Schließen" in der UINavigationController ist gedrückt, wird die Methode closeView aufgerufen. Diese Methode überprüft, ob der Delegat auf dismissPopoverAnimated:animated reagiert, und wenn ja, ruft er es auf. Wenn es nicht auf diese Methode reagiert, zeigt es eine Protokollmeldung an und tut nichts mehr (so wird es nicht abstürzen).

Ich habe meinen Code mit ARC geschrieben, daher gibt es keine Speicherverwaltung.

Ich hoffe, das hat dir geholfen.

Verwandte Themen