はじめに
昨今SwiftUIブームがきており、StoryboardをSwiftUIに置き換える という動きが多いです。
また、SwiftUIの学習に伴って個人開発のアプリに部分的にSwiftUIを取り入れていく、という人も多いのではないでしょうか。
そこで、見た目をSwiftUIで、処理をUIKitで 記述する方法を考えます。
SwiftUIの画面を作ろう
今回は押されたら小さくなるボタンを作ります。SwiftUIでの作り方はこのようになります。
CameraButton
struct CameraButton: View {
var onButtonPressed: () -> Void
@State private var pressing = false
var body: some View {
Circle()
.fill(Color.white)
.frame(width: pressing ? 60 : 80, height: pressing ? 60 : 80)
.shadow(radius: 10)
.onLongPressGesture(minimumDuration: 0, pressing: { pressing in
self.pressing = pressing
if !pressing {
onButtonPressed()
}
}, perform: {})
}
}
ここでonButtonPressed
は、ボタンが押された時の処理をUIKit側で記述するためのパーツです。
このように処理だけを引き渡すことで、Storyboard側のアーキテクチャを大きく変えることなくSwiftUIに移行していけます。
HostingControllerを使おう
次はUIKit側の画面を作ります。
ViewController
import UIKit
import SwiftUI
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let cameraButton = CameraButton(onButtonPressed: {
self.cameraButtonTapped()
})
let hostingController = UIHostingController(rootView: cameraButton)
addChild(hostingController)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(hostingController.view)
hostingController.didMove(toParent: self)
NSLayoutConstraint.activate([
hostingController.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
hostingController.view.centerYAnchor.constraint(equalTo: view.centerYAnchor),
hostingController.view.widthAnchor.constraint(equalToConstant: 100),
hostingController.view.heightAnchor.constraint(equalToConstant: 100)
])
}
private func cameraButtonTapped() {
print("Camera button tapped")
}
}
このcameraButtonTapped
に押された時の処理を記入することで、処理を呼び出すことができます!
おまけ
SwiftUIの強みの一つはアニメーションの充実なので、以下のようにアニメーションをつけてもいいでしょう。
CameraButton
struct CameraButton: View {
var onButtonPressed: () -> Void
@State private var pressing = false
var body: some View {
Circle()
.fill(Color.white)
.frame(width: pressing ? 60 : 80, height: pressing ? 60 : 80)
.shadow(radius: 10)
.scaleEffect(pressing ? 0.9 : 1.0)
.animation(.spring(), value: pressing)
.onLongPressGesture(minimumDuration: 0, pressing: { pressing in
self.pressing = pressing
if !pressing {
onButtonPressed()
}
}, perform: {})
}
}
まとめ
SwiftUIとStoryboardの長所を両方組み合わせて良い開発をしていきましょう!