iOS 14 的一些適配問題

UIDatePicker

在 iOS 14 開始,UIDatePicker 默認樣式為:

iOS14 默認樣式

而在 iOS14 之前的樣式是

iOS 14 之前默認樣式

同樣的代碼,顯示樣式不一樣

UIDatePicker *datePicer = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 200, self.width, 100)];
datePicer.backgroundColor = [UIColor whiteColor];
[self addSubview:datePicer];

雖然有設置 UIDatePickerframe,但是在 iOS 14 上完全沒有效果,要想在 iOS 14 上顯示跟之前一樣,還要再設置 preferredDatePickerStyle 這個屬性為 UIDatePickerStyleWheels.

/// Request a style for the date picker. If the style changed, then the date picker may need to be resized and will generate a layout pass to display correctly.
@property (nonatomic, readwrite, assign) UIDatePickerStyle preferredDatePickerStyle API_AVAILABLE(ios(13.4)) API_UNAVAILABLE(tvos, watchos);

對于這個屬性,是 UIDatePicker 的樣式,如果樣式發生了更改,則可能需要調整 UIDatePicker 的大小并生成布局展示出來

所以如果只是單單設置了這個屬性還不行,還需要再重新設置 FramebackgroundColor

UIDatePicker *datePicer = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 200, self.width, 100)];
if (@available(iOS 13.4, *)) {
    datePicer.preferredDatePickerStyle = UIDatePickerStyleWheels; // 只設置了 preferredDatePickerStyle 屬性
}
datePicer.backgroundColor = [UIColor whiteColor];
[self addSubview:datePicer];
只設置了preferredDatePickerStyle屬性,并未改變 Frame
CGRect frame = CGRectMake(0, 200, self.width, 100);
UIDatePicker *datePicer = [[UIDatePicker alloc] initWithFrame:CGRectZero];
if (@available(iOS 13.4, *)) {
    datePicer.preferredDatePickerStyle = UIDatePickerStyleWheels; // 只設置了 preferredDatePickerStyle 屬性
}
datePicer.backgroundColor = [UIColor whiteColor];
datePicer.frame = frame;
[self addSubview:datePicer];
設置了樣式并且重新設置了 Frame

UITableViewCell

在 iOS 14 環境下,UITableViewCell 的結構如下:

iOS 14 UITableViewCell 結構

而在 iOS 14 之前,UITableViewCell 的結構如下:

iOS 14 之前 UITableViewCell 結構

對比可以發現,iOS14 多了一個 _UISystemBackgroundView 和一個子視圖
如果我們在cell 中創建新的 UI 控件,然后直接添加到 cell 中,所以在 iOS14 下,如果直接講 UI 空間添加到 cell 上面,默認會放在 contentView 下面,如果有一些交互事件,這時候是無法響應的,因為被 contentView 給擋住了,所以需要添加到 contentView 上面.

UIPageControl

在之前,如果想要修改 UIPageControl 默認圖片和選中圖片,需要按照如下方式修改:

[_pageControl setValue:_pageIndicatorImage forKeyPath:@"pageImage"];
[_pageControl setValue:_currentPageIndicatorImage forKeyPath:@"currentPageImage"];

但是在 iOS14 開始,這樣修改直接一個異常,提示調用過時的私有方法:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Call to obsolete private method -[UIPageControl _setPageImage:]'
異常信息
UIPageControl *pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, 100, self.view.width, 30)];
pageControl.backgroundColor = [UIColor orangeColor];
pageControl.numberOfPages = 6;
    
if (@available(iOS 14.0, *)) {
    pageControl.backgroundStyle = UIPageControlBackgroundStyleMinimal;
    pageControl.allowsContinuousInteraction = false;
    pageControl.preferredIndicatorImage = [UIImage imageNamed:@"page_currentImage"];
    // 目前發現只能通過這樣的方式去設置當前選中的圖片顏色
    pageControl.currentPageIndicatorTintColor = [UIColor redColor];
    [pageControl setIndicatorImage:[UIImage imageNamed:@"live"] forPage:2];
} else {
    [pageControl setValue:[UIImage imageNamed:@"page_image"] forKeyPath:@"pageImage"];
    [pageControl setValue:[UIImage imageNamed:@"page_currentImage"] forKeyPath:@"currentPageImage"];
}
[self.view addSubview:pageControl];

運行不同環境

iOS 14 之前環境

UIPageControl 在 iOS 14 之前樣式

iOS 14 之后環境

iOS 14 之后環境

CALayer 的 mask

公司所在的項目中,聊天界面利用CALayermask方式將背景弄成一個氣泡的樣式,在 iOS 14 之前是好的,但是在 iOS 14 上就顯示不出來了.具體的方式是將一個氣泡圖片,用一個 UIImageView 加載出來,然后將這個氣泡的 ImageViewlayer 作為一個遮罩,放在圖片消息上面去.
代碼類似下面的:

UIImageView *imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"calendar"];
imageView.size = CGSizeMake(200, 200);
imageView.center = self.center;
[self addSubview:imageView];
    
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 150, 80)];
imgView.image = [UIImage imageNamed:@"green_pop"];
imageView.layer.mask = imgView.layer;

以上代碼運行結果,在不同的環境下,顯示出來的效果不一樣

iOS14 環境下運行結果.png
iOS12.4環境下運行結果.png

iOS14 顯示不出來,但是在 iOS12.4 卻能顯示出來

后面在添加到 imageView.layer.mask 之前,將 imgView 添加到某個視圖上去,發現在 iOS 14 上又能顯示出來,所以想是不是在 iOS14 上的渲染邏輯發生了改變

將 imgView 添加到某個視圖上
UIImageView *imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"calendar"];
imageView.size = CGSizeMake(200, 200);
imageView.center = self.center;
[self addSubview:imageView];

UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 150, 80)];
imgView.image = [UIImage imageNamed:@"green_pop"];
[imageView addSubview:imgView];
imageView.layer.mask = imgView.layer;

其實可以直接使用 layercontent 進行設置圖片

將圖片賦值到 content.png
UIImageView *imageView = [UIImageView new];
imageView.image = [UIImage imageNamed:@"calendar"];
imageView.size = CGSizeMake(200, 200);
imageView.center = self.center;
[self addSubview:imageView];
CALayer *maskLayer = [[CALayer alloc] init];
maskLayer.frame = CGRectMake(0, 0, 180, 90);
maskLayer.contents = (__bridge id)[UIImage imageNamed:@"green_pop"].CGImage;
imageView.layer.mask = maskLayer;

這樣也能顯示出來

AssetsLibrary

AssetsLibrary 在 iOS9 已經開始被棄用了,但是一些老的項目還在使用這個庫進行相冊訪問,經過測試,同樣的代碼,在 iOS 14 下拿到相冊中的圖片之后,獲取圖片的大小已經獲取不到了

iOS14 之前獲取圖片大小情況

iOS14之前AssetsLibrary獲取圖片大小

iOS 14 獲取圖片大小情況

iOS14 AssetsLibrary獲取圖片大小

PHPickerViewController 的使用

在 iOS14 增加了一個 PHPickerViewController 對相冊的訪問,替代 UIImagePickerController.

我們可以在 UIImagePickerController.h 文件中看到,蘋果推薦使用 PHPickerViewController 去訪問相冊

UIImagePickerController替換提示.jpg

首先,創建一個 PHPickerConfiguration 進行一些配置

PHPickerConfiguration *configuration = [PHPickerConfiguration new];
configuration.filter = [PHPickerFilter imagesFilter]; // 設置所選的類型,這里設置是圖片,默認是 nil,設置成 nil 則代表所有的類型都顯示出來(包括 視頻/LivePhoto )
configuration.selectionLimit = 10; // 設置可選擇的最大數,默認為 1

創建 PHPickerViewController , 并進行跳轉

PHPickerViewController *picker = [[PHPickerViewController alloc] initWithConfiguration:configuration];
picker.delegate = self;
picker.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:picker animated:YES completion:nil];

實現代理方法 picker:didFinishPicking:results

- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results  API_AVAILABLE(ios(14)){
    
    [picker dismissViewControllerAnimated:YES completion:nil];
    if (!results || !results.count) return;
    // 遍歷獲取到的結果
    for (PHPickerResult *result in results) {
        NSItemProvider *itemProvider = result.itemProvider;
        if ([itemProvider canLoadObjectOfClass:UIImage.class]) {
            [itemProvider loadObjectOfClass:UIImage.class
                          completionHandler:^(__kindof id<NSItemProviderReading>  _Nullable object, NSError * _Nullable error) {
                // 取出圖片
                if (!error && object && [object isKindOfClass:UIImage.class]) {
                    NSLog(@"%@", object);
                }
            }];
        }
    }
}
PHPickerViewController的使用.gif
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • UIDatePicker 在 iOS 14 開始,UIDatePicker 默認樣式為: 而在 iOS14 之前的...
    王家小雷閱讀 990評論 0 4
  • 又是一年蘋果發布會,蘋果更新了新版本的系統iOS14。就我個人來說的話系統耗電有優化,小程序類似部件化APP體驗也...
    尼古拉斯佩思閱讀 4,097評論 0 9
  • 1、UIDatePicker iOS14 UIDatePicker新增加了一個UI樣式 tvos watchos ...
    480a52903ce5閱讀 2,499評論 0 3
  • iOS14 的適配,很重要的一環就集中在和方面。 在 iOS13 及以前,當用戶首次訪問應用程序時,會被要求開放大...
    vicentwyh閱讀 2,846評論 0 5
  • 久違的晴天,家長會。 家長大會開好到教室時,離放學已經沒多少時間了。班主任說已經安排了三個家長分享經驗。 放學鈴聲...
    飄雪兒5閱讀 7,550評論 16 22