2010-04-13 24 views
8

Ho un pulsante all'interno del contenuto di un UIPopoverController. Questo pulsante esegue un metodo chiamato myAction.ipad - eliminazione di un UIPopoverController

myAction ha la forma

- (void) myAction:(id)sender 

così, myAction riceve l'id del chiamante tasto.

Ora, all'interno di questo metodo vorrei chiudere l'UIPopoverController, ma l'unica cosa che ho è l'ID del pulsante del chiamante. Ricorda che il pulsante si trova all'interno di UIPopoverController.

C'è un modo per scoprire l'ID di UIPopoverController, dato l'ID del pulsante che ho già?

grazie.

risposta

19

Purtroppo no. Almeno, non all'interno delle pratiche standard. Potresti essere in grado di risalire lo stack di risponditori per trovarlo, ma è un hack, è bug, ed è davvero, davvero disordinato.

Se si desidera eliminare un popover premendo un pulsante, è necessario che un posto pertinente mantenga un riferimento al popover. Di solito questo sarebbe il proprietario del popover (non il controller ha mostrato entro il il popover). Quando viene premuto il pulsante, è possibile inviare un messaggio al controller proprietario, che può quindi eliminare il popover.

Si potrebbe essere tentati di avere il controller visualizzato all'interno del popover essere il proprietario del proprio popover, ma la codifica in questo modo è fragile, può diventare disordinata (di nuovo), e può causare loop di conservazione in modo che nessuno dei due rilasciato.

+0

grazie. Cambierò il codice! – SpaceDog

+3

Il secondo paragrafo è estremamente importante in questa risposta. Ricorda, secondo la Guida alla programmazione dell'iPad: "Ricorda però che è tua responsabilità archiviare un riferimento al controller popover in modo da poterlo eliminare." Il sistema non ne fornisce uno per impostazione predefinita. " Quindi, non fare un "rilascio" su di esso (causerà comunque un crash) finché la vista genitore non è entrata nella fase dealloc. (questo è il mio metodo di sicurezza). – Jann

+0

usa solo [self dismissViewControllerAnimated: YES completion: nil]; "Il controller di visualizzazione che presenta è responsabile della rimozione del controller di visualizzazione presentato. Se si chiama questo metodo sul controller di visualizzazione presentato, esso inoltra automaticamente il messaggio al controller di visualizzazione che presenta." –

4

Ho questo funzionamento, e non penso che sia un hack. Ho una app per iPad con vista divisa standard. Ho quindi aggiunto un metodo al mio controller di dettaglio (il proprietario del pop-over) per gestire il licenziamento.

Nella vista divisa standard di architechture, sia i controller di visualizzazione radice che di dettaglio sono disponibili tramite il delegato dell'app. Quindi ho inserito un pulsante all'interno del pop per chiamare un metodo che ottiene il delegato dell'app. Da lì chiamo il metodo sul controller di dettaglio per chiudere il popover.

Questo è il codice per il metodo sul View Controller che viene visualizzato all'interno del popover:

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

    [appDelegate.detailViewController exitDrill]; 
} 

Poi il metodo semplice per chiudere sul dettaglio View Controller:

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

Mi piace la capacità di farlo perché mi dà modo di mostrare a un utente come possono uscire da un pop-over. Questo potrebbe non essere necessario nelle versioni future dell'app; per ora, mentre questo paradigma è ancora nuovo per la piattaforma, preferisco lasciare che gli utenti mostrino uno schermo in un paio di modi diversi per assicurarmi di minimizzare la frustrazione.

5

È possibile accedere al popoverController che presenta accedendo a "popoverController" con KVC.

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

Intelligente, ma nessuna possibilità di essere taggata come "utilizzando API private" e l'app viene rifiutata anche se tecnicamente non utilizza l'API privata? –

+0

Sì @Chintan. È potenzialmente respinto da AppStore se rilevano che il codice utilizza la "API privata" della loro. –

+0

@JasonMing Questa è l'unica cosa che ha funzionato per me e ho trascorso la maggior parte delle 5 ore cercando di trovare una soluzione. Grazie mille ... –

0

Come Ed Marty già scritto

Se si vuole licenziare un popover premendo un pulsante, un posto rilevante dovrebbe tenere un riferimento alla popover

Questo è molto vero ; tuttavia, quando mostra un UIPopoverController, la classe che apre il popovercontroller mantiene già questa risorsa. Quindi, quello che potresti fare è usare questa classe come classe delegata per il tuo controller Popover.

Per fare ciò, è possibile eseguire quanto segue, che utilizzo nel mio codice. In apertura del popover la classe, questo è il mio codice:

- (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]; 
} 

Quindi quello che sto facendo qui è la creazione di un UINavigationController e l'impostazione di un BookingDetailsViewController come rootViewController. Quindi aggiungo anche la classe corrente come delegato a questo BookingDetailsViewController.

La seconda cosa che ho aggiunto è un metodo di licenziamento chiamato dismissPopoverAnimated:animated.

Nel mio BookingDetailsViewController.h ho aggiunto il seguente codice:

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

E nella mia BookingDetailsViewController.m ho aggiunto questo codice:

[...] 

@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"); 
    } 
} 

[...] 

Quello che succede è che quando il pulsante "Chiudi" nella UINavigationController è premuto, viene chiamato il metodo closeView. Questo metodo controlla se il delegato risponde a dismissPopoverAnimated:animated e, in tal caso, lo chiama. Se non risponde a questo metodo mostrerà un messaggio di log e non farà altro (quindi non si bloccherà).

Ho scritto il mio codice usando ARC, quindi non c'è gestione della memoria.

Spero che questo ti abbia aiutato.

Problemi correlati