Anche se sono d'accordo in linea di principio che il modo corretto per gestire questa situazione è quello di rotolare il proprio Popover, in questo caso si tratta di un non-problema per versioni più recenti del sistema operativo. Voglio davvero costruire e mantenere la mia implementazione di popover solo per supportare un sistema operativo che alla fine sarà irrilevante? Se lo desideri, considera alcune delle implementazioni open source gratuite sul web.
Personalmente ho studiato i metodi suggeriti qui e ho trovato il mio utilizzando questa pagina come punto di partenza (grazie!). Funziona per entrambi gli scenari (con o senza una barra di navigazione) ed è un po 'più sicuro a mio parere.
Invece di aggiungere un metodo a UIPopoverController, ho aggiunto una routine al mio UIPopoverBackgroundView per cercare le viste offensive utilizzando una route RELATIVA, piuttosto che ABSOLUTE. In breve, dato che il codice ha un riferimento diretto a UIPopoverBackgroundView (self), può navigare su (superview) e quindi giù (sottoview).
Gli alberi vista simile a questa in entrambi gli scenari:
Con UINavigationBar:
Senza UINavigationBar:
I due punti di vista che ci interessa sono le Viste UILayoutView e UIImage evidenziate in grassetto e sottolineate in ciascun grafico. Possiamo ottenere un riferimento a questi a partire da UIPopoverBackgroundView utilizzando il codice seguente (presuppone ARC). Eseguo questo da layoutSubviews
nella mia implementazione UIPopoverBackgroundView.
// Helper method for traversing child views based solely on class types
UIView* (^__unsafe_unretained __block traverseSubviews)(UIView*, NSArray*) = ^(UIView *root, NSArray* nodeTypes) {
NSString *typeName = [nodeTypes objectAtIndex:0];
for (UIView *subView in root.subviews) {
if ([NSStringFromClass([subView class]) isEqualToString: typeName]) {
if (nodeTypes.count == 1)
return subView;
else
return traverseSubviews(subView, [nodeTypes subarrayWithRange:NSMakeRange(1, nodeTypes.count - 1)]);
}
}
return (UIView*)nil;
};
// Find the subviews of interest, taking into account there could be a navigation bar
UIView *layoutView = traverseSubviews([self superview], @[@"UIView", @"UILayoutContainerView"]);
if (traverseSubviews(layoutView, @[@"UINavigationBar"])) {
layoutView = traverseSubviews(layoutView, @[@"UILayoutContainerView"]);
}
UIView *imageView = traverseSubviews(layoutView, @[@"UIImageView"]);
// Remove the default content appearance
layoutView.layer.cornerRadius = 0;
[imageView removeFromSuperview];
Qui utilizzo un blocco per eseguire l'attraversamento delle sottoview per mantenere il codice conciso. Prende una prospettiva come punto di partenza e una serie di nomi di classi. L'array di nomi di classi è la sequenza di classi vista che mi aspetto dove l'indice 0 è il genitore dell'indice 1 e l'indice 1 è il genitore dell'indice 2, ecc. Restituisce la vista rappresentata dall'ultimo elemento nell'array.
fonte
2013-02-25 13:31:03
La risposta di kajham, per iOS 6 dovrebbe essere la risposta accettata. –