いまさらながらiOS15のお話!
iOS15がリリースされて結構経ちましたが、先日アプリの対応を入れました。
既存のアプリを動かすとUINavigationBar、UITabBarの色が設定できておらず、スクロールすると色が変わってしまうようになってました。
どうやらスクロールで透過されるようになっており、今までの設定が無効になっているようでした。
通常時、スクロールで端に行った時の設定をそれぞれしないといけいようです。
ということで以下のように修正しました。
全体に設定したい場合
if #available(iOS 15.0, *) {
let appearance = UINavigationBarAppearance()
appearance.titleTextAttributes = [.foregroundColor: UIColor.red]
appearance.backgroundColor = UIColor.white
UINavigationBar.appearance().standardAppearance = appearance
UINavigationBar.appearance().scrollEdgeAppearance = appearance
}
それぞれで設定したい場合は各インスタンスに設定する
if #available(iOS 15.0, *) {
let appearance = UINavigationBarAppearance()
appearance.titleTextAttributes = [.foregroundColor: UIColor.red]
appearance.backgroundColor = UIColor.white
navigationController?.navigationBar.standardAppearance = appearance
navigationController?.navigationBar.scrollEdgeAppearance = appearance
}
UITabBarも同様に全体に設定する場合
if #available(iOS 15.0, *) {
let appearance = UITabBarAppearance()
appearance.backgroundColor = UIColor.white
UITabBar.appearance().standardAppearance = appearance
UITabBar.appearance().scrollEdgeAppearance = appearance
}
それぞれで設定したい場合は各インスタンスに設定する
if #available(iOS 15.0, *) {
let appearance = UITabBarAppearance()
appearance.backgroundColor = UIColor.white
tabBarController?.tabBar.standardAppearance = appearance
tabBarController?.tabBar.scrollEdgeAppearance = appearance
}
上記の設定することで、ちゃんと色が着くようになりました。
毎度のことながら今まで動いていたのが動かなくなる更新がきますね。
せめてターゲットを変えるまではそのまま動いて欲しい・・・
と、これだけでは寂しいのでiOS15で追加された機能を試してみようかと思います。
新機能一覧を見ているとUISheetPresentationControllerなるものが追加されていました。
これはViewControllerを表示する時、半分の位置、全画面位置まで切り替えて表示できるものでした。
似たようなものを実装しているので、これで置き換えられるのかと思い試してみました。
呼び元となるUIViewControllerを用意し、ボタンを押すと別のUIViewControllerを表示するようにします。
この時UIViewControllerに新たにsheetPresentationControllerが追加されているので、ここに色々設定することで半分の位置で止めたりできるようになります。
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium(), .large()]
}
present(viewController, animated: true, completion: nil)

sheet.detents = [.medium(), .large()]で中間と一番上で止められるようになります。
各設定を見てみましょう。
・detents
どの位置に止まるか
medium()かlarge() の二つ
medium()だけにすると中間にしか止まらなくなります。
・selectedDetentIdentifier
どの位置で止まっているか
mediumかlargeの二つ
これを設定することでコードから位置を変えられます。
・largestUndimmedDetentIdentifier
呼び出し元のViewControllerが暗く表示されない最大
何も設定しないと中間位置で暗く表示され、そこをタップするとSheetが閉じます。
mediumを設定すると中間位置でも暗く表示されなく、元のViewControllerの操作ができます。
largeはあまり意味なさそうです。一応最大にした時にちょっと見える部分が暗くなります。
Sheet外をタップして閉じたい時は何も設定しない、Sheet外で操作もしたい時はmediumを設定すると良いです。
・prefersScrollingExpandsWhenScrolledToEdge
Sheet上にスクロールがある場合にtrueにするとSheetが最大まで広がった後にスクロールでき、
falseにすると中間でもスクロールできるようになります。
・prefersGrabberVisible
Sheet上部にバーが表示されます。
バーをタップするとdetentsが複数ある場合は切り替わり、一つの場合は閉じます。
・prefersEdgeAttachedInCompactHeight
trueにすると横画面にした時、横幅いっぱいに広がらなくなります。
・widthFollowsPreferredContentSizeWhenEdgeAttached
prefersEdgeAttachedInCompactHeightと一緒にtrueにするとViewControllerの幅になります。
・preferredCornerRadius
Sheetの角丸の大きさ
・animateChanges
selectedDetentIdentifierを設定して高さを帰る時、そのまま入れるとアニメーションされずに即変わります。
animateChangesのクロージャ内で設定するとアニメーションされます。
・delegate
Sheetのサイズが変わったことを検知できます。
中間と最大の変化のみを検知し、閉じるのは検知できません。
またユーザー操作のみ検知し、コードでselectedDetentIdentifierを設定(初回表示含む)しても検知しません。
色々設定するとこんな感じに


サンプルコード
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func touchUpInside(_ sender: Any) {
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "sheet")
if let sheet = viewController.sheetPresentationController {
sheet.detents = [.medium(), .large()]
sheet.largestUndimmedDetentIdentifier = .medium
sheet.selectedDetentIdentifier = .medium
sheet.prefersScrollingExpandsWhenScrolledToEdge = true
sheet.widthFollowsPreferredContentSizeWhenEdgeAttached = true
sheet.prefersGrabberVisible = true
sheet.prefersEdgeAttachedInCompactHeight = true
sheet.preferredCornerRadius = 16
sheet.delegate = self
}
present(viewController, animated: true, completion: nil)
}
}
extension ViewController: UISheetPresentationControllerDelegate {
func sheetPresentationControllerDidChangeSelectedDetentIdentifier(_ sheetPresentationController: UISheetPresentationController) {
if let detent = sheetPresentationController.selectedDetentIdentifier?.rawValue {
print(detent)
}
}
}
class SheetViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func touchUpInside(_ sender: Any) {
if let sheet = sheetPresentationController {
sheet.animateChanges {
sheet.selectedDetentIdentifier = .medium
}
}
}
}
うーん、痒いところに手が届かない・・・
止まる位置もsmallとか数値で指定できたり、閉じれないようにできたりできれば良いのにー。
今後のアップデートに期待ですね。ちょっとこれでは置き換えられません、残念。
別の使い所はありそうなので機会があれば使ってみようと思います。
