ios13_ios13.4 - CSDN
精华内容
参与话题
  • iOS13真机包,13.zip

    2020-07-21 10:31:48
    打开 Finder,按下 command + shift + G,输入 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport,将文件解压到这个目录
  • I、 适配第三方库在iOS13的问题: 1.1) : 升级腾讯的第三方UI框架,解决iOS13 无法访问私有属性的问题 II、 适配iOS13UI控件的API :(涉及的模块有登录) 2.1)UITextField的_placeholderLabel属性:无法直接访问_...

    前言

    汇总本文要点

    1、适配第三方库在iOS13的问题:

    • 1.1) : 升级腾讯的第三方UI框架,解决iOS13 无法访问私有属性的问题

    2、 适配iOS13UI控件的API :(涉及的模块有登录)

    • 2.1)UITextField的_placeholderLabel属性:无法直接访问,使用 富文本的API【 NSMutableAttributedString attributedPlaceholder】
    
     self.endBtn.attributedPlaceholder =[[NSAttributedString alloc] initWithString:models.clearsendStr attributes:    @{NSForegroundColorAttributeName:rgb(153,153,153) ,NSFontAttributeName:self.endBtn.font        }];
         self.numberTF.attributedPlaceholder =[[NSAttributedString alloc] initWithString:self.numberTF.placeholder attributes:    @{NSFontAttributeName:self.numberTF.font        }];
         
     //    [self.numberTF setValue:self.numberTF.font forKeyPath:@"_placeholderLabel.font"];  // iOS13 的系统闪退
    
    
    • 2.2)适配暗黑模式
    • 2.3)iOS 13适配:设置UITabBarItem上title选择和缺省状态的颜色,使用新的API【self.tabBar.unselectedItemTintColor】
    • 2.4)设置状态栏背景颜色的解决方案:使用新的API 【statusBarManager】
    • 2.5)iOS13 适配【present 半屏问题】: 如果没适配会导致列表下拉刷新失效。modalPresentationStyle属性默认不是UIModalPresentationFullScreen了,需要根据需求手动设置:推荐使用UIModalPresentationOverFullScreen
    • 2.6)CNCopyCurrentNetworkInfo:获取WiFi SSID的接口CNCopyCurrentNetworkInfo 不再返回SSID的值,除非先获取用户位置权限才能返回SSID

    I、 适配第三方库在iOS13的问题:

    1.1) : 升级腾讯的第三方UI框架,解决iOS13 无法访问私有属性的问题

    II、 适配iOS13UI控件的API :( 禁止用 KVC访问私有属性)

    同 iOS 13 更新时的 textField 的 placeHolder 属性一样,iOS 14 禁止用 KVC访问 UIPageControl 的私有属性 pageImage

    2.1)UITextField的_placeholderLabel属性:无法直接访问_placeholderLabel.textColor

    解决方案: 使用 NSMutableAttributedString 富文本attributedPlaceholder来替代KVC访问 UITextField 的 _placeholderLabel。

    + (void)setupUITextField4attributedPlaceholder:(UITextField*)textField{
        
                if (@available(iOS 13.0, *)) {
                    
                    
                }else{
                    
                    return;
                }
        
        
        
        textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"placeholder" attributes:@{NSForegroundColorAttributeName:kTextPlaceholderColor, NSFontAttributeName:kTextFont(13) }];
    
        
    //    textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"placeholder" attributes:@{NSForegroundColorAttributeName: [UIColor darkGrayColor], NSFontAttributeName: [UIFont systemFontOfSize:13]}];
    
    }
    
    

    2.2)适配暗黑模式

    2.2.1 关闭暗黑模式

    • 关闭
    <key>UIUserInterfaceStyle</key>
    	<string>Light</string>
    

    2.2.2 暗色模式开发规范

    如果想暗色模式适配起来更方便,就要在开发的时候统一一套暗色模式开发规范;

    • 页面
    • 文本
    • 图片及icon
    • 导航栏
    • 页面卡
    • 状态栏

    当做主题来开发

    1. 首先定制一批颜色:每个颜色都分为亮色模式暗色模式两种
    2. 定义一批图片,亮色和暗色区别
    3. 网络请求图片的处理:如果后台没有这两种,在暗色模式下图片加白边
    4. 导航栏、页面、状态栏、页面卡背景色处理
    5. 其它更多针对每个app的细节修改

    2.3)iOS 13适配:设置UITabBarItem上title颜色

        if (@available(iOS 13.0, *)) {
            self.tabBar.unselectedItemTintColor = ktabNorTextColor;
            
            self.tabBar.tintColor = BASE_RED_COLOR;
    
        }else{
            
            //设置文字样式
            NSMutableDictionary *textAttr = [NSMutableDictionary dictionary];
            textAttr[NSForegroundColorAttributeName] = ktabNorTextColor;
            [childVC.tabBarItem setTitleTextAttributes:textAttr forState:UIControlStateNormal];
            //选择状态的文字颜色样式
            NSMutableDictionary *selectedTextAttr = [NSMutableDictionary dictionary];
            [selectedTextAttr setValue:BASE_RED_COLOR forKey:NSForegroundColorAttributeName];
            [childVC.tabBarItem setTitleTextAttributes:selectedTextAttr forState:UIControlStateSelected];
            
    
            
        }
    
    

    2.3)设置状态栏背景颜色

     [Bugly]  Trapped uncaught exception 'NSInternalInconsistencyException', reason: 'App called -statusBar or -statusBarWindow on UIApplication: this code must be changed as there's no longer a status bar or status bar window. Use the statusBarManager object on the window scene instead.' 
    
    • 旧代码
        UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
    
    
    • 解决方案:使用keyWindow.windowScene.statusBarManager
    if (@available(iOS 13.0, *)) {
           UIView *statusBar = [[UIView alloc]initWithFrame:[UIApplication sharedApplication].keyWindow.windowScene.statusBarManager.statusBarFrame] ;
            statusBar.backgroundColor = color;
            [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
        } else {
            // Fallback on earlier versions
            UIView *statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
               if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
                   statusBar.backgroundColor = color;
               }
        }
    
    
    

    坑2:如果整个项目的状态栏(电池栏)都是有颜色的,并且都是不透明的,上面这个方法完全可以应付

    • 但是:如果有状态是有透明或者半透明的效果,上面这个方法还是不能胜任,越透明越明显;经过一番查找,终于发现问题:

    • 问题: iOS 13之前,可以通过valueForKey 获取UIApplication的statusBar,因为UIApplication是单例,因此,在iOS 12,通过: [[[UIApplication sharedApplication] valueForKey:@“statusBarWindow”] valueForKey:@“statusBar”]拿到的statusBar永远是同一个对象。不行可以打印出内存地址看下就很清楚了。iOS 13之后,因为苹果不允许使用KVC的valueForKey访问私有属性。通过上面的代码可以多看点,每次进来都调用 alloc:init的方法,重新生成一个statusBar;然后添加到UIApplication的keyWindow上,再设置背景颜色。因此这个方法多次调用就会创建多份statusBar,造成内存开销不说,如果设置为透明,根部不能起效果。

    解决办法:既然定位到问题所在,办法就是保证iOS 13 之后,每次也都能拿到有去只有一个对象。方法有很多,我的方法代码如下:使用 static 配合 gcd

    HSSingletonM(QCTStatusBarTool);
    
    + (void)setStatusBarBackgroundColor4ios13:(UIColor *)color {
        
        static UIView *statusBar = nil;
        static dispatch_once_t onceToken;
        if (@available(iOS 13.0, *)) {  //iOS 13不允许使用valueForKey、setValue: forKey获取和设置私有属性;
            dispatch_once(&onceToken, ^{
                statusBar = [[UIView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame];
                [[UIApplication sharedApplication].keyWindow addSubview:statusBar];
            });
                    
         } else {
             statusBar = [[[UIApplication sharedApplication] valueForKey:@"statusBarWindow"] valueForKey:@"statusBar"];
        }
        if ([statusBar respondsToSelector:@selector(setBackgroundColor:)]) {
            statusBar.backgroundColor = color;
        }
    }
    
    
    

    2.5)iOS13 适配【present 半屏问题】: 如果没适配会导致列表下拉刷新失效

    modalPresentationStyle属性默认不是UIModalPresentationFullScreen了,需要根据需求手动设置

    //
    //  UIViewController+ERPPresent13.m
    //  retail
    //
    //  Created by mac on 2020/2/24.
    //  Copyright © 2020 QCT. All rights reserved.
    //
    
    #import "UIViewController+ERPPresent13.h"
    
    static const char *K_automaticallySetModalPresentationStyleKey;
    
    @implementation UIViewController (ERPPresent13)
    + (void)load {
        Method originAddObserverMethod = class_getInstanceMethod(self, @selector(presentViewController:animated:completion:));
        Method swizzledAddObserverMethod = class_getInstanceMethod(self, @selector(K_presentViewController:animated:completion:));
        method_exchangeImplementations(originAddObserverMethod, swizzledAddObserverMethod);
    }
    
    - (void)setK_automaticallySetModalPresentationStyle:(BOOL)K_automaticallySetModalPresentationStyle {
        objc_setAssociatedObject(self, K_automaticallySetModalPresentationStyleKey, @(K_automaticallySetModalPresentationStyle), OBJC_ASSOCIATION_ASSIGN);
    }
    
    - (BOOL)K_automaticallySetModalPresentationStyle {
        id obj = objc_getAssociatedObject(self, K_automaticallySetModalPresentationStyleKey);
        if (obj) {
            return [obj boolValue];
        }
        return [self.class K_automaticallySetModalPresentationStyle];
    }
    
    + (BOOL)K_automaticallySetModalPresentationStyle {
        if ([self isKindOfClass:[UIImagePickerController class]] || [self isKindOfClass:[UIAlertController class]]) {
            return NO;
        }
        return YES;
    }
    
    - (void)K_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
        if (@available(iOS 13.0, *)) {
            if (viewControllerToPresent.K_automaticallySetModalPresentationStyle) {
                viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
            }
            [self K_presentViewController:viewControllerToPresent animated:flag completion:completion];
        } else {
            // Fallback on earlier versions
            [self K_presentViewController:viewControllerToPresent animated:flag completion:completion];
        }
    }
    
    @end
    
    
    
    
    

    2.6 CNCopyCurrentNetworkInfo:获取WiFi SSID的接口CNCopyCurrentNetworkInfo 不再返回SSID的值,除非先获取用户位置权限才能返回SSID

    - (NSString*) getWifiSsid {
        if (@available(iOS 13.0, *)) {
            //用户明确拒绝,可以弹窗提示用户到设置中手动打开权限
            if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusDenied) {
                NSLog(@"User has explicitly denied authorization for this application, or location services are disabled in Settings.");
                //使用下面接口可以打开当前应用的设置页面
                //[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
                return nil;
            }
            CLLocationManager* cllocation = [[CLLocationManager alloc] init];
            if(![CLLocationManager locationServicesEnabled] || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined){
                //弹框提示用户是否开启位置权限
                [cllocation requestWhenInUseAuthorization];
                usleep(50);
                //递归等待用户选选择
                return [self getWifiSsidWithCallback:callback];
            }
        }
        NSString *wifiName = nil;
        CFArrayRef wifiInterfaces = CNCopySupportedInterfaces();
        if (!wifiInterfaces) {
            return nil;
        }
        NSArray *interfaces = (__bridge NSArray *)wifiInterfaces;
        for (NSString *interfaceName in interfaces) {
            CFDictionaryRef dictRef = CNCopyCurrentNetworkInfo((__bridge CFStringRef)(interfaceName));
    
            if (dictRef) {
                NSDictionary *networkInfo = (__bridge NSDictionary *)dictRef;
                NSLog(@"network info -> %@", networkInfo);
                wifiName = [networkInfo objectForKey:(__bridge NSString *)kCNNetworkInfoKeySSID];
                CFRelease(dictRef);
            }
        }
        CFRelease(wifiInterfaces);
        return wifiName;
    }
    
    
    

    III、 iOS13生命周期的改动

    原本AppDelegate(UIApplicationDelegate)控制生命周期的行为移交给了SceneDelegate(UIWindowSceneDelegate)

    如果不使用iPad的多窗口的话建议大家不要使用场景。

    3.1 不使用场景的具体步骤如下:

    1、 使用Xcode11以上新建的项目,删除info.plist UIApplicationSceneManifest
    2、在Appdelegate.h中添加一个window属性
    3、在AppDelegate的didFinishLaunchingWithOptions创建视图

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        
        UITabBarController *tabbarVC = [[UITabBarController alloc] init];
        
        tabbarVC.viewControllers = @[
            [[UINavigationController alloc] initWithRootViewController:[ViewController1 new]],
            [[UINavigationController alloc] initWithRootViewController:[KNViewController2 new]],
            [[UINavigationController alloc] initWithRootViewController:[KNViewController3 new]],
        ];
        
        self.window.rootViewController = tabbarVC;
        [self.window makeKeyAndVisible];
    
        
        
        return YES;
    }
    
    
    

    不使用场景

    see also

    • 补充说明iOS13的UIModalPresentationFullScreen
    //            viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
                
                            viewControllerToPresent.modalPresentationStyle = UIModalPresentationAutomatic;// 1、后果:被怼了很惨,因为项目里有很多模态出来的VC是半透明,结果现在变成完全不透明,背景为黑色。2、 修复拜访记录日期控件PGDatePicker蒙版的问题:点击时间输入框,弹窗蒙版变成了空白
    
                //            2、后遗症:因为把显示效果修改为:UIModalPresentationOverFullScreen;半透明,全屏覆盖的问题都得到完美解决。但是会引发一个新的问题:前一个页面的viewWillAppear:、viewDidAppear:也无法触发。例如: A   Present  B, 有时因为业务逻辑需要,必须在viewWillAppear, viewDidAppear里写一些代码,当B 调用dismiss方法的时候, A的这个两个方法不会触发,因此会有一些安全隐患。因此如果要求B 调用dismiss方法,A要执行viewWillAppear:、viewDidAppear:这个两个方法,这个时候要把B的modalPresentationStyle设置为:UIModalPresentationFullScreen;
    
                            
                //      3、      其他:如果要求 B既要半透明,dismiss时,A还要调用viewWillAppear:、viewDidAppear:。我的想法是在B 写一个block,在B调用dismiss之前,利用block回调A相关的业务逻辑代码。如果有其他更好的方法请告诉我。万分感谢!!
                            
    
    
    展开全文
  • iOS13相关变化及适配

    千次阅读 2019-10-16 19:25:05
    文章目录一、 iOS 13 支持的机型二、 适配要求三、具体适配清单1、 Dark Mode2、Sign In with Apple3、模态弹出视图的显示问题...iOS13以后将不再继续支持UIWebView7、UISearchDisplayController被废弃8、 MPMoviePl...


    9月20号iOS 13 已正式发布,第一时间更新了最新系统,网上对其用户体验上的新特性的描述也很多,而对于开发者来说,更需要关注的是新系统在 API 层面做了哪些改动,对我们现有的代码产生什么影响,需要做什么样的适配。

    本文主要列举了一些需要开发者注意的地方,不一定项目中都有涉及到相关发生变化的东西,但仍需注意。

    一、 iOS 13 支持的机型

    •iPhone X、iPhone XR、iPhone XS、iPhone XS Max
    •iPhone 8、iPhone 8 Plus
    •iPhone 7、iPhone 7 Plus
    •iPhone 6s、iPhone 6s Plus
    •iPhone SE
    •iPod touch (第七代)

    二、 适配要求

    Starting April, 2020, all iOS apps submitted to the App Store will need to be built with the iOS 13 SDK or later. They must also support the all-screen design of iPhone XS Max or the 12.9-inch iPad Pro (3rd generation), or later.

    根据官网的说法,2020年4月之后所有提交到 App Store 的应用必须使用 iOS 13 以上的 SDK 进行编译,并要求屏幕尺寸支持 iPhone Xs Max 和 12.9 寸 iPad Pro。

    三、具体适配清单

    1、 Dark Mode

    Dark Mode(暗黑模式)是苹果在iOS13推出的新特性。使用iOS13及更高版本的系统的iOS 设备,可以使用暗黑模式。在暗黑模式下,系统会采用较暗的视图控件。开发者在开发过程中需要对视图控件进行相应暗模式的适配。

    适配原理:
    1.将同一个资源,创建出两种模式的样式。系统根据当前选择的样式,自动获取该样式的资源
    2.每次系统更新样式时,应用会调用当前所有存在的元素调用对应的一些重新方法,进行重绘视图,可以在对应的方法做相应的改动

    如果不打算适配 Dark Mode,可以强行关闭暗黑模式

    if(@available(iOS 13.0, *)){
            [self setOverrideUserInterfaceStyle:UIUserInterfaceStyleLight];
        }
    

    不过即使设置了颜色方案,系统自带的申请各个权限的弹窗还是会依据系统的颜色进行显示,自己创建的提示弹窗 UIAlertController则不会。

    对于暗黑模式,如果项目中重新对各个控件设置过背景色,那么即使开启暗黑模式,也不会对控件的背景色有影响;如果未重新设置过背景色,那么APP里的控件就会根据系统的显示模式而显示相应的颜色,此时需要适配暗黑模式,否则有些控件显示就会异常。

    2、Sign In with Apple

    在 iOS 13 中苹果推出一种在 App 和网站上快速、便捷登录的方式: Sign In With Apple。这是 iOS 13 新增的功能,因此需要使用 Xcode 11 进行开发。关于应用是否要求接入此登录方式,苹果在 App Store 应用审核指南 中提到:

    Apps that exclusively use a third-party or social login service (such as Facebook Login, Google Sign-In, Sign in with Twitter, Sign In with LinkedIn, Login with Amazon, or WeChat Login) to set up or authenticate the user’s primary account with the app must also offer Sign in with Apple as an equivalent option.

    如果应用使用了第三方或社交账号登录服务(如Facebook、Google、Twitter、LinkedIn、Amazon、微信等)来设置或验证用户的主账号,就必须把 Sign In With Apple 作为同等的选项添加到应用上。

    如果是下面这些类型的应用则不需要添加:
    •仅仅使用公司内部账号来注册和登录的应用;
    •要求用户使用现有的教育或企业账号进行登录的教育、企业或商务类型的应用;
    •使用政府或业界支持的公民身份识别系统或电子标识对用户进行身份验证的应用;
    •特定第三方服务的应用,用户需要直接登录其邮箱、社交媒体或其他第三方帐户才能访问其内容。

    另外需要注意,关于何时要求接入 Sign In With Apple,苹果在 News and Updates 中提到:

    Starting today, new apps submitted to the App Store must follow these guidelines. Existing apps and app updates must follow them by April 2020.

    现有应用和应用更新须在 2020 年 4 月前完成接入。

    这部分目前还未看到有APP做这一条的适配,对于我们自己自身的APP我觉得暂时也不急于做,可以先看看其他APP具体如何做,然后参考参考,再制定具体的方案。

    3、模态弹出视图的显示问题

    一般打开新页面会采用push的方式,某些临时页面会采用模态视图present的方式,iOS13后模态出新页面的时候会出现页面从导航栏下开始显示的情况,主要是因为之前对UIViewController里面的一个属性,即modalPresentationStyle(该属性是控制器在模态视图时将要使用的样式)没有设置需要的类型。

    在iOS13中modalPresentationStyle的默认改为UIModalPresentationAutomatic,而在之前默认是UIModalPresentationFullScreen。所以如果想显示样式和以前的保持一致,需要手动设置modalPresentationStyleUIModalPresentationFullScreen

    这个属性不受Xcode版本的影响,只要是iOS13系统,采用present的方式打开页面却没有设置modalPresentationStyleUIModalPresentationFullScreen的话,就会有这个显示问题

    4、不允许使用KVC进行对私有属性进行获取或者修改

    iOS13中通过KVC方式来获取私有属性,有Carsh风险,尽量避免使用.比如我们常用的UITextFiledUISearchController等。尽量不要使用valueForKeysetValue: forKeyPath: 等方法获取或设置私有属性,虽然编译可以通过,但是在运行时会直接崩溃。比如访问 UISearchBar 的 _searchField:

    UITextField *textField = [searchBar valueForKey:@"_searchField"];//崩溃
    [textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];//崩溃
    

    5、推送的 deviceToken 获取到的格式发生变化

    系统返回deviceToken的方法是- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    由此可见,返回的是NSData类型的deviceToken。如果需要把NSData类型的deviceToken转换成字符串类型,原本只需要用系统方法转换,然后替换掉多余的符号即可:

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        NSString *token = [deviceToken description];
        for (NSString *symbol in @[@" ", @"<", @">", @"-"]) {
            token = [token stringByReplacingOccurrencesOfString:symbol withString:@""];
        }
        NSLog(@"deviceToken:%@", token);
    }
    

    但在 iOS 13 中,这种方法已经失效,NSData类型的 deviceToken 转换成的字符串变成了:

    {length = 32, bytes = 0xd7f9fe34 69be14d1 fa51be22 329ac80d … 5ad13017 b8ad0736 } `

    解决方案:

    需要进行一次数据格式处理,获取方式如下:

    #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);
    }
    

    项目中用到deviceToken的场景是注册极光推送,而极光推送注册的API使用的是NSData类型的deviceToken,所以并不需要客户端做类型转换处理,目前相关的推送SDK也未有iOS13兼容的更新提示,后续是否需要升级推送SDK,还需继续关注。

    6、 iOS13以后将不再继续支持UIWebView

    UIKIT_EXTERN API_DEPRECATED("No longer supported; please adopt WKWebView.", ios(2.0, 12.0)) API_UNAVAILABLE(tvos, macos) @interface UIWebView : UIView <NSCoding, UIScrollViewDelegate>
    

    在 iOS 13 后,官方将UIWebView的支持的系统范围定格在了iOS 2.0 ~ iOS 12.0,建议开发者用WKWebViewUIWebView进行适配。目前,网上有人提到,如果开发者将包含 UIWebView api 的应用更新上传到 App Store 审核后,其将会收到包含 ITMS-90809 信息的回复邮件,提示你在下一次提交时将应用中 UIWebView 的 api 移除。但是并不会影响当次的审核,下次再提交如果还是有UIWebView还是会继续发邮件提醒你更换成WKWebView。

    Dear Developer,
    We identified one or more issues with a recent delivery for your app, "xxx". Your delivery was successful, but you may wish to correct the following issues in your next delivery:
    ITMS-90809: Deprecated API Usage - Apple will stop accepting submissions of apps that use UIWebView APIs . See developer.apple.com/documentati… for more information.
    After you’ve corrected the issues, you can use Xcode or Application Loader to upload a new binary to App Store Connect.
    Best regards,
    The App Store Team
    

    解决方案
    WKWebView替代UIWebView,确保所有 UIWebView 的 api 都要移除,如果需要适配 iOS 7 的可以通过 openURL 的方式在 Safari 打开。

    7、UISearchDisplayController被废弃

    在iOS 8 之前,在 UITableView 上添加搜索框可以采用 UISearchBar + UISearchDisplayController的组合方式,而在 iOS 8 之后,苹果就已经推出了 UISearchController 来代替这个组合方式。在 iOS 13 中已经不支持UISearchDisplayController,如果还继续使用 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替换 UISearchBar + UISearchDisplayController 的组合方案。

    8、 MPMoviePlayerController 被弃用

    在 iOS 9 之前播放视频可以使用MediaPlayer.framework中的MPMoviePlayerController类来完成,它支持本地视频和网络视频播放。但是在 iOS 9 开始被弃用,如果在 iOS 13 中继续使用的话会直接抛出异常:

    *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'MPMoviePlayerController is no longer available. Use AVPlayerViewController in AVKit.'
    

    解决方案

    使用AVFoundation 里的AVPlayer 作为视频播放控件。

    9、蓝牙权限字段更新导致审核失败

    For apps with a deployment target of iOS 13 and later, use NSBluetoothAlwaysUsageDescription instead.
    

    在 iOS 13 中,苹果将原来蓝牙申请权限用的 NSBluetoothPeripheralUsageDescription字段,替换为 NSBluetoothAlwaysUsageDescription 字段。

    如果还是以旧的字段提交审核,将会收到包含 ITMS-90683 的邮件

    解决方案
    官方文档提到:

    For deployment targets earlier than iOS 13, add both NSBluetoothAlwaysUsageDescription and NSBluetoothPeripheralUsageDescription to your app’s Information Property List file.
    

    所以只要在Info.plist 中把两个字段都加上即可。

    10、 LaunchImage 被弃用

    iOS 有两种设置启动图的方式,一种是LaunchImage,一种是LaunchScreen。采用LaunchImage设置启动图的话需要根据不同的机型设计相应尺寸的启动图,随着苹果设备屏幕尺寸越多,所需要的启动图就越多,这种启动图的设置方式就会显得不够智能;LaunchScreen只要一张图片,系统会自动适配,其采用的是AutoLayout+SizeClass的方式,可以自动适配各种屏幕。

    苹果在 Modernizing Your UI for iOS 13 section 中提到 ,从2020年4月开始,所有支持 iOS 13 的 App 必须提供LaunchScreen.storyboard,否则将无法提交到 App Store 进行审核。

    11、 UISegmentedControl 默认样式改变

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

    原本设置选中颜色的tintColor 已经失效,新增了selectedSegmentTintColor 属性用以修改选中的颜色。

    ####12、 Xcode 11 创建的工程在低版本设备上运行黑屏
    使用 Xcode 11 创建的工程,运行设备选择 iOS 13.0 以下的设备,运行应用时会出现黑屏。这是因为 Xcode 11 默认是会创建通过UIScene管理多个 UIWindow 的应用,工程中除了AppDelegate外会多一个SceneDelegate,
    SceneDelegate是为了 iPadOS 的多进程准备的,但是旧版本根本没有UIScene

    解决方案

    在 AppDelegate 的头文件加上:
    @property (strong, nonatomic) UIWindow *window;

    13、 StatusBar 与之前版本不同

    目前状态栏也增加了一种模式,由之前的两种,变成了三种, 其中default由之前的黑色内容,变成了会根据系统模式,自动选择当前展示lightContent还是darkContent

    14、 TabBar 选中文字颜色变成系统默认蓝色

    在iOS13系统中,跳转到二级页面再返回一级页面时,TabBar的选中项的文字颜色会变成系统默认的蓝色。主要是由于tincolor影响了 ,通过重新设置默认颜色即可

    if (@available(iOS 13.0, *)) {
               self.tabBar.unselectedItemTintColor = THEMEBLUECOLOR;
           } else {
           // Fallback on earlier versions
           }
    

    以上是综合各个资料及项目中遇到的整理的iOS13适配点,从20号发布iOS13.0正式版到现在,截止目前已经推出了iOS13.1.3版本,关于iOS13的适配仍需持续关注。

    展开全文
  • 5.iOS13初探

    2019-08-08 14:35:21
    iOS13初探TextFIeld KVC的问题presentViewController 的问题崩溃问题DeviceToken 的问题Dark 模式适配问题 iOS13测试版发布以后,老大让我赶紧也适配一下,就一番折腾,安装了ios13Btea测试版,Xcode直接添加ios13...


    iOS13测试版发布以后,老大让我赶紧也适配一下,就一番折腾,安装了ios13Btea测试版,Xcode直接添加ios13真机包,一运行,没有任何问题,网上说的TextFIeldKVC会崩溃,模态跳转的问题完全都不存在
    重点:也就是说iOS13是完全兼容Xcode11之前的版本的,只有通过 Xcode11编译运行的才会有上述问题

    以下问题都是建立在Xcode11iOS13之上的

    TextFIeld KVC的问题
    //iOS13以前我们可以通过KVC 修改TextFiled的内部属性,例如:
    
       [self.txtPhone setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
       [self.txtPassword setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
       
    //但是,在iOS13之后就会崩溃,需要改成下面这样:
    
        self.txtPhone.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"登录手机号"attributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
        self.txtPassword.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"请输入密码"attributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
    
    
    
    presentViewController 的问题

    iOS13之前我们只要设置如下就可以了,至于模态的方式一般默认,有需要再调整:

    UIViewController *vc = [[UIViewController alloc] init];
    vc.view.backgroundColor = [UIColor orangeColor];
    [self presentViewController:vc animated:YES completion:nil];
    

    但是,iOS13以后上面这个代码,只模态出小卡片形式,如果需要之前一样还是满屏的的模态可设置如下:

    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    

    这里还有个问题就是:在dismiss vc的时候,不会再走vc 的这两个方法,如果在这两个方法中有初始化或者重要逻辑的,就需要修改了

    - (void)viewWillAppear:(BOOL)animated;
    - (void)viewWillDisappear:(BOOL)animated;
    
    崩溃问题
    [_LSDefaults sharedInstance]: unrecognized selector sent to class 0x1dfc01258
    

    代码运行起来0~2分钟内,必然会出现这个崩溃,代码里所有sharedInstance的地方加了断点一个都没走,很绝望,最后通过注释代码的方式,终于找到问题所在了,是由于接入UM, 在设置UM的appkey的时候崩溃的:

    [UMConfigure initWithAppkey:@"" channel:nil];
    

    解决方法:升级UMCCommon到最新的2.1.1版本,最好呢,继承UM的库都升级到最新版本

    DeviceToken 的问题

    菜鸟第一次从官网下载了一个iOS13 public测试版本的描述文件,安装以后,真机运行完全都不会走这个方法:

    -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    

    证书,push开关这些都没问题的,因为在非iOS13的手机上都是没问题的,也在开发群里咨询了大神,他们的都是可以的没有问题,最后菜鸟只能退回到iOS12.4, 真机运行时没问题的,说明手机没问题,再次下载iOS13 Beta5描述文件安装以后,再真机就能获取到deviceToken了,我也很无奈、、、、

    iOS13 DeviceToken获取方法,来源于UM:

    #include <arpa/inet.h>
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
    {
        if (![deviceToken isKindOfClass:[NSData class]]) return;
        const unsigned *tokenBytes = (const unsigned *)[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);
    }
    
    Dark 模式适配问题

    在Dark模式下, app没有设置背景颜色的控件会呈现Dark模式的颜色,字体颜色会根据Dark模式自动变化。

    设置了背景色的地方就需要进行适配:

    UIColor *dyColor = [UIColor colorWithDynamicProvider:^UIColor * _Nonnull(UITraitCollection * _Nonnull trainCollection) {
            if ([trainCollection userInterfaceStyle] == UIUserInterfaceStyleLight) {
                return [UIColor redColor];
            }
            else {
                return [UIColor greenColor];
            }
        }];
        
     [self.bgView setBackgroundColor:dyColor];
    

    但是项目中,设置背景的地方太多了,改起来工作量很大,我试图通过Method Swizzling 进行重写:

    + (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
    

    来达到适配dark,但是很遗憾,这样做虽然能够解决部分背景,但是还有一部分还是需要单独设置,尤其是字体颜色

    图片的适配:
    在这里插入图片描述那有人说,适配这个Dark模式太浪费时间了,要等UI重新设计, 效果还不一定好,那能不能强制设置Light(非Dark)模式呢

    很肯定的告诉你:可以的

    只需要在info.plist里加入:UserInterfaceStyle : UIUserInterfaceStyleLight
    在这里插入图片描述那单个VC可不可设置强制设置呢

    也是可以的:

    self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark
    

    TabBar 字体颜色的问题

    1. Dark模式下,跳转界面返回以后,tabBarItem的字体变成了蓝色,改不了
      跳转前:
      在这里插入图片描述跳转返回后:
      在这里插入图片描述可以过一下代码解决:
    //未选中下的颜色(ios10以后才有)
    UITabBar.appearance.unselectedItemTintColor = [UIColor redColor];
    //选中下的颜色(代替selectedImageTintColor)
    UITabBar.appearance.tintColor = [UIColor orangeColor];
    

    未解决的问题

    1. tabBar的setShadowImage不起作用,去不掉上边线
     UITabBarController * tabBC = [[UITabBarController alloc] init];
     [tabBC.tabBar setShadowImage:[self createImageWithColor:[UIColor orangeColor]]];
     [tabBC.tabBar setBackgroundImage:[self createImageWithColor:[UIColor whiteColor]]];
    

    上述代码设置了tabBar的shadowImage为 orangeColor颜色的
    事件结果如图,没有任何的效果,如果不设置默认是黑色的上边线:
    在这里插入图片描述

    展开全文
  • iOS13 适配总结

    千次阅读 2019-11-14 14:53:20
    1、UISegmentedControl 修改选择背景色 if (@available(iOS 13.0, *)) { _segmented.selectedSegmentTintColor = Stock_Red; } else { _segmented.tintColor = Stock_Red; }

    1、UISegmentedControl 修改选择背景色

           if (@available(iOS 13.0, *)) {
                _segmented.selectedSegmentTintColor = Stock_Red;
            } else {
                _segmented.tintColor = Stock_Red;
            }
    // 以下代码可以代替上面:
       [_segmented setBackgroundImage:[UIImage imageWithColor:[UIColor clearColor]] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
       [_segmented setBackgroundImage:[UIImage imageWithColor:Stock_Red] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
    
    // [UIImage imageWithColor:xx]
    // 这是我自己封装的方法:返回一张纯色图片 
    + (UIImage *)imageWithColor:(UIColor *)color {
        CGRect rect = CGRectMake(0, 0, 1, 1);
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    
    



    2、模态视图样式

    代码块语法遵循标准markdown代码,例如:

    要改回原来模态视图样式,我们只需要把UIModalPresentationStyle设置为UIModalPresentationFullScreen即可。
    
    ViewController *vc = [[ViewController alloc] init];
    vc.title = @"presentVC";
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
    nav.modalPresentationStyle = UIModalPresentationFullScreen;
    [self.window.rootViewController presentViewController:nav animated:YES completion:nil];
    



    3、私有KVC

    在使用iOS 13运行项目时突然APP就crash掉了。定位到的问题是在设置UITextField的Placeholder也就是占位文本的颜色和字体时使用了KVC的方法:

    [_textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
    [_textField setValue:[UIFont systemFontOfSize:14] forKeyPath:@"_placeholderLabel.font"];
    

    可以将其替换为:

    _textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"文本" attributes:@{
    NSFontAttributeName:[UIFont systemFontOfSize:16],
    NSForegroundColorAttributeName:[UIColor redColor]}];
    

    并且只需要在初始化的时候设置attributedPlaceholder即富文本的占位文本,再重新赋值依然使用placeolder直接设置文本内容,样式不会改变。



    4、黑暗模式

    取消黑暗模式
    在 plist 文件中添加一下键值对:
    UIUserInterfaceStyle Light
    在这里插入图片描述



    5、iOS13 屏幕旋转

    这里 ViewController 简称:VC
    iOS13以前的 API (在iOS13中失效了),以前在进入ViewController 时可以自动调用,现在不调用了

    @interface xxViewController
    
    @end
    
    @implementation xxViewController
    
    // 原需求:屏幕锁定,不支持屏幕旋转,手动让VC横屏    
    #pragma mark - Orientation是否支持转屏
    - (BOOL)shouldAutorotate{
        return NO;
    }
    #pragma mark - 支持哪些转屏方向
    - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
        if (self.isBack) {
            return UIInterfaceOrientationMaskPortrait;
        }else {
            return UIInterfaceOrientationMaskLandscapeRight;
        }
    }
    #pragma mark - 默认的屏幕方向
    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
        return UIInterfaceOrientationLandscapeRight;
    }
    @end
    

    iOS 13 中的解决方案

    //-----------------------"  AppDelegate  "-----------------------
    #import <UIKit/UIKit.h>
    #import <CoreData/CoreData.h>
    + (AppDelegate *)shareInstance;
    // 旋转屏幕 
    -(void)changeOrientation:(UIInterfaceOrientation)toOrientation;
    @end
    
    
    #import "AppDelegate.h"
    @interface AppDelegate () 
    @end
    
    @implementation AppDelegate
    
    static AppDelegate *_singleInstance;
    +(AppDelegate *)shareInstance {
        return _singleInstance;
    }
    - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        if(self.allowRotation) {
            return UIInterfaceOrientationMaskLandscape;
        } else {
            return UIInterfaceOrientationMaskPortrait;
        }
    }
    //要解决很简单,只需要在方法函数头部添加几句不会被编译器优化掉的代码即可。
    #pragma mark - 旋转屏幕
    -(void)changeOrientation:(UIInterfaceOrientation)toOrientation {
        NSLog(@"---旋转屏幕= %ld",(long)toOrientation);
      if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
            SEL selector = NSSelectorFromString(@"setOrientation:");
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];
            [invocation setSelector:selector];
            [invocation setTarget:[UIDevice currentDevice]];
          
          int val = 0;
          if (toOrientation==UIInterfaceOrientationPortrait) {
              val = UIInterfaceOrientationPortrait;
              
          }else if (toOrientation==UIInterfaceOrientationPortraitUpsideDown){
              val = UIInterfaceOrientationPortraitUpsideDown;
              
          }else if (toOrientation==UIInterfaceOrientationLandscapeLeft){
              val = UIInterfaceOrientationLandscapeRight;
              
          }else if (toOrientation==UIInterfaceOrientationLandscapeRight){
              val = UIInterfaceOrientationLandscapeLeft;
          }
            [invocation setArgument:&val atIndex:2];
            [invocation invoke];
        }
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
     
        //1.AppDelegate
        _singleInstance = self;
        self.application = application;
        return YES;
    }
    @end
    
    //-----------------------"  xxViewController  "-----------------------
    interface xxViewController
    
    @end
    
    @implementation xxViewController
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        [AppDelegate shareInstance].allowRotation = YES;
        [[AppDelegate shareInstance] changeOrientation:UIInterfaceOrientationLandscapeLeft];
    }
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
        [AppDelegate shareInstance].allowRotation = NO;
         [[AppDelegate shareInstance] changeOrientation:UIInterfaceOrientationPortrait];
    }
    @end
    
    



    6、iOS13 新增编辑手势

    复制:三指捏合
    剪切:两次三指捏合
    粘贴:三指松开
    撤销:三指向左划动(或三指双击)
    重做:三指向右划动
    快捷菜单:三指单击

    // 暂时禁用

    #ifdef __IPHONE_13_0
    - (UIEditingInteractionConfiguration)editingInteractionConfiguration{
        return UIEditingInteractionConfigurationNone;
    }
    #endif
    



    7、iOS13 新生命周期 SceneDelegate

    增加了 #import "SceneDelegate.h"
    原来的 #import "AppDelegate.h" 没有了window

    要想维持原状,需要在AppDelegate里,添加window,并且删掉Info.plist里的新增键值对
    @property (strong, nonatomic) UIWindow *window;

    @interface AppDelegate : UIResponder
    @property (strong, nonatomic) UIWindow *window;
    @end
    删掉以下键值对
    Application Scene Manifest:2times
    Main storyboard file base name:Main

    在这里插入图片描述


    更新中·····

    「文章有不对地方,欢迎批评指正!」
    展开全文
  • iOS13.1.zip

    2020-05-17 19:08:09
    解压放置:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport 文件夹
  • iOS历史回顾(iOS1~iOS8)

    万次阅读 2014-09-27 23:37:11
    历史对比
  • 现在有不少小伙伴都更新到了iOS13系统,如要适配他的黑暗模式那必须要一张完美的黑色壁纸,但是壁纸黑色的下方的Dock栏还有一条,对于强迫症的患者简直忍不了,今天就给大家...
  • ios14 6月22号凌晨ios14测试版推出后,上午立马给我的小7装上尝尝鲜。 ios14主要的不同点是: App资源库,可以智能分类 小组件,主屏幕和负一屏 画中画,这个实测仅限apple TV可以使用 接下来的一段时间让我深刻...
  • ios13怎么添加自定义字体

    千次阅读 2019-09-26 09:15:36
    随着ios13系统的正式版推送,很多用户已经开始升级了ios13系统,而在ios系统中新增了很多意外的功能,苹果竟然可以改字体了,那么ios13怎么添加自定义字体呢?下面就为大家带来ios13添加自定义字体的方法,一起来...
  • iOS13 已越狱 iOS12.4 已越狱

    万次阅读 2019-06-20 12:13:39
    你没看错,iOS13 beta 内测版系统刚出没多久,那么快被攻破了,在2019年6月11日国外越狱大神 iBSparkes 开发者 在推特分享了二张图片,分别为iOS12.4 和 iOS 13 已经越狱的 Cydia 截图。众所周知一旦设备成功搭载 ...
  • 在苹果官方推出的ios13.2正式版本之后,很多用户升级了发现还是有很多存在问题,最大的问题就是ios13.2系统疯狂杀进程,可以自动把你的后台运行应用全部关了,那么ios13.2杀进程怎么解决呢?下面为大家带来有关ios...
  • 2019年9月20日,知道ios13的第一时间,选择了升级,然后watch也提示升级os6。然后就。。 接下来说说我的努力吧。 一、睡一觉,手机上下载到手表上的os6,慢慢更新完。 二、隔天醒来,终于下载完了,然后到了手机...
  • 随着iPhone11搭载iOS13系统正式发布,越来越多的老iPhone用户也升级到了iOS13。虽然iOS系统每次升级多会或多或少存在一些问题,但整体来说都是利大于弊,无脑升级就对了。 但是,这次iOS13升级确实给不少用户带来...
  • iOS开发 iOS13禁用深色模式

    万次阅读 2019-09-24 15:46:42
    全局禁用深色模式(暗黑模式) 在Info.plist中增加UIUserInterfaceStyle,值为Light,如下 <key>UIUserInterfaceStyle</key> <string>Light</string>...如果想要在某个UIViewController中禁用深色...
  • 大家都知道在iPhone系统更新的时候都会提示咱们进行更新,但是有些小伙伴不想更新,但是不更新有一个小红点1这样人很烦躁,对于强迫症的人实在是忍不了,今天我就给大家分享一个方法,只需要一...
  • 前言自打iOS13正式版出来后就有不断的小伙伴吐槽这个系统不稳,Bug太多,好后悔,当然也有很多小伙伴很喜欢新版系统,认为新系统真的很棒,期待已久的黑暗模式,以及更好用的...
  • 收集整理一波iOS12的捷径库(使用方法见文末),大家使用过程中如果发现有啥问题或者想实现什么捷径,可以关注微信公众号“云峰小罗”,找到我。 1.抖音视频无水印下载 2. 清除照片位置信息 3. 获取热门新闻 4.照片...
  • iOS学习之系统历史版本概览

    千次阅读 2017-10-18 18:25:53
    日期 版本号 2013.09.18 iOS 7.0 2013.09.20 iOS 7.0.1 2013.09.26 iOS 7.0.2 2013.10.22 iOS 7.0.3 2013.11.14 iOS 7.0.4 2014.01.29 iOS 7.0.5 2014.02.21 iOS 7.0.6 2014.03.10 iOS 7
  • 移动端调试(ios手机safari+chrome调试(windows))

    万次阅读 热门讨论 2018-03-05 16:21:59
    1、ios手机连接到pc设置手机safari 设置-》safari-》高级-》打开web检查器 (授权调试功能)2.、安装ios_webkit_debug_proxy根据文档,在windows下,首先需要安装scoop,而安装scoop需要电脑里有powershell。win10...
1 2 3 4 5 ... 20
收藏数 134,336
精华内容 53,734
关键字:

ios13