iOS 13 適配總結(jié)

自從6月份的 WWDC大會(huì)展示了iOS 13的新版本之后溃睹,廣大開發(fā)者朋友又面臨著新一輪的系統(tǒng)升級適配工作;隨著蘋果9月份發(fā)布會(huì)腳步的臨近锌俱,對公司的App升級適配勢在必行。

iOS 13發(fā)現(xiàn)問題回顧

  • 禁止用戶獲取或直接設(shè)置私有屬性:調(diào)用setValue:forKeyPath:负蚊、valueForKey:方法會(huì)引起App崩潰。例如:UITextField修改_placeholderLabel.textColor颓哮、UISearchBar修改_searchField
  • UITextFieldleftViewrightView調(diào)整:部分視圖位置顯示異常
  • UITabBar部分調(diào)整:UITabBarItem播放gif顯示比例有問題家妆;UITabBarItem只顯示圖片時(shí),圖片位置偏移冕茅;Badge文字顯示偏大
  • UITableViewcell選中樣式失效
  • 第三方SDK的閃退兼容問題
將所有問題歸納總結(jié)伤极,得出以下幾點(diǎn)解決方案的建議和示例代碼,記錄一下

1. UITextField

  • 設(shè)置placeholder引起的閃退

    iOS 13之前姨伤,設(shè)置placeholder有三種方案:

    • 基于KVO簡單粗暴的修改私有屬性(iOS 13禁用)

      [textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
      [textField setValue:[UIFont boldSystemFontOfSize:16] forKeyPath:@"_placeholderLabel.font"];
      
    • 設(shè)置attributedPlaceholder屬性

      textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"placeholder" attributes:@{NSForegroundColorAttributeName: [UIColor darkGrayColor], NSFontAttributeName: [UIFont systemFontOfSize:13]}];
      
    • 重寫UITextField子類的drawPlaceholderInRect:方法

      - (void)drawPlaceholderInRect:(CGRect)rect {
      
        [self.placeholder drawInRect:rect withAttributes:@{NSForegroundColorAttributeName: [UIColor purpleColor], NSFontAttributeName: [UIFont systemFontOfSize:13]}];
      }
      

    適配iOS 13時(shí)哨坪,可根據(jù)實(shí)際情況選取后兩種方案解決閃退問題。如果項(xiàng)目中重復(fù)使用了同一種UITextField的樣式乍楚,推薦使用第三種方案当编,創(chuàng)建UITextField的子類。

    修改建議: 采用第二種方案徒溪,創(chuàng)建UITextFieldCategory文件忿偷,里面封裝好修改placeholder的方法,后續(xù)修改都可統(tǒng)一直接調(diào)用這些方法

    // UITextField+CIPlaceholder.m文件
    
    #import "UITextField+CIPlaceholder.h"
    
    @implementation UITextField (CIPlaceholder)
    
    - (void)setPlaceholderFont:(UIFont *)font {
    
        [self setPlaceholderColor:nil font:font];
    }
    
    - (void)setPlaceholderColor:(UIColor *)color {
    
        [self setPlaceholderColor:color font:nil];
    }
    
    - (void)setPlaceholderColor:(nullable UIColor *)color font:(nullable UIFont *)font {
    
        if ([self checkPlaceholderEmpty]) {
            return;
        }
    
        NSMutableAttributedString *placeholderAttriString = [[NSMutableAttributedString alloc] initWithString:self.placeholder];
        if (color) {
            [placeholderAttriString addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(0, self.placeholder.length)];
        }
        if (font) {
            [placeholderAttriString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.placeholder.length)];
        }
    
        [self setAttributedPlaceholder:placeholderAttriString];
    }
    
    - (BOOL)checkPlaceholderEmpty {
    
        return IsStrEmpty(self.placeholder);
    }
    
    @end
    
  • 子視圖leftViewrightView顯示異常

    修改建議:將需要顯示的視圖包裝在一個(gè)簡單的UIView中或者在需要顯示的自定義視圖子類里词渤,實(shí)現(xiàn)systemLayoutSizeFittingSize:方法

    //  示例代碼
    - (void)buildTextField {
        UITextField *textField;
        //  iOS 13之前
        textField.rightView = [self buildButtonForRightView];
        //  iOS 13之后
        textField.rightView = [self buildTextFieldRightView];
    }
    
    //  iOS 13之前正常
    - (UIButton *)buildButtonForRightView {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        //  do somethings
        return button;
    }
    
    • 將顯示的視圖包裝在一個(gè)簡單的UIView

      //  iOS 13之后需要封裝一層
      - (UIView *)buildTextFieldRightView {
          UIButton *button = [self buildButtonForRightView];
          //  封裝一層
          UIView *rightView = [[UIView alloc] initWithFrame:button.bounds];
          [rightView addSubview:button];
      
          return rightView;
      }
      
    • 在需要顯示的自定義視圖子類里牵舱,實(shí)現(xiàn)systemLayoutSizeFittingSize:方法

      //  CICustomButton.m文件
      #import "CICustomButton.h"
      
      @implementation CICustomButton
      
      //  iOS 13之后需要實(shí)現(xiàn)該方法
      - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize {
          return CGSizeMake(100, 30);
      }
      
      @end
      
      ------------------------
      //  Build TextFiled頁面
      
      //  iOS 13之后串绩,修改UIButton為CICustomButton
      - (UIButton *)buildButtonForRightView {
          UIButton *button = [CICustomButton buttonWithType:UIButtonTypeRoundedRect];
          //  do somethings
          return button;
      }
      

