iOS 橫屏項(xiàng)目打開相機(jī)崩潰問題解決辦法

不管是哪種方式(JS與OC交互調(diào)用原生的方法,H5input標(biāo)簽)打開相機(jī),只要打開相機(jī)的時(shí)候,app項(xiàng)目是橫屏的(在xcode中只支持了橫屏方向)打開相機(jī),發(fā)生崩潰了,用下面的方法都可以解決。

我目前發(fā)生崩了的機(jī)型是x以上機(jī)型,不分iOS系統(tǒng)。 但是我面試的時(shí)候,有個(gè)面試官說他們公司所有機(jī)型在我上述場景中,都會崩潰。

報(bào)錯(cuò)日志:Supported orientations has no common orientation with the application, and [CAMViewfinderViewController shouldAutorotate] is returning YES

報(bào)錯(cuò)截圖:
圖片.png

崩潰分析:由于項(xiàng)目設(shè)置只支持了橫屏,相機(jī)默認(rèn)為豎屏打開。但是相機(jī)類[CAMViewfinderViewController shouldAutorotate] 返回了YES,也就是說:在這個(gè)類中,界面支持旋轉(zhuǎn),但是系統(tǒng)沒有豎屏選項(xiàng),支持旋轉(zhuǎn)就造成沖突,所以崩潰了。那么我們就要將這個(gè)[CAMViewfinderViewController shouldAutorotate] 返回NO.

實(shí)踐以input標(biāo)簽打開為例:(測試了JS調(diào)用原生方法打開相機(jī),直接在原生按鈕點(diǎn)擊事件里面打開相機(jī))

因?yàn)橛胕nput標(biāo)簽打開相機(jī),沒有辦法獲取到打開相機(jī)的點(diǎn)擊事件,所以沒有辦法用通知那種方法來通知AppDelegate的代理方法來改變屏幕支持的旋轉(zhuǎn)方向。所以我就用了分類+方法交換的方式來解決問題。

利用runtime的方法交換,實(shí)現(xiàn)當(dāng)系統(tǒng)調(diào)用[CAMViewfinderViewController shouldAutorotate]這個(gè)方法的時(shí)候,我實(shí)現(xiàn)自己的方法,并且返回NO,就可以達(dá)到不崩潰的目的。

下面是分類代碼:

.h文件。啥都沒有

#import <UIKit/UIKit.h>
@interface UIImagePickerController (custom)

@end

.m文件。如下:

#import "UIImagePickerController+custom.h"
#import <objc/runtime.h>

@implementation UIImagePickerController (custom)
static BOOL isDelegateMethodHooked = false;//防止交換方法的邏輯被多次調(diào)用

-(void)viewDidLoad{
    [super viewDidLoad];
    if (isDelegateMethodHooked == NO) {
        Class vc = NSClassFromString(@"CAMViewfinderViewController");
        SEL originalSelector = @selector(shouldAutorotate);
        SEL swizzledSelector = @selector(sjx_stringByAppendingString);
        
        Method originalMethod = class_getInstanceMethod(vc, originalSelector);
        Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
        BOOL didAddMethod = class_addMethod(vc,originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));
        if(didAddMethod) {
            class_replaceMethod([self class],swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }
}

- (BOOL)sjx_stringByAppendingString{
    NSLog(@"2222222");
    return YES;
}


-(void)dealloc{
    isDelegateMethodHooked = YES;
}

看完代碼你可能會想,為什么交換方法的實(shí)現(xiàn)為什么沒有放到load里面,load里面只會調(diào)用一次,這樣也不用使用一個(gè)boll變量來保證代碼只執(zhí)行一次。
這是因?yàn)槲易铋_始放在load方法里面執(zhí)行,會發(fā)現(xiàn)獲取不到CAMViewfinderViewController這個(gè)類。這個(gè)時(shí)候這個(gè)類還咩有被創(chuàng)建,所以不能放在load方法里面執(zhí)行方法交換了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容