【MISSAJJ原创-iOS】 Xcode9~iOS 11和iP

作者: MISSAJJ琴瑟静听 | 来源:发表于2017-09-23 01:06 被阅读3205次
    MISSAJJ Projects

    前天9月21日,手机更新到iOS 11, 看了一下早期上架 App Store 的应用, 啥问题都没有, 心里正沾沾自喜也松了一口气......

    可昨夜更新到 Xcode9后编译代码,发现还有一些问题的, 因为同时管理了好几个应用,其他应用也是需要同步作 iOS 11适配, 所以好记不如赖笔头, 省得适配其他应用的时候忘记.....

    问题 1: UINavigationBar 内UIBarButtonItem按钮错位拉伸

    问题描述:

    好在公司的几个应用的导航栏设计并不复杂, 不需要自定义 titleView,所以不涉及到自定义导航titleView的宽度适配问题.

    但是,自定义的 MANavigationController里所重写的UIBarButtonItem返回按钮 icon 被拉宽,并且各界面导航栏UIBarButtonItem按钮, 也同样挤压和错位,设置的 title 也看不到了.

    以下2张截图就是Xcode9编译代码发现的iOS 11下UIBarButtonItem按钮出现的问题:

    • 图1: 主界面顶部左右3个按钮被拉伸
      [图片加载中,请耐心等待....]


      IMG_4897.PNG
    • 图2: 顶部导航栏中间的 title 消失, 3个按钮错位和被拉伸
      [图片加载中,请耐心等待....]

    IMG_4899.PNG

    解决方案:

    最简单的解决方案: 将 UIbutton 包装到 UIview 内, 再通过initWithCustomView方法传递给UIBarButtonItem

        //针对 iOS11适配改写 的关键性代码, 就这么几行,完全搞定了
        UIView *containVew = [[UIView alloc] initWithFrame:btn.bounds];
        [containVew addSubview:btn];
        return [[UIBarButtonItem alloc]initWithCustomView:containVew];
    
    
     以下代码摘自 MISSAJJ 写的MAButtonTool工具类,为了节约时间,提高创建按钮控件的效率,特抽出一个创建各种按钮的类方法
     
     支持:
     1,图片按钮 (默认居中按钮,左返回按钮,右分享按钮)
     2,自定义文字图片靠左靠右按钮
     3,按项目需求,设定了按钮样式和位置样式
     4,只要修改一下分享和返回按钮图片就可以直接应用到项目中了
     5,由于美工给的图片素材尺寸会不同,所以按钮的frame和setImageEdgeInsets可根据项目素材情况在VC层创建后重写调整
     6,支持block调用按钮事件
       
     使用方法请看:https://github.com/MISSAJJ/MAButtonTool
    
    ^_^ 我只要在这个工具类里针对 iOS 11增加几行包装代码,
    就解决了全部项目在 iOS 11下导航栏按钮错位问题, 
    这就是包装工具类的好处......
    
    
    #pragma mark ==[自定义 block 导航栏 按钮]==
    +(UIBarButtonItem *)createButtonWithImage:(NSString * __nullable)imageStr position:(MAButtonToolPostion)position type:(MAButtonToolType)type actionBlock:(ButtonItemBlock)block
    {
        UIButton* btn;
        
        if (position == MAButtonToolPostionLeft) { //位置靠左
            
            if (type ==MAButtonToolTypeBack) {  //返回按钮
                btn = [self createLeftBackButton];
            }else{
                btn = [self createLeftButton:imageStr]; //默认靠左按钮
            }
            
        }else if (position == MAButtonToolPostionRight) { //位置靠右
            
            if (type ==MAButtonToolTypeShare) {  //分享按钮
                btn = [self createRightShareButton];
            }else{
                btn = [self createRightButton:imageStr];//默认考右按钮
            }
            
        }else {  //位置中间
            btn = [self createButton:imageStr];
        }
        
        [btn addTouchAction:^(UIButton *btn) {
            
            if (block)
            {
                block(btn);
            }
            
        }];
    
        //针对 iOS11适配改写
        UIView *containVew = [[UIView alloc] initWithFrame:btn.bounds];
        [containVew addSubview:btn];
        return [[UIBarButtonItem alloc]initWithCustomView:containVew];
    }
    
    
    #pragma mark ==[左自定义图片按钮]==
    + (UIButton *)createLeftButton:(NSString *)imageStr
    {
        UIButton* btn= [self createButton:imageStr]; 
        [btn setImageEdgeInsets:UIEdgeInsetsMake(0, -10, 0, 10)];
        return btn;
    }
    
    #pragma mark ==[右自定义图片按钮]==
    + (UIButton*)createRightButton:(NSString*)imageStr
    {
        UIButton* btn=[self createButton:imageStr];
        [btn setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, -10)];
        return btn;
        
    }
    
    #pragma mark ==[左返回按钮]==
    + (UIButton*)createLeftBackButton
    {
        UIButton* btn= [self createButton:@"backarrow_white"];
        btn.frame = CGRectMake(0, 0, 50, 50);
        [btn setImageEdgeInsets:UIEdgeInsetsMake(0, -20, 0, 20)];
        return btn;
    }
    
    #pragma mark ==[右分享按钮]==
    + (UIButton*)createRightShareButton
    {
        UIButton* btn= [self createButton:@"share_white"];
        btn.frame = CGRectMake(0, 0, 35, 35);
        [btn setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, -10)];
        return btn;
    }
    

    解决问题后的导航栏显示截图

    • 图1: 导航栏左右3个按钮显示正常, 中间的标题也显示正常了
      [图片加载中,请耐心等待....]


      IMG_4901.PNG
    • 图2: 主界面顶部左右3个按钮显示正常了
      [图片加载中,请耐心等待....]


      IMG_4901.PNG

    问题 2 : Xcode9下相册等访问权限问题

    查了资料说iOS11下,苹果对相册的权限key做了调整,原来的 NSPhotoLibraryUsageDescription ,在iOS11之后,改成了NSPhotoLibraryAddUsageDescription

    针对于此测试了一下应用,果然毫无悬念, 立即去 info.plist 把 key 改成NSPhotoLibraryAddUsageDescription, 很快解决问题了.

    图3: info.plist内设置NSPhotoLibraryAddUsageDescription权限
    [图片加载中,请耐心等待....]


    2D3256F9-45E2-412C-B4AF-E66EB262E4B6.png

    问题 3 : 等我好好睡个美容觉之后, 再继续写吧....... : )

    昨夜熬到凌晨3点,适配发布好了[AR 扫描器]APP应用,已经提交审核,
    今夜适配另外一个[乐游博物馆]APP 应用, 不知不觉又已经凌晨1:00了,

    这两个星期几乎每天都只睡了几个小时,

    好怕自己迅速变老,
    好怕自己肾衰竭猝死,
    好怕自己吃东西没滋味,
    好怕自己神经衰落睡不着,

    今天可是周末啊! ~周末啊! ~周末啊! ~
    .........哎........

    问题 4 : MJRefresh下拉刷新适配 iOS 11和 iPhone X问题

    熬夜完成了公司的2个应用的 iOS 11适配之后, 今晚开始适配自己的一些项目,打开其中一个项目在不同的模拟器下分别编译看效果, 底部自定义 tabbar 显示没有问题, 但顶部是隐藏了 NavigationBar并采用了MJRefresh下拉刷新,发现有错位..

    图4: iOS 11下拉刷新出现错位问题
    [图片加载中,请耐心等待....]


    屏幕快照 2017-09-24 01.57.32.png

    图4: iPhone X下拉刷新出现错位问题
    [图片加载中,请耐心等待....]


    屏幕快照 2017-09-24 01.58.03.png

    我的解决方案: (灰常简单)

    因为我的布局是 CollectionView, 所以只要设置 iOS 11的新特性方法contentInsetAdjustmentBehavior为UIScrollViewContentInsetAdjustmentNever就可以了
    以此类推,如果是 UITableView 布局的,也是设置contentInsetAdjustmentBehavior

    判定 iOS 11的方法, 官方建议的方法:

    以下是官方的屏幕尺寸, 原本最初的想法就是根据屏幕的高度812pt来判定


    图片.png

    官方建议的方法 :

    if (@available(iOS 11.0, *)) {
    }else{
    }
    

    我的适配代码:

    if (@available(iOS 11.0, *)) {
          _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
     } else {
       // Fallback on earlier versions
     }
    
    

    判定iPhoneX的方法 :

    
    #define isIPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? [[UIScreen mainScreen] currentMode].size.height==2436 : NO)
    
    

    其他的一些相关适配方法:(摘自 MJRefresh讨论区的解决方案)

    注:首先这个下拉刷新的偏移量并不是MJRefresh造成的,但是确实需要适配,比如通栏ViewController显示的时候,刘海会遮住下拉刷新的组件,解决办法是对下拉刷新控件自定义,调整内部组件的布局,通栏的ViewController地方使用自定义的下拉控件。

    对于iOS11下的iPhoneX适配下拉刷新有以下几点:

    1,首先请配置相应的启动图,尺寸是1125*2436;
    2,对于通栏ViewController中的UIScrollView,系统会默认根据contentInsetAdjustmentBehavior属性改变其bounds的y值为-44,导致UIScrollView中的所有子控件下移,解决办法是,对于通栏ViewController,请设置其UIScrollView的contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever。

    其他适配点:

    1,iOS11下的iPhoneX的导航栏为高度44,状态栏高度也调整为44,所以整个顶部状态栏的高度和导航栏的高度一起是88,自定义导航栏的同学需要根据系统机型控制导航栏高度;
    2,iOS11下的iPhoneX的tabBar的高度调整为83,自定义tabBar的同学建议使用Frame布局;
    3,iOS11下的iPhoneX下,屏幕底部默认显示了长条状的Home键指示器,可以通过UIViewController (UIHomeIndicatorAutoHidden)分类中的prefersHomeIndicatorAutoHidden来隐藏,但是官方并不建议这样做。

    适配 iOS 11和 iPhone X 之后的界面效果

    我的建议:
    在 iPhone X 下还是最好还是有导航栏的设计比较美观, 因为隐藏导航栏后, 刘海会把顶部控件切割掉, 画面就比较尴尬了....哈哈~~

    图5: 适配后的截图
    [图片加载中,请耐心等待....]


    屏幕快照 2017-09-24 02.23.18.png

    图6: 适配后的下拉刷新,同时隐藏导航栏的截图


    图片.png

    图7: 界面上滑显示导航栏的效果

    屏幕快照 2017-09-24 05.23.34.png

    iPhone X 导航栏错位问题

    iOS11下的iPhoneX的导航栏为高度44,状态栏高度也调整为44,所以整个顶部状态栏的高度和导航栏的高度一起是88,所以在自定义导航栏里针对 iPhone X 修改的高度

    图片.png

    我的解决方法:
    我所有的项目都是使用了宏定义参数的方法来设置各种控件的, 所以只要改写这些相关宏定义参数, 整个项目都同步做好了适配, 所以平时的积累和归纳思维很重要,关键时刻可以减轻很多不必要的重复工作量.

    /*****宏定义 *****/
    //导航栏高度
    #define  MANavBarHeight  isIPhoneX ? 88 : 64
    //底部Tabbar 高度
    #define MATabBarHeight  isIPhoneX ? 83 : 49 
    //状态栏高度
    #define  MAStatusBarHeight  isIPhoneX ? 44 : 20
    
    //一些相关同步对应的代码
    // set navigationBar backgroundImage
    - (void)MA_setBackgroundImage:(UIImage *)image
    {
        [self.backgroundView removeFromSuperview];
        self.backgroundView = nil;
        if (self.backgroundImageView == nil)
        {
            // add a image(nil color) to _UIBarBackground make it clear
            [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
            self.backgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), MANavBarHeight)];
            self.backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
            // _UIBarBackground is first subView for navigationBar
            [self.subviews.firstObject insertSubview:self.backgroundImageView atIndex:0];
        }
        self.backgroundImageView.image = image;
    }
    
    // set navigationBar barTintColor
    - (void)MA_setBackgroundColor:(UIColor *)color
    {
        [self.backgroundImageView removeFromSuperview];
        self.backgroundImageView = nil;
        if (self.backgroundView == nil)
        {
            // add a image(nil color) to _UIBarBackground make it clear
            [self setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
            self.backgroundView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), MANavBarHeight)];
            self.backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
            // _UIBarBackground is first subView for navigationBar
            [self.subviews.firstObject insertSubview:self.backgroundView atIndex:0];
        }
        self.backgroundView.backgroundColor = color;
    }
    
    其他方法:

    网络里也有相关这种重写layoutSubviews的方法,我试过之后发现导航栏变透明,并且颜色怪怪的了, 所以最终还是用了上面的方法解决了问题, 下面的这种方法大家也可是尝试一下

    自定义的navigationBar,在iOS11上运行就可能出现布局错乱的bug,
    解决办法是重写UINavigationBar的layoutSubviews方法调整布局:
    
    - (void)layoutSubviews {
        [super layoutSubviews];
        
        //注意导航栏及状态栏高度适配
        self.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), MANavBarHeight);
        for (UIView *view in self.subviews) {
            if([NSStringFromClass([view class]) containsString:@"Background"]) {
                view.frame = self.bounds;
            }
            else if ([NSStringFromClass([view class]) containsString:@"ContentView"]) {
                CGRect frame = view.frame;
                frame.origin.y = statusBarHeight;
                frame.size.height = self.bounds.size.height - frame.origin.y;
                view.frame = frame;
            }
        }
    }
    

    适配 iPhone X 之后的截图

    图片.png

    问题 5 : XCode9打包上传遇到的问题和解决方式

    问题:上传后返回警告,缺失1024px的图标
    图标缺失
    原因和解决: 升级Xcode9后Assets/AppIcon下多了一个1024pt的icon框,需要补上缺失的图标
    1024pt图标

    问题 6 : iPhone X下自定义键盘的高度如何增加34px 的高度

    iPhone X 的默认系统键盘 : 底部会自动加上高度
    默认系统键盘底部会自动加上高度
    问题: 自定义的表情键盘的底部在 iPhone X 下没有增加高度
    自定义的键盘底部不够高
    将自定义表情emojiToolBarView设置为 UITextView输入框的inputAccessoryView,emojiToolBarView会置顶于系统键盘,并且跟随系统键盘向上向下移动
    self.customTextView.inputAccessoryView = self.emojiToolBarView;
    
    将自定义表情toolBar 传给 UITextView的inputAccessoryView
    //点击自定义表情按钮事件的逻辑
    - (IBAction)emotionBtnClicked:(id)sender {
        UIButton *button = sender;
        
        if (!isEmotionShow) {
            [button setImage:[UIImage imageNamed:@"board_system"] forState:UIControlStateNormal];
            isEmotionShow = YES;
            isKeyboard = NO;
            // self.customEmojiBoardView为自定义表情键盘 View
            self.customTextView.inputView = self.customEmojiBoardView;
            [self.customTextView resignFirstResponder];
            
        }else{
            [button setImage:[UIImage imageNamed:@"board_emoji"] forState:UIControlStateNormal];
            isEmotionShow = NO;
            isKeyboard = YES;
            self.customTextView.inputView = nil;
            [self.customTextView resignFirstResponder];
            
        }
    }
    
    增加高度后的自定义表情键盘
    解决办法: 将你自定义的键盘的customEmojiBoardView 的高度加上34就可以了
    //自定义表情键盘的宽高
     CGFloat viewWidth = [UIScreen mainScreen].bounds.size.width - 16;
    //原本自定义的高度是 216, 那就判定 iPhone X 下高度 再加上 34 为: 216+34 ;
     CGFloat viewHeight = isPhoneX ? 250 : 216;
    
    //自定义表情键盘customEmojiBoardView 的初始化 
     - (instancetype)init { 
        self = [super initWithFrame:CGRectMake(0, 0,viewWidth, viewHeight)];
        if (self) {
           以下代码省略...... 
        }
        return self; 
    }
    

    最后:

    Contact 联系方式:
    希望能有更多的狮子一起共勉探讨学习,愉快奔跑!
    联系方式: QQ 996174446 [验证:iOS 攻城狮]
    MISSAJJ网站 : http://www.MISSAJJ.com
    Github : https://github.com/MISSAJJ
    GitBook : https://www.gitbook.com/@missajj
    MISSAJJ琴瑟静听( Swift 和 Objective-C )iOS 开发项目电子书
    https://github.com/MISSAJJ/MISSAJJ_IOS_DEVELOPMENT_BOOK

    相关文章

      网友评论

      • Xavier_Lost:iPhone X自定义键盘底部怎么空34个距离
        MISSAJJ琴瑟静听: 你的问题已经更新在文内,请看文内的问题 6 : 自定义键盘的高度如何增加34px 的高度
        Xavier_Lost:@MISSAJJ琴瑟静听 我是添加到inputView 上的
        MISSAJJ琴瑟静听:@略_0727 先打印出你自定义的键盘的高度,针对需求找到相关代码往上移
      • if_you_like:哈哈哈,不明觉厉
      • 177e2f7f8f57:感觉现在都不会嵌套UISearchController了 或者UISearchBar 都是一个做一个button 做个触发搜索事件
        :joy:
        177e2f7f8f57:@MISSAJJ琴瑟静听 嗯 但是又觉得 原生的动画很有质感
        MISSAJJ琴瑟静听:其实最容易的方案,就是用UIview+UIimageview+UItextview 自定义模仿成SearchBar的样子, 获取用户输入的UItextview值,接着请求服务器数据, 成功后跳转到搜索列表界面,一了百了,不用纠结于UISearchBar或者UISearchController的乱七八糟的问题。
      • 灵台无计:感谢楼主呀,帮了大忙了
        MISSAJJ琴瑟静听:@灵台无计 能帮到你是我的荣幸:yum:
      • iOS白水:通过自定义leftbaritem 实现返回按钮偏左。你没有解决呢?
        MISSAJJ琴瑟静听:@超S神 等我把那个工具类更新到iOS11适配版本,就没有问题了……更新代码最近没空发布
        iOS白水:@MISSAJJ琴瑟静听 qq交流。你那种有问题。我已经加你qq。你通过一下。
        MISSAJJ琴瑟静听:@超S神 我的github里有一个MAButtonTool 工具类,解决了偏左偏右的问题
      • 幸福的尾巴__:app的美女挺漂亮:smirk:
      • 李乾坤David:是不是可以用一下这个!https://github.com/HarshilShah/NotchKit 解决iPhone X上的问题?
        MISSAJJ琴瑟静听:@李乾坤David 等我空下来,看看……
      • 简了个书呗:请问iOS11searchBar的占位文字和放大镜居中你是怎么做的,我之前的是居中,iOS11变成左对齐了。
        MISSAJJ琴瑟静听:@简了个书呗 我的不是searchBar控件,完全是自定义Imageview 和UILabel做出來的,避开了iOS11 中titleView的棘手问题:stuck_out_tongue_winking_eye:……苹果官方有iOS 11中titleView内嵌入searchBar的案例的

      本文标题:【MISSAJJ原创-iOS】 Xcode9~iOS 11和iP

      本文链接:https://www.haomeiwen.com/subject/hoeqextx.html