2. UISearchBar

通過valueForKey缺虐、setValue: forKeyPath獲取和設(shè)置私有屬性程序崩潰
//  修改searchBar的textField
UISearchBar *searchBar = [[UISearchBar alloc] init];

//  iOS 13之前可直接獲取,然后修改textField相關(guān)屬性
UITextField *searchTextField = [searchBar valueForKey:@"_searchField"];

修改建議:可遍歷searchBar的所有子視圖礁凡,找到指定的UITextField類型的子視圖高氮,根據(jù)上述UITextField的相關(guān)方法修改屬性;也可根據(jù)UITextField自定義UISearchBar的顯示

//  UISearchBar+CIChangePrivateSubviews.m文件

//  修改SearchBar的系統(tǒng)私有子視圖

#import "UISearchBar+CIChangePrivateSubviews.h"

@implementation UISearchBar (CIChangePrivateSubviews)

/// 修改SearchBar系統(tǒng)自帶的TextField
- (void)changeSearchTextFieldWithCompletionBlock:(void(^)(UITextField *textField))completionBlock {

    if (!completionBlock) {
        return;
    }

    UITextField *textField = [self findTextFieldWithView:self];
    if (textField) {
        completionBlock(textField);
    }
}

/// 遞歸遍歷UISearchBar的子視圖顷牌,找到UITextField
- (UITextField *)findTextFieldWithView:(UIView *)view {

    for (UIView *subview in view.subviews) {
        if ([subview isKindOfClass:[UITextField class]]) {
            return (UITextField *)subview;
        }else if (!IsArrEmpty(subview.subviews)) {
            return [self findTextFieldWithView:subview];
        }
    }
    return nil;
}

@end

3. UITableView

iOS 13設(shè)置cell.contentView.backgroundColor會(huì)影響cellselected或者highlighted時(shí)的效果

例如:如果設(shè)置cell.selectedBackgroundView為自定義選中背景視圖剪芍,并修改cell.contentView.backgroundColor為某種不透明顏色;contentView就會(huì)遮蓋cell.selectedBackgroundView窟蓝,最終導(dǎo)致無法看到自定義的selectedBackgroundView效果罪裹。

修改建議:不設(shè)置contentView.backgroundColor時(shí),默認(rèn)值為nil运挫;改為直接設(shè)置cell本身背景色

//  自定義cell.m文件

//  iOS 13之前正常
self.contentView.backgroundColor = [UIColor blueColor];
//  iOS 13改為
self.backgroundColor = [UIColor blueColor];

備注:iOS 13UITableView還做了一些其他的修改状共,詳細(xì)內(nèi)容可查閱最底部 參考內(nèi)容1,整個(gè)網(wǎng)頁搜索UITableViewCell即可

4. UITabbar

  • Badge文字顯示不正常

    Badge默認(rèn)字體大小谁帕,iOS 13從之前13號字體變?yōu)?7號字體

    修改建議:在初始化TabBarController時(shí)峡继,在需要顯示BadgeViewController處調(diào)用setBadgeTextAttributes:forState:方法

    //  iOS 13需要添加
    if (@available(iOS 13, *)) {
        [viewController.tabBarItem setBadgeTextAttributes:@{NSFontAttributeName: CI_FONT_13} forState:UIControlStateNormal];
        [viewController.tabBarItem setBadgeTextAttributes:@{NSFontAttributeName: CI_FONT_13} forState:UIControlStateSelected];
    }
    
  • 字體顏色異常

    iOS 13不設(shè)置self.tabBar.barTintColor = [UIColor clearColor];時(shí)字體顏色會(huì)顯示藍(lán)色,iOS 13之前設(shè)置與否無影響

    修改建議:設(shè)置tabBar.barTintColor顏色為UIColor clearColor]

    //  自定義TabBarController.m文件
    - (void)viewDidLoad {
      [super viewDidLoad];
    
      self.tabBar.barTintColor = [UIColor clearColor];
      //  整個(gè)項(xiàng)目只有一種TabBarController時(shí)或者多個(gè)相同風(fēng)格時(shí)可設(shè)置全局風(fēng)格(其他情況不推薦)
      // [[UITabBar appearance] setBarTintColor:[UIColor clearColor]];
    }
    

5. UITabBarItem

  • 播放gif匈挖,設(shè)置ImageView圖片時(shí)注意設(shè)置圖片的scale比例
    //  根據(jù)路徑取gif數(shù)據(jù)
    NSData *data = [NSData dataWithContentsOfFile:path];
    CGImageSourceRef gifSource = CGImageSourceCreateWithData(CFBridgingRetain(data), nil);
    size_t gifCount = CGImageSourceGetCount(gifSource);
    CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i,NULL);
    
    //  iOS 13之前
    UIImage *image = [UIImage imageWithCGImage:imageRef]
    //  iOS 13需要注意:添加scale比例(該imageView將展示該動(dòng)圖效果)
    UIImage *image = [UIImage imageWithCGImage:imageRef scale:image.size.width / CGRectGetWidth(imageView.frame) orientation:UIImageOrientationUp];
    
    CGImageRelease(imageRef);
    
  • 播放gif碾牌,需找到設(shè)置的ImageView視圖
    //  UITabBarItem+CIChangePrivateSubviews.m文件
    //  修改TabbarItem系統(tǒng)私有子視圖
    
    #import "UITabBarItem+CIChangePrivateSubviews.h"
    
    @implementation UITabBarItem (CIChangePrivateSubviews)
    
    /// 修改UITabBarSwappableImageView
    - (void)changeSwappableImageViewWithCompletionBlock:(void(^)(UIImageView *imageView))completionBlock {
    
        if (!completionBlock) {
            return;
        }
    
        UIView *tabBarButton = [self valueForKey:@"view"];
        for (UIView *subviews in tabBarButton.subviews) {
            if ([NSStringFromClass([subviews class]) isEqualToString:@"UITabBarSwappableImageView"]) {
                completionBlock((UIImageView *)subviews);
            }
        }
    }
    
  • 只顯示圖片康愤,沒有文字時(shí)圖片的位置調(diào)整

    iOS 13不需要調(diào)整imageInsets,圖片會(huì)自動(dòng)居中顯示舶吗,如果設(shè)置會(huì)造成圖片位置有些許偏移

    修改建議:添加版本限制條件征冷,只在iOS 13之前調(diào)用設(shè)置方法

    if (IOS_VERSION < 13.0) {
        viewController.tabBarItem.imageInsets = UIEdgeInsetsMake(5, 0, -5, 0);
    }
    

6. 彈出ViewController樣式變化

模態(tài)展示UIModalPresentationStyle類型新增UIModalPresentationAutomatic API_AVAILABLE(ios(13.0)) = -2

用戶調(diào)用presentViewController:animated:completion:方法彈出視圖時(shí),iOS 13效果變化更炫酷誓琼,可以在iOS 13系統(tǒng)App中體驗(yàn)到這種變化资盅;
如果不希望使用這種效果,可利用Runtime方法踊赠,恢復(fù)設(shè)置modalPresentationStyleUIModalPresentationFullScreen

//  UIViewController+CIChangePresentStyle.m文件

#import "UIViewController+CIChangePresentStyle.h"

@implementation UIViewController (CIChangePresentStyle)

+ (void)load {

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        //替換方法
        SEL originalSelector = @selector(presentViewController:animated:completion:);
        SEL swizzledSelector = @selector(ci_presentViewController:animated:completion:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);;
        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(swizzledMethod),
                        method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));

        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

- (void)ci_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {

    viewControllerToPresent.modalPresentationStyle = UIModalPresentationFullScreen;
    [self ci_presentViewController:viewControllerToPresent animated:flag completion:completion];
}

@end

7. 第三方SDK相關(guān)

  • 友盟社會(huì)化分享SDK:使用“新浪微博完整版”閃退

    替換新浪微博最新的SDK版本Github地址呵扛,友盟集成SDK暫時(shí)未更新

  • 高德地圖相關(guān)等其他第三方SDK更新

    查看相關(guān)Github或者官方SDK下載地址,更新最新的SDK即可

以上就是適配iOS 13的一些修改建議筐带。如果各位朋友發(fā)現(xiàn)有一些新問題和解決方案今穿,可以在評論區(qū)留言,希望大家暢所欲言伦籍,共同發(fā)現(xiàn)并幫助解決問題蓝晒。

參考內(nèi)容

  1. iOS & iPadOS 13 Beta 6 Release Notes
  2. 友盟+推出全新SDK,適配iOS 13
  3. 新浪微博 iOS SDK
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帖鸦,一起剝皮案震驚了整個(gè)濱河市芝薇,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌作儿,老刑警劉巖洛二,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異攻锰,居然都是意外死亡晾嘶,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門娶吞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垒迂,“玉大人,你說我怎么就攤上這事妒蛇』希” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵绣夺,是天一觀的道長吏奸。 經(jīng)常有香客問我,道長乐导,這世上最難降的妖魔是什么苦丁? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮物臂,結(jié)果婚禮上旺拉,老公的妹妹穿的比我還像新娘产上。我一直安慰自己,他們只是感情好蛾狗,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布晋涣。 她就那樣靜靜地躺著,像睡著了一般沉桌。 火紅的嫁衣襯著肌膚如雪谢鹊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天留凭,我揣著相機(jī)與錄音佃扼,去河邊找鬼。 笑死蔼夜,一個(gè)胖子當(dāng)著我的面吹牛兼耀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播求冷,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼瘤运,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了匠题?” 一聲冷哼從身側(cè)響起拯坟,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎韭山,沒想到半個(gè)月后郁季,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掠哥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年巩踏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秃诵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片续搀。...
    茶點(diǎn)故事閱讀 38,566評論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖菠净,靈堂內(nèi)的尸體忽然破棺而出禁舷,到底是詐尸還是另有隱情,我是刑警寧澤毅往,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布牵咙,位于F島的核電站,受9級特大地震影響攀唯,放射性物質(zhì)發(fā)生泄漏洁桌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一侯嘀、第九天 我趴在偏房一處隱蔽的房頂上張望另凌。 院中可真熱鬧谱轨,春花似錦、人聲如沸吠谢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽工坊。三九已至献汗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間王污,已是汗流浹背罢吃。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昭齐,地道東北人刃麸。 一個(gè)月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像司浪,于是被迫代替她去往敵國和親泊业。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容