[iOS10]Xcode8系统导航适配

开发环境

Xcode 8
iOS 10

Xcode 7.3
iOS9.3

问题

最近有个朋友问我,在适配iOS10的时候,导航的图片不显示了,使用的是系统导航,怎么调整都不显示.
在Xcode7.3,iOS9.3显示如下:

[iOS10]Xcode8系统导航适配_第1张图片
Xcode7.3-iOS9.3正常情况下

导航中间位置有一个LOGO视图(当然不是这个条形码),而在Xcode8-iOS10上,这个视图不显示了,如下:

[iOS10]Xcode8系统导航适配_第2张图片
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 = >",
    "<_UINavigationBarBackIndicatorView: 0x7f86cdc0d6c0; frame = (0 11.5; 13 21); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = >"
)

发现其背景视图名称变了,暗自高兴,这么容易就找到了,欢欢喜喜的修改了如下代码:

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如下图:

[iOS10]Xcode8系统导航适配_第3张图片
Xcode7.3-iOS9.3

导航条的视图布局如下:

[iOS10]Xcode8系统导航适配_第4张图片
导航条视图布局

而在Xcode8-iOS10则变成这样了:

[iOS10]Xcode8系统导航适配_第5张图片
Xcode8-iOS10层级关系

而导航条的布局为:

[iOS10]Xcode8系统导航适配_第6张图片
Xcode8导航条布局

发现,添加的视图是存在的,但是为什么不显示呢?
仔细观察两个视图的区别会发现,在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;
                }
            }
        }

再运行,会发现,问题解决:

[iOS10]Xcode8系统导航适配_第7张图片
Xcode8-iOS10

到此这个问题就解决完毕,如果有其他的解决途径,还请不吝赐教,感谢!!!

(完)

Github LQQZYY
CSDN博客 流火绯瞳
新浪微博 杯水_沧海
QQ 302934443

你可能感兴趣的:([iOS10]Xcode8系统导航适配)