Aunque estoy de acuerdo en principio que la forma correcta de manejar esto es rodar su propia Popover, en este caso se trata de un problema no para versiones más nuevas del sistema operativo. ¿De verdad quiero construir y mantener mi propia implementación de popover solo para soportar un SO que eventualmente será irrelevante? Si realmente lo desea, considere algunas de las implementaciones gratuitas de código abierto en la web.
Personalmente, investigué los métodos sugeridos aquí y surgió el mío usando esta página como punto de partida (¡gracias!). Funciona para ambos escenarios (con o sin una barra de navegación) y es un poco más seguro en mi opinión.
En lugar de agregar un método al UIPopoverController, agregué una rutina a mi UIPopoverBackgroundView para buscar las vistas ofensivas usando una ruta RELATIVA, en lugar de ABSOLUTO. En resumen, dado que el código tiene una referencia directa a UIPopoverBackgroundView (self), puede navegar hacia arriba (superview) y luego hacia abajo (subviews).
La vista árboles parecen esto en ambos escenarios:
Con UINavigationBar:
Sin UINavigationBar:
Los dos puntos de vista que nos interesa son las Vistas UILayoutView y UIImage que están en negrita y subrayadas en cada gráfico. Podemos obtener una referencia a estos a partir de UIPopoverBackgroundView utilizando el siguiente código (supone ARC). Ejecuto esto desde layoutSubviews
en mi implementación 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];
Utilizo un bloque aquí para hacer el recorrido de las subvistas para mantener el código conciso. Toma una vista como punto de partida y una matriz de nombres de clase. La matriz de nombres de clase es la secuencia de clases de vista que espero, donde el índice 0 es el padre del índice 1 y el índice 1 es el padre del índice 2, etc. Devuelve la vista representada por el último elemento de la matriz.
Mira la respuesta de kajham, para iOS 6 debería ser la respuesta aceptada. –