iOS開發(fā)--iOS 12.1系統(tǒng)tabBar按鈕偏移錯(cuò)位問題

現(xiàn)在我們使用的APP框架,大部分都是 UINavigationController + UITabBarController的模式。如果使用的是默認(rèn)的UITabBar磨砂效果,而且在pushViewController時(shí),設(shè)置了hidesBottomBarWhenPushed屬性為true ,則在iOS 12.1系統(tǒng),使用手勢返回的時(shí)候,就會觸發(fā)UITabBarButton 被設(shè)置frame.size 為 (0, 0)的錯(cuò)誤布局, 導(dǎo)致的tabBar上的圖標(biāo)和文字偏移錯(cuò)位。

案例
extension UINavigationController {
    @objc open func ck_pushViewController(_ viewController: UIViewController, animated: Bool) {
        viewController.hidesBottomBarWhenPushed = true
        self.ck_pushViewController(viewController, animated: animated)
        if self.viewControllers.count == 1 {
            viewController.hidesBottomBarWhenPushed = false
        }
    }
}

方案一:修改tabBarisTranslucent透明度(不推薦)或添加背景圖片

1、可以通過修改tabBar的透明度達(dá)到我們想要的效果:

if #available(iOS 12.1, *) {
  UITabBar.appearance().isTranslucent = false
} else {
  UITabBar.appearance().isTranslucent = true
}

但是這個(gè)會引入其它的問題:

  • (1)tabBar想保留原來的磨砂效果;
  • (2)會影響tableView的布局,底部間距多了tabBar的高度;

所以這種方式pass

2、可以統(tǒng)一給tabBar添加背景圖片,則不會有這個(gè)問題。

方案二:使用runtime過濾UITabBarButtonframe設(shè)置(推薦)

為了達(dá)到既不修改原先的設(shè)計(jì)又達(dá)到解決這個(gè)問題,我這邊通過交換UITabBarButtonsetFrame方法,過濾一些錯(cuò)誤的大小設(shè)置,來達(dá)到我們的目的,這里提供了OCSwift兩個(gè)版本的代碼,如下:

  • OC

添加UIView的分類,并在+load方法中,交換UITabBarButtonsetFrame方法,過濾錯(cuò)誤的大小

#import <UIKit/UIKit.h>

@interface UIView (CKTabBarItem)

@end
#import "UIView+CKTabBarItem.h"
#import <objc/runtime.h>

@implementation UIView (CKTabBarItem)

+ (void)load
{
    if (@available(iOS 12.1, *)) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Class class = NSClassFromString(@"UITabBarButton");
            SEL originalSelector  = @selector(setFrame:);
            SEL swizzledSelector  = @selector(ck_setFrame:);
            Method originalMethod = class_getInstanceMethod(class, originalSelector);
            Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
            BOOL isSuccess = class_addMethod(class,
                                             originalSelector,
                                             method_getImplementation(swizzledMethod),
                                             method_getTypeEncoding(swizzledMethod));
            if (isSuccess) {
                class_replaceMethod(class,
                                    swizzledSelector,
                                    method_getImplementation(originalMethod),
                                    method_getTypeEncoding(originalMethod));
            } else {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        });
    }
}

- (void)ck_setFrame:(CGRect)frame
{
    if (!CGRectIsEmpty(self.frame)) {
        if (CGRectIsEmpty(frame)) {
            return;
        }
        frame.size.height = MAX(frame.size.height, 48.0);
    }
    [self ck_setFrame: frame];
}

@end
  • Swift

Swift4 不支持dispatch_once,靜態(tài)變量默認(rèn)用dispatch_once初始化,可以替代dispatch_once的實(shí)現(xiàn)

import UIKit

extension UIView {
    
    /// Swift4 不支持dispatch_once,靜態(tài)變量默認(rèn)用dispatch_once初始化,可以替代dispatch_once的實(shí)現(xiàn)
    private static let swizzlingTabBarButtonFrame: Void = {
        guard #available(iOS 12.1, *) else {
            return
        }
        guard let cls = NSClassFromString("UITabBarButton") else {
            return
        }
        let originalSelector = #selector(setter: UIView.frame)
        let swizzledSelector = #selector(UIView.ck_setFrame)
        guard let originalMethod = class_getInstanceMethod(cls, originalSelector) else {
            return
        }
        guard let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector) else {
            return
        }
        let isSuccess = class_addMethod(cls,
                                        originalSelector,
                                        method_getImplementation(swizzledMethod),
                                        method_getTypeEncoding(swizzledMethod))
        if (isSuccess) {
            class_replaceMethod(cls,
                                swizzledSelector,
                                method_getImplementation(originalMethod),
                                method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }()
    
    @objc func ck_setFrame(frame: CGRect) {
        var newFrame: CGRect = frame
        if !self.frame.isEmpty {
            guard !newFrame.isEmpty else {
                return
            }
            newFrame.size.height = newFrame.size.height > 48.0 ? newFrame.size.height : 48.0
        }
        self.ck_setFrame(frame: newFrame)
    }
    
    open class func swizzledTabBarButtonFrame() {
        UIView.swizzlingTabBarButtonFrame
    }

}

Swift因?yàn)闆]有+load方法,所以需要手動去觸發(fā),我這里直接放到UIApplicationDelegate的代理方法中。

// MARK: - <UIApplicationDelegate>
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // ...

        // 處理iOS 12.1系統(tǒng)tabBar圖標(biāo)偏移錯(cuò)位問題
        UIView.swizzledTabBarButtonFrame()

        return true
    }

如果有任何疑問,歡迎留言或私信交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,401評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,011評論 3 413
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,263評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,543評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,323評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,874評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,968評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,095評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,605評論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,551評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,720評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,242評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,961評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,358評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,612評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,330評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,690評論 2 370