Хотя я согласен в принципе, что правильный способ справиться с этим - запустить собственный Popover, в этом случае это не проблема для более новых версий ОС.Действительно ли я хочу создавать и поддерживать свою собственную реализацию popover только для поддержки ОС, которая в конечном итоге не будет иметь значения?Если вы действительно хотите, рассмотрите некоторые из бесплатных реализаций с открытым исходным кодом в сети.
Лично я исследовал предложенные здесь методы и придумал свой собственный, используя эту страницу в качестве отправной точки (спасибо!).Он работает для обоих сценариев (с панелью навигации или без нее) и, на мой взгляд, немного безопаснее.
Вместо добавления метода в UIPopoverController, я добавил подпрограмму в свой UIPopoverBackgroundView для поиска оскорбительных представлений.используя ОТНОСИТЕЛЬНЫЙ маршрут, а не АБСОЛЮТНЫЙ.Короче говоря, поскольку код имеет прямую ссылку на UIPopoverBackgroundView (self), он может перемещаться вверх (суперпредставление) и затем вниз (подпредставления).
Деревья представлений выглядят так в обоих сценариях:
С UINavigationBar:
Без UINavigationBar:
Два вида, которые нас интересуют, - это представления UILayoutView и UIImage, которые выделены жирным шрифтом и подчеркнуты на каждом графике.Мы можем получить ссылку на них, начиная с UIPopoverBackgroundView, используя код ниже (предполагает ARC).Я выполняю это из layoutSubviews
в моей реализации 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];
Я использую здесь блок для обхода подпредставлений, чтобы сохранить код кратким.Это берет представление как отправную точку и массив имен класса.Массив имен классов - это ожидаемая последовательность классов представлений, где индекс 0 является родительским для индекса 1, а индекс 1 является родительским для индекса 2 и т. Д. Он возвращает представление, представленное последним элементом в массиве.