开发环境
Xcode 8
iOS 10
及
Xcode 7.3
iOS9.3
问题
最近有个朋友问我,在适配iOS10的时候,导航的图片不显示了,使用的是系统导航,怎么调整都不显示.
在Xcode7.3,iOS9.3显示如下:
导航中间位置有一个LOGO视图(当然不是这个条形码),而在Xcode8-iOS10上,这个视图不显示了,如下:
我看了他添加视图的代码,如下:
-(void)setNavigationBarBackgroundView:(UIView *)backgroundView
{
NSArray * subs =[self.navigationBar subviews];
UIView * bgview=nil;
for (UIView * v in subs)
{
NSString * classname = NSStringFromClass([v class]);
if ([classname isEqualToString:@"_UINavigationBarBackground"] || [classname isEqualToString:@"UINavigationBarBackground"])
{
bgview=v;
break;
}
}
if (bgview!=nil)
{
int systemVersion =[[UIDevice currentDevice].systemVersion intValue];
UIView * container=[bgview viewWithTag:20001];
if (!container)
{
CGRect r;
if (systemVersion>=7)
{
r=CGRectMake(0, 0, bgview.frame.size.width, 64);
}else{
r=CGRectMake(0, 0, bgview.frame.size.width, 44);
}
container = [[UIView alloc] initWithFrame:r];
[container setBackgroundColor:[UIColor whiteColor]];
[container setTag:20001];
[bgview addSubview:container];
[container release];
}
[bgview setUserInteractionEnabled:YES];
UIView * v=[container viewWithTag:20000];
if ([v isEqual:backgroundView])
{
return;
}
if (v)
{
[v removeFromSuperview];
}
float h=container.frame.size.height;
if (![backgroundView isKindOfClass:[UIImageView class]])
{
h=44;
}
CGRect rect=backgroundView.frame;
rect.origin.x=0;
rect.origin.y=container.frame.size.height-h;
rect.size.width=bgview.frame.size.width;
rect.size.height=h;
[backgroundView setFrame:rect];
[backgroundView setTag:20000];
[container addSubview:backgroundView];
}
}
是不是看到了个不和谐的词** release** ,好吧,这是个最低要适配到6.0的古董级的项目了....
排查问题
当时看了他的导航视图,我的第一反应是,为什么不自定义个呢?岂不是要省事很多?好吧,系统的有问题,也是需要解决的,原谅我自定义的导航用多了...
我第一个想到的是,这个bgView是不是存在的,所以打个断点后发现,这个bgView是nil,所以我重新打印了导航视图的子视图:
(
"<_UIBarBackground: 0x7f86cdd0b4e0; frame = (0 0; 320 44); userInteractionEnabled = NO; layer = <CALayer: 0x6000000273c0>>",
"<_UINavigationBarBackIndicatorView: 0x7f86cdc0d6c0; frame = (0 11.5; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x60800002a660>>"
)
发现其背景视图名称变了,暗自高兴,这么容易就找到了,欢欢喜喜的修改了如下代码:
if ([classname isEqualToString:@"_UINavigationBarBackground"] || [classname isEqualToString:@"UINavigationBarBackground"])
// 将遍历子视图时的判断条件更改为
if ([classname isEqualToString:@"_UINavigationBarBackground"] || [classname isEqualToString:@"UINavigationBarBackground"]||[classname isEqualToString:@"_UIBarBackground"])
运行,结果却....还是不显示!!!
再看断点处的bgView,确实也拿到了这个背景view,那是怎么回事呢?
然后,使用可视化视图调试Debug View Hierarchy看了下视图的层次关系:
在Xcode7.3-iOS9.3如下图:
导航条的视图布局如下:
而在Xcode8-iOS10则变成这样了:
而导航条的布局为:
发现,添加的视图是存在的,但是为什么不显示呢?
仔细观察两个视图的区别会发现,在Xcode8上,添加的视图上面还覆盖了一个视图UIVisualEffectView,而在Xcode7.3上这个模糊视图是不存在的,其实仔细观察未显示图片的导航条也会发现,隐隐约约能够看到一些下面图片颜色,这里就是中间有点灰色,这是因为这个模糊视图把下面的图片覆盖了,所以没有显示出来,这才是图片不显示的根本原因.
解决问题
找到原因了,修改代码就比较容易了,你可以在添加视图时,将bgView指定到UIVisualEffectView,将新的视图添加到UIVisualEffectView上:
for (UIView * v in subs)
{
NSString * classname = NSStringFromClass([v class]);
if ([classname isEqualToString:@"_UINavigationBarBackground"] || [classname isEqualToString:@"UINavigationBarBackground"])
{
bgview=v;
break;
} else if ([classname isEqualToString:@"_UIBarBackground"]) {
//适配iOS10导航
for (UIView *vi in v.subviews) {
NSString *viName = NSStringFromClass([vi class]);
if ([viName isEqualToString:@"UIVisualEffectView"]) {
bgview = vi;
break;
}
}
}
}
也可以还添加到_UIBarBackground上,但是找到UIVisualEffectView,将其隐藏掉:
if ([classname isEqualToString:@"_UINavigationBarBackground"] || [classname isEqualToString:@"UINavigationBarBackground"])
{
bgview=v;
break;
} else if ([classname isEqualToString:@"_UIBarBackground"]) {
bgview = v;
for (UIView *vi in v.subviews) {
// 适配iOS10
NSString *viName = NSStringFromClass([vi class]);
if ([viName isEqualToString:@"UIVisualEffectView"]) {
vi.hidden = YES;
break;
}
}
}
再运行,会发现,问题解决:
到此这个问题就解决完毕,如果有其他的解决途径,还请不吝赐教,感谢!!!
(完)
Github | LQQZYY |
CSDN博客 | 流火绯瞳 |
新浪微博 | 杯水_沧海 |
302934443 |