本文作為自己準備適配iOS15所用,在開始適配之前,先去學習各位同學的文章,記錄在此備用。
1、導航欄UINavigationBar
從 iOS 15 開始,UINavigationBar、UIToolbar 和 UITabBar 在控制器中關聯滾動視圖頂部或底部時使用
在iOS15中,UINavigationBar默認是透明的,有滑動時會逐漸變為模糊效果,可以通過改變UINavigationBar.scrollEdgeAppearance屬性直接變為模糊效果、配置相關屬性-背景、字體等
if #available(iOS 15.0, *) { //UINavigationBarAppearance屬性從iOS13開始
let navBarAppearance = UINavigationBarAppearance()
// 背景色
navBarAppearance.backgroundColor = UIColor.clear
// 去掉半透明效果
navBarAppearance.backgroundEffect = nil
// 去除導航欄陰影(如果不設置clear,導航欄底下會有一條陰影線)
navBarAppearance.shadowColor = UIColor.clear
// 字體顏色
navBarAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
self.navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
}
用新xcode13編譯工程后,導航欄的問題比較明顯,調試之后發現是UINavigationBar部分屬性的設置在iOS15上是無效的
- 舊代碼
navigationBar.setBackgroundImage(UIColor.clear.image, for: .default)
// 導航欄背景,主題色是綠色
navigationBar.barTintColor = UIColor.theme
// 默認不透明
navigationBar.isTranslucent = false
// 著色,讓返回按鈕圖片渲染為白色
navigationBar.tintColor = UIColor.white
// 導航欄文字
navigationBar.titleTextAttributes = [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18),
NSAttributedString.Key.foregroundColor: UIColor.white
]
run起來后發現,導航欄顏色設置沒有作用,呈現是白色,字體顏色也沒有生效,呈現黑色,查看導航欄特性API:UINavigationBarAppearance后發現,iOS15navigationBar的相關屬性設置要通過實例UINavigationBarAppearance來實現,UINavigationBarAppearance是iOS13更新的API,應該有人已經在用,我們的應用兼容iOS10以上,對于導航欄的設置還沒有使用UINavigationBarAppearance,如今在iOS15上失效,所以對于呈現的問題,做如下適配:
- 新代碼
if #available(iOS 15, *) {
let app = UINavigationBarAppearance.init()
app.configureWithOpaqueBackground() // 重置背景和陰影顏色
app.titleTextAttributes = [
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18),
NSAttributedString.Key.foregroundColor: UIColor.white
]
app.backgroundColor = UIColor.theme // 設置導航欄背景色
app.shadowImage = UIColor.clear.image // 設置導航欄下邊界分割線透明
navigationBar.scrollEdgeAppearance = app // 帶scroll滑動的頁面
navigationBar.standardAppearance = app // 常規頁面。描述導航欄以標準高度顯示時要使用的外觀屬性。
}
關于navigationBar背景圖片失效的問題:
老代碼:
navigationBar.setBackgroundImage(img, for: .default)
iOS15代碼:
appearance.backgroundImage = img;
appearance.backgroundImageContentMode = UIViewContentModeScaleToFill;
navigationBar.standardAppearance = appearance;
tabbar跟navigationBar同理設置即可。
2、TableView
從 iOS 15 開始,TableView 增加sectionHeaderTopPadding屬性,默認情況sectionHeaderTopPadding會有22個像素的高度,及默認情況,TableView section header增加22像素的高度
/// Padding above each section header. The default value is `UITableViewAutomaticDimension`.
@available(iOS 15.0, *)
open var sectionHeaderTopPadding: CGFloat
if #available(iOS 15.0, *) {
self.tableView.sectionHeaderTopPadding = 0
}
3、Image
在iOS15中,UIImageWriteToSavedPhotosAlbum存儲圖片之后的回調不再返回圖片了,會返回nil,如果在回調方法里面操作image有可能會直接Crash,目前的解決辦法聲明一個全局image去記錄,后面再去操作
self.image = image;
UIImageWriteToSavedPhotosAlbum(image,self,@selector(image:didFinishSavingWithError:contextInfo:), NULL);
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
// self.image doing...
}
4、UITabbar
tabbar的問題和navigationBar的問題屬于同一類,tabbar背景顏色設置失效,字體設置失效,陰影設置失效問題
- 舊代碼
self.tabBar.backgroundImage = UIColor.white.image
self.tabBar.shadowImage = UIColor.init(0xEEEEEE).image
item.setTitleTextAttributes(norTitleAttr, for: .normal)
item.setTitleTextAttributes(selTitleAttr, for: .selected)
首先是背景色設置失效,讓我就想到了navigationbar的問題,所以沒有查api了
直接用UITabBarAppearance來設置,
- 新代碼
if #available(iOS 15, *) {
let bar = UITabBarAppearance.init()
bar.backgroundColor = UIColor.white
bar.shadowImage = UIColor.init(0xEEEEEE).image
let selTitleAttr = [
NSAttributedString.Key.font: itemFont,
NSAttributedString.Key.foregroundColor: UIColor.theme
]
bar.stackedLayoutAppearance.selected.titleTextAttributes = selTitleAttr // 設置選中attributes
self.tabBar.scrollEdgeAppearance = bar
self.tabBar.standardAppearance = bar//與navi同理
}
5、對狀態編程的支持:UICellConfigurationState;UICollectionViewCell、UITableViewCell都支持狀態變化時的block執行了。
6、UICollectionViewLayout支持自動高度;AutomaticDimension
7、json解析支持json5了
8、增加UISheetPresentationController,通過它可以控制 Modal 出來的 UIViewController 的顯示大小,且可以通過拖拽手勢在不同大小之間進行切換。只需要在跳轉的目標 UIViewController 做如下處理:
if let presentationController = presentationController as? UISheetPresentationController {
// 顯示時支持的尺寸
presentationController.detents = [.medium(), .large()]
// 顯示一個指示器表示可以拖拽調整大小
presentationController.prefersGrabberVisible = true
}
9、UIButton支持更多配置。UIButton.Configuration是一個新的結構體,它指定按鈕及其內容的外觀和行為。它有許多與按鈕外觀和內容相關的屬性,如cornerStyle、baseForegroundColor、baseBackgroundColor、buttonSize、title、image、subtitle、titlePadding、imagePadding、contentInsets、imagePlacement等。
// Plain
let plain = UIButton(configuration: .plain(), primaryAction: nil)
plain.setTitle("Plain", for: .normal)
// Gray
let gray = UIButton(configuration: .gray(), primaryAction: nil)
gray.setTitle("Gray", for: .normal)
// Tinted
let tinted = UIButton(configuration: .tinted(), primaryAction: nil)
tinted.setTitle("Tinted", for: .normal)
// Filled
let filled = UIButton(configuration: .filled(), primaryAction: nil)
filled.setTitle("Filled", for: .normal)
10、推出CLLocationButton用于一次性定位授權,該內容內置于CoreLocationUI模塊,但如果需要獲取定位的詳細信息仍然需要借助于CoreLocation。
let locationButton = CLLocationButton()
// 文字
locationButton.label = .currentLocation
locationButton.fontSize = 20
// 圖標
locationButton.icon = .arrowFilled
// 圓角
locationButton.cornerRadius = 10
// tint
locationButton.tintColor = UIColor.systemPink
// 背景色
locationButton.backgroundColor = UIColor.systemGreen
// 點擊事件,應該在在其中發起定位請求
locationButton.addTarget(self, action: #selector(getCurrentLocation), for: .touchUpInside)
11、URLSession 推出支持 async/await 的 API,包括獲取數據、上傳與下載。
// 加載數據
let (data, response) = try await URLSession.shared.data(from: url)
// 下載
let (localURL, _) = try await session.download(from: url)
// 上傳
let (_, response) = try await session.upload(for: request, from: data)
12、系統圖片支持多個層,支持多種渲染模式。
// hierarchicalColor:多層渲染,透明度不同
let config = UIImage.SymbolConfiguration(hierarchicalColor: .systemRed)
let image = UIImage(systemName: "square.stack.3d.down.right.fill", withConfiguration: config)
// paletteColors:多層渲染,設置不同風格
let config2 = UIImage.SymbolConfiguration(paletteColors: [.systemRed, .systemGreen, .systemBlue])
let image2 = UIImage(systemName: "person.3.sequence.fill", withConfiguration: config2)
13、UIImage 新增了幾個調整尺寸的方法。
// preparingThumbnail
UIImage(named: "sv.png")?.preparingThumbnail(of: CGSize(width: 200, height: 100))
// prepareThumbnail,閉包中直接獲取調整后的UIImage
UIImage(named: "sv.png")?.prepareThumbnail(of: CGSize(width: 200, height: 100)) { image in
// 需要回到主線程更新UI
}
// byPreparingThumbnail
await UIImage(named: "sv.png")?.byPreparingThumbnail(ofSize: CGSize(width: 100, height: 100))
比較實用的9,13,之前都是封裝了好多代碼,現在一句話搞定