UIiOS-Developer-OCios基础知识

iOS 13适配

2019-09-26  本文已影响0人  啸狼天

[UIApplication sharedApplication].keyWindow API将被弃用

@property(nullable, nonatomic,readonly) UIWindow *keyWindow API_DEPRECATED("Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes", ios(2.0, 13.0));

iOS13 UIApplication keyWindow被标记为API_DEPRECATED,

修改使用下方代码获取

[[[UIApplication sharedApplication] windows] objectAtIndex:0]

UISearchBar 黑线处理导致崩溃

iOS13之前为了处理搜索框的黑线问题,通常会遍历 searchBar 的 subViews,找到并删除 UISearchBarBackground。

修改为:

for (UIView *view in _searchBar.subviews.lastObject.subviews) {
    if ([view isKindOfClass:NSClassFromString(@"UISearchBarBackground")]) {
        view.layer.contents = nil;
        break;
    }
} 

设置 UISearchBarBackground 的 layer.contents 为 nil。

UISearchDisplayController彻底弃用,导致崩溃

在 iOS 8 之前,我们在 UITableView 上添加搜索框需要使用 UISearchBar + UISearchDisplayController 的组合方式。

在 iOS 8 之后,苹果就已经推出了 UISearchController 来代替这个组合方式。在 iOS 13 中,如果还继续使用 UISearchDisplayController会直接导致崩溃,崩溃信息如下:

Terminating app due to uncaught exception 'NSGenericException', reason: 'UISearchDisplayController is no longer supported when linking against this version of iOS. Please migrate your application to UISearchController.'

解决方法:使用UISearchController代替

私有API被封禁(KVC限制),禁止访问.

iOS13中通过KVC方式来获取私有属性,有Carsh风险,尽量避免使用.比如我们常用的UITextFiled和UISearchController等,在iOS 13的searchbar添加了一个- (void)set_cancelButtonText:(NSString *)text方法,这个方法专门用来命中kvc,一旦命中就Crash。

//修改textField的占位符字体颜色
[textField setValue:[UIColor xxx] forKeyPath:@"_placeholderLabel.textColor"];

(1).获取SearchBar的textField

由于在13中把SearchBar中的textField直接暴露给开发者使用,无需在通过kvc获取。

- (UITextField *)sa_GetSearchTextFiled{
    if ([[[UIDevice currentDevice]systemVersion] floatValue] >= 13.0) {
        return self.searchTextField;
    }else{
        UITextField *searchTextField =  [self valueForKey:@"_searchField"];
        return searchTextField;
    }
}

(2).修改TextFiled的占位符字体大小以及颜色,在iOS13中不能通过KVC来进行修改,可以通过其属性字符串来进行修改

UITextField *textfield = [[UITextField alloc]init];
NSMutableAttributedString *arrStr = [[NSMutableAttributedString alloc]initWithString:textfield.placeholder attributes:@{NSForegroundColorAttributeName : [UIColor redColor],NSFontAttributeName:[UIFont systemFontOfSize:12]}];
textfield.attributedPlaceholder = arrStr;

(3).获取SearchBar的cancleButton,由于searcBar的层级发生变化以及对象的局部变量,因为无法通过kvc的方式来获取

if ([[[UIDevice currentDevice]systemVersion] floatValue] >= 13.0) {
          for(id cc in [self.searchBar subviews]) {
              for (id zz in [cc subviews]) {
                  for (id gg in [zz subviews]) {
                      if([gg isKindOfClass:[UIButton class]]){
                          UIButton *cancelButton = (UIButton *)gg;
                          [cancelButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
                      }
                  }
              }

          }
      }else{
          UIButton*cancelButton = (UIButton *)[self.searchBar getVarWithName:@"_cancelButton"];
          [cancelButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
      }

MPMoviePlayerController在iOS13中废弃

MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.
在iOS13中对于MPMoviePlayerController使用的废弃,需要使用AVKit中的AVPlayerViewController来达到播放的目的。

Sign in with Apple 第三方登录

当 Sign In with Apple 服务正式上线以后,所有已接入其它第三方登录的 App,Sign In with Apple 将被要求作为一种登录选择,否则有可能就不给过。如果 APP 支持三方登陆(Facbook、Google、微信、QQ、支付宝等),就必须支持苹果登录,且要放前边。解决方法:未来上线之后,添加登录入口即可。

即将废弃的 LaunchImage

从 iOS 8 的时候,苹果就引入了 LaunchScreen,我们可以设置 LaunchScreen来作为启动页。当然,现在你还可以使用LaunchImage来设置启动图。不过使用LaunchImage的话,要求我们必须提供各种屏幕尺寸的启动图,来适配各种设备,随着苹果设备尺寸越来越多,这种方式显然不够 Flexible。而使用 LaunchScreen的话,情况会变的很简单, LaunchScreen是支持AutoLayout+SizeClass的,所以适配各种屏幕都不在话下。⚠️从2020年4月开始,所有使⽤ iOS13 SDK的 App将必须提供 LaunchScreen,LaunchImage即将退出历史舞台。可以使用Launch Storyboards来进行解决。

模态弹出默认交互改变

iOS 13 的 presentViewController 默认有视差效果,模态出来的界面现在默认都下滑返回。 一些页面必须要点确认才能消失的,需要适配。如果项目中页面高度全部是屏幕尺寸,那么多出来的导航高度会出现问题。

// Objective-C
self.modalPresentationStyle = UIModalPresentationFullScreen;

UIViewController 增加一个了属性 isModalInPresentation,默认为 false,当该属性为 false 时,用户下拉可以 dismiss 控制器,为 true 时,下拉不可以 dismiss控制器。

UISegmentedControl 默认样式改变

默认样式变为白底黑字,如果设置修改过颜色的话,页面需要修改

增加一直使用蓝牙的权限申请

CBCentralManager,iOS13以前,使用蓝牙时可以直接用,不会出现权限提示,iOS13后,再使用就会提示了。在info.plist里增加

 NSBluetoothAlwaysUsageDescription 我们要一直使用您的蓝牙,具体做什么别问我

废弃 UISearchDisplayController

在 iOS 8 之前,我们在 UITableView 上添加搜索框需要使用 UISearchBar + UISearchDisplayController 的组合方式,而在 iOS 8 之后,苹果就已经推出了 UISearchController 来代替这个组合方式。在 iOS 13 中,如果还继续使用 UISearchDisplayController 会直接导致崩溃,

黑夜模式

Apps on iOS 13 are expected to support dark mode Use system colors and materials Create your own dynamic colors and images Leverage flexible infrastructure

审核强制要求适配黑夜模式。

// 模式强制切换
if (darkMode) {
    if (@available(iOS 13.0, *)) {
        [UIApplication sharedApplication].keyWindow.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
    }
} else {
    if (@available(iOS 13.0, *)) {
        [UIApplication sharedApplication].keyWindow.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
    }
}

全局关闭黑暗模式

方式一 配置plist文件: 在Info.plist 文件中,添加UIUserInterfaceStyle key 名字为 User Interface Style 值为String,将UIUserInterfaceStyle key 的值设置为 Light
在开发中,如果用的系统控件(如cell、tableview的背景色)未设置背景色(或者为透明),则进入暗黑模式后,控件背景色变为黑色。

可以每一个页面设置,当然也可以整体设置, 一般我们的APP都是在一个window下的,那就整体设置APP里的window

方式二 :代码关闭黑暗模式 强制关闭暗黑模式

#if defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0
if(@available(iOS 13.0,*)){
self.window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
#endif

单个界面不遵循暗黑模式

UIViewController与UIView 都新增一个属性 overrideUserInterfaceStyle

将 overrideUserInterfaceStyle 设置为对应的模式,则强制限制该元素与其子元素以设置的模式进行展示,不跟随系统模式改变进行改变

1.设置 ViewController 的该属性, 将会影响视图控制器的视图和子视2.图控制器采用该样式
2.设置 View 的该属性, 将会影响视图及其所有子视图采用该样式
3.设置 Window 的该属性, 将会影响窗口中的所有内容都采用样式,包括根视图控制器和在该窗口中显示内容的所有演示控制器(UIPresentationController)

增加一直使用蓝牙的权限申请

CBCentralManager,iOS13以前,使用蓝牙时可以直接用,不会出现权限提示,iOS13后,再使用就会提示了。 在info.plist里增加

<key>NSBluetoothAlwaysUsageDescription</key>
<string>我们要一直使用您的蓝牙,具体做什么别问我</string>`

使用MJExtension 中处理NSNull的不同

这个直接会导致Crash的在将服务端数据字典转换为模型时,如果遇到服务端给的数据为NSNull时, mj_JSONObject,其中 class_copyPropertyList方法得到的属性里,多了一种EFSQLBinding类型的东西,而且属性数量也不准确, 那就没办法了, 我只能改写这个方法了,这个组件没有更新的情况下,写了一个方法swizzling掉把当遇到 NSNull时,直接转为nil了。

WKWebView 中测量页面内容高度的方式变更

iOS 13以前 document.body.scrollHeight iOS 13中 document.documentElement.scrollHeight 两者相差55 应该是浏览器定义高度变了

[deviceToken description] 获取到的格式发生变化

#include <arpa/inet.h>
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    if (![deviceToken isKindOfClass:[NSData class]]) return;
    const unsigned *tokenBytes = [deviceToken bytes];
    NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
                          ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
                          ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
                          ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
    NSLog(@"deviceToken:%@",hexToken);
}

UITextField

通过KVC方式修改空白提示语颜色 崩溃

[UITextField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor”];

解决方案:

attributedPlaceholder
leftView、rightView 设置异常 【疑似iOS13beta4新出现】

在设置leftView 左按钮时,如果使用的是UIImageView即会出现图片无法按照意图显示的问题。
@騲尼罵人獣狂 反馈UITextFieldrightView的子视图如果使用约束布局, 会导致rightView覆盖整个UITextField

// Confuse in beta4 iOS13
UIImageView *imageIcon = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 34, 30)];
//search_icon  15*15
imageIcon.image = [UIImage imageNamed:@"search_icon"];
imageIcon.contentMode = UIViewContentModeCenter;
UITextField *txtSearch = [[UITextField alloc] init];
txtSearch.leftView = imageIcon;

Status Bar

之前 Status Bar 有两种状态,default 和 lightContent

现在 Status Bar 有三种状态,default, darkContent 和 lightContent

现在的 darkContent 对应之前的 default,现在的 default 会根据情况自动选择 darkContent 和 lightContent

UIActivityIndicatorView

之前的 UIActivityIndicatorView 有三种 style 分别为 whiteLarge, white 和 gray,现在全部废弃。

增加两种 style 分别为 medium 和 large,指示器颜色用 color 属性修改。

如何在模式切换时打印日志

在 Arguments 中的 Arguments Passed On Launch 里面添加下面这行命令。

-UITraitCollectionChangeLoggingEnabled YES

UIImageView

//1\. 初始化问题
UIImageView.image 初始化时必须设置,否则不显示 

//2\. 暗黑适配问题 [图片经过拉伸处理后,会导致暗黑适配失效]
UIImage *image = [image stretchableImageWithLeftCapWidth:0 topCapHeight:top];
self.imageView.image = image;

#pragma mark - 解决Image拉伸问题
+ (UITraitCollection *)lightTrait API_AVAILABLE(ios(13.0)) {
    static UITraitCollection *trait = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        trait = [UITraitCollection traitCollectionWithTraitsFromCollections:@[
            [UITraitCollection traitCollectionWithDisplayScale:UIScreen.mainScreen.scale],
            [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight]
        ]];
    });

    return trait;
}

+ (UITraitCollection *)darkTrait API_AVAILABLE(ios(13.0)) {
    static UITraitCollection *trait = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        trait = [UITraitCollection traitCollectionWithTraitsFromCollections:@[
            [UITraitCollection traitCollectionWithDisplayScale:UIScreen.mainScreen.scale],
            [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark]
        ]];
    });

    return trait;
}

+ (void)fixResizableImage API_AVAILABLE(ios(13.0)) {

    Class klass = UIImage.class;
    SEL selector = @selector(resizableImageWithCapInsets:resizingMode:);
    Method method = class_getInstanceMethod(klass, selector);
    if (method == NULL) {
        return;
    }

    IMP originalImp = class_getMethodImplementation(klass, selector);
    if (!originalImp) {
        return;
    }

    IMP dynamicColorCompatibleImp = imp_implementationWithBlock(^UIImage *(UIImage *_self, UIEdgeInsets insets, UIImageResizingMode resizingMode) {
            // 理论上可以判断UIColor 是否是 UIDynamicCatalogColor.class, 如果不是, 直接返回原实现; 但没必要.
            UITraitCollection *lightTrait = [self lightTrait];
            UITraitCollection *darkTrait = [self darkTrait];

            UIImage *resizable = ((UIImage * (*)(UIImage *, SEL, UIEdgeInsets, UIImageResizingMode))
                                      originalImp)(_self, selector, insets, resizingMode);
            UIImage *resizableInLight = [_self.imageAsset imageWithTraitCollection:lightTrait];
            UIImage *resizableInDark = [_self.imageAsset imageWithTraitCollection:darkTrait];

            if (resizableInLight) {
                [resizable.imageAsset registerImage:((UIImage * (*)(UIImage *, SEL, UIEdgeInsets, UIImageResizingMode))
                                                         originalImp)(resizableInLight, selector, insets, resizingMode)
                                withTraitCollection:lightTrait];
            }
            if (resizableInDark) {
                [resizable.imageAsset registerImage:((UIImage * (*)(UIImage *, SEL, UIEdgeInsets, UIImageResizingMode))
                                                         originalImp)(resizableInDark, selector, insets, resizingMode)
                                withTraitCollection:darkTrait];
            }
            return resizable;
        });

    class_replaceMethod(klass, selector, dynamicColorCompatibleImp, method_getTypeEncoding(method));
}

绘制异常 【暂未确定是否为iOS13新发】

应用场景:自定义控件生成图片,绘制API会受到UIImage的拉伸方式UIImageResizingModeTile影响。

/// 常见的绘制代码
UIGraphicsBeginImageContextWithOptions(contentSize,YES,[[UIScreen mainScreen] scale]);

问题API:
/// CGContextRef ctx = UIGraphicsGetCurrentContext();
/// [self.viewContent.layer renderInContext:ctx];

建议使用如下API:
[self.viewContent drawViewHierarchyInRect:CGRectMake(0, 0, contentSize.width, contentSize.height) afterScreenUpdates:YES];

//生成图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

UIWindow 变更

在iOS13版本下,App 任意处生成YYTextView均会导致全局的scrollsToTop 回顶功能失效。
虽然最终追查至YYTextEffectWindow中,但整个排查过程还是发现了很多新内容的。

这是正常的回顶功能调用逻辑,基于此一条条的覆写了系统相关的私有函数来判别问题出自何处。


-[UICollectionView scrollViewShouldScrollToTop:] 
-[UIScrollView _scrollToTopIfPossible:] ()
-[UIScrollView _scrollToTopFromTouchAtScreenLocation:resultHandler:] ()
-[UIWindow _scrollToTopViewsUnderScreenPointIfNecessary:resultHandler:]_block_invoke.796 ()
-[UIWindow _handleScrollToTopAtXPosition:resultHandler:] ()

//此处能看到有个新鲜的 UIStatusBarManager 是iOS13新增的类,可以看到状态栏的点击事件已经被其接管了。
//经过实践,出问题的时候该方法也能被正常调用故此排上以上调用栈方法。
-[UIStatusBarManager _handleScrollToTopAtXPosition:] ()
-[UIStatusBarManager handleTapAction:] ()

开始以为是多个UIScrollView共存时scrollsToTop的设置问题,还有UIScrollViewContentInsetAdjustmentNever的设置问题。结果都不是...
最终沿着UIScrollView 子类一直查找,找到了YYTextView 其中用到的 YYTextEffectWindow也进入了视野...

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (![UIApplication isAppExtension]) {
            one = [self new];
            one.frame = (CGRect){.size = kScreenSize};
            one.userInteractionEnabled = NO;
            //此处能看到 窗口等级是高于状态栏的,但多次尝试等级调整均无果。
            one.windowLevel = UIWindowLevelStatusBar + 1;

           //元凶在这里
           //所以,即使关闭了用户交互 但是它竟能够阻挡状态栏的事件,但却对常规Window的事件无任何影响...
            if (@available(iOS 13.0, *)) {
                //费解的结果...
                one.hidden = YES;
            }else{
                one.hidden = NO;
            }

            // for iOS 9:
            one.opaque = NO;
            one.backgroundColor = [UIColor clearColor];
            one.layer.backgroundColor = [UIColor clearColor].CGColor;
        }
    });
    return one;

在UIWindow 上使用addSubview添加子视图,需要注意 暗黑模式切换,并不会向子视图下发状态变更。

获取系统暗黑切换通知(自行实现),然后重写添加到 UIWindow 的子视图 overrideUserInterfaceStyle 为正确的状态。

状态栏相关

        if (@available(iOS 13.0, *)) {
            UIView *_localStatusBar = [[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager performSelector:@selector(createLocalStatusBar)];
            UIView * statusBar = [_localStatusBar performSelector:@selector(statusBar)];
            // 注意此代码不生效 用于绘制
           // [statusBar drawViewHierarchyInRect:statusBar.bounds afterScreenUpdates:NO];
            [statusBar.layer renderInContext:context];

        } else {
            // Fallback on earlier versions
        }

常见于视频播放页需求
原因1:视频播放器所属的 UIViewController 未能正确旋转所致。
原因2:iOS13下API失效
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];

允许控制器旋转,iOS13横屏时会自动隐藏状态栏。

由于iOS13下当前状态栏实际上被系统强制接管了,是拿不到的。🐶 或者是有我没找到的API

    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    UIView *viewStatusColorBlend = [[UIView alloc]initWithFrame:keyWindow.windowScene.statusBarManager.statusBarFrame];
    viewStatusColorBlend.backgroundColor = Color;
    [keyWindow addSubview:viewStatusColorBlend];

UIScrollView 滚动条异常偏移

屏幕旋转可能会触发系统对滚动条的自动修正
如果没有修改需求,关闭该特性即可

#ifdef __IPHONE_13_0
   if (@available(iOS 13.0, *)) {
       self.automaticallyAdjustsScrollIndicatorInsets = NO;
   }
#endif

UICollectionView 异常API

该API 在iOS13下会强制将cell置中,导致上部留白。
推测,底部应该也会有留白的情况。

#pragma mark - 修复iOS13 下滚动异常API
#ifdef __IPHONE_13_0
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated{

    [super scrollToItemAtIndexPath:indexPath atScrollPosition:scrollPosition animated:animated];

    //修复13下 Cell滚动位置异常
    //顶部
    if(self.contentOffset.y < 0){
        [self setContentOffset:CGPointZero];
        return;
    }

    //底部
    if(self.contentOffset.y > self.contentSize.height){
        [self setContentOffset:CGPointMake(0, self.contentSize.height)];
    }
}
#endif

UITableViewCell 异常 【疑似iOS13beta4新出现】

[self addSubView: viewObjA]
[self.contentView addSubview:viewObjB]
上面两种方式,在遇到折叠需求时。设置self.clipsToBounds=YES 可能会有布局异常

//保险的做法 [添加如下两句]
self.clipsToBounds = YES;  【无效】
//此处很费解
self.layer.masksTobounds = YES;  【有效】

疑似布局引擎机制有调整 【有待确定】

在调试中发现,如果代码流是这样一种状态 可能会造成 【约束失效】
如果遇到诡异问题 需要排查下是否存在约束和绝对布局混用的情况

[viewMain addSubView:viewA];
[viewMain addSubView:viewB];
// 更新 viewA 的约束
 [self.imageBackground mas_updateConstraints:^(MASConstraintMaker *make) {
       make.top.mas_equalTo(50);
 }];

 //立即更新约束
 [viewA.superview setNeedsUpdateConstraints];
 [viewA.superview updateConstraintsIfNeeded];
 [viewA.superview layoutIfNeeded];

//更新容器约束
[viewMain mas_updateConstraints:^(MASConstraintMaker *make) {
       make....
 }];

....
其它处理逻辑
....

// 更新 viewA 的约束 【代码不会生效】
 [self.imageBackground mas_updateConstraints:^(MASConstraintMaker *make) {
       make.top.mas_equalTo(100);
 }];

WKWebView 暗黑适配

要点:

  1. 模式参数通过 UA 传递
  2. 联调中出现加载闪白问题
webView.opaque = false;

手势影响

iOS13下,如果在UITextView上附加如拖动手势,会发现如果触点落在UITextView之上极易触发第一响应者。
实际效果,可对比iOS12之前版本的表现。

!!!注意这两项即使开启也不会有改善效果!!!
gesture.cancelsTouchesInView = YES;
gesture.delaysTouchesBegan = YES;

image image
///UITextView override
#ifdef __IPHONE_13_0
//用于解决 iOS13下,可拖动UITextView场景中放大镜手势引起的异常激活编辑状态问题。
-(void)addInteraction:(id<UIInteraction>)interaction{
    [super addInteraction:interaction];

    if(!self.otherGestureRecognizer || self.otherGestureRecognizer.count == 0){
        return;
    }

    if([interaction isKindOfClass:NSClassFromString(@"UITextLoupeInteraction")]){
        UIGestureRecognizer *delayLoupeGesture = [self.gestureRecognizers objectWithBlock:^BOOL(UIGestureRecognizer *obj) {
            return [obj isKindOfClass:NSClassFromString(@"UIVariableDelayLoupeGesture")];
        }];
        if(delayLoupeGesture){

            [self.otherGestureRecognizer forEach:^(UIGestureRecognizer *obj) {
                [delayLoupeGesture requireGestureRecognizerToFail:obj];
            }];
        }

    }
}
#endif

push时UITabBarItem字体颜色变化

@interface MainViewController : UITabBarController

@end

当push时使用 self.hidesBottomBarWhenPushed = YES;

  UITabBarItem *barItem = [[UITabBarItem alloc] initWithTitle:title image:[[UIImage imageNamed:imageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] selectedImage:[[UIImage imageNamed:hightImage] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
  
  barItem.titlePositionAdjustment = UIOffsetMake(0, -5);
  
  [barItem setTitleTextAttributes:@{NSForegroundColorAttributeName : RGBCOLOR(0x21BD66)} forState:UIControlStateSelected];
  [barItem setTitleTextAttributes:@{NSForegroundColorAttributeName : RGBCOLOR(0x8a8a8a)} forState:UIControlStateNormal];
  
  //在iOS13中  self.hidesBottomBarWhenPushed = YES; 是UITabBarItem字体颜色变化,此两行代码就可解决
  self.tabBar.tintColor = RGBCOLOR(0xffffff);
  self.tabBar.barTintColor = RGBCOLOR(0xffffff);
  
  
  nav.tabBarItem = barItem;
  //设置导航栏字体颜色
  [nav.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor blackColor], NSFontAttributeName : [UIFont fontWithName:@"Helvetica-Bold" size:16]}];
  [self.controllerArray addObject:nav];
 

UIKit

音频

音频共享

上一篇下一篇

猜你喜欢

热点阅读