はじめに
SwiftUIでUIKitを使う場合はUIViewRepresentable
を使いますが、あらためて公式ドキュメントで使い方を確認してみました。
内容
Viewの作成と更新
func makeUIView(context: Self.Context) -> Self.UIViewType
- 必須
- Viewのオブジェクトを作成、初期状態を構成する
- Viewを初めて作成するときに、このメソッドを1回だけ呼び出す
func updateUIView(_ uiView: Self.UIViewType, context: Self.Context)
- 必須
- Viewの状態をSwiftUIからの新しい情報で更新する
- SwiftUIは、対応するUIKitのVIewに影響を与える変更に対してこのメソッドを呼び出す
- パラメーターで提供される新しい状態情報に一致するようにビューの構成を更新する
サイズの指定
func sizeThatFits(_ proposal: ProposedViewSize, uiView: Self.UIViewType, context: Self.Context) -> CGSize?
- iOS16から使える
- 提案サイズからViewのサイズを指定する
Viewのクリーンアップ
static func dismantleUIView(_ uiView: Self.UIViewType, coordinator: Self.Coordinator)
- Viewに関連する追加のクリーンアップ作業を実行する
- たとえば、オブザーバーを削除するなど
Coordinatorの提供
func makeCoordinator() -> Self.Coordinator
- Viewの変更がアプリの他の部分に影響を与える可能性がある場合は、このメソッドを実装する
- UIKitのdelegateを使う場合などでも使う
実装例
AppleログインのボタンをUIViewRepresentable
を使って実装した場合のイメージ👇
import SwiftUI
import AuthenticationServices
struct CustomButton: UIViewRepresentable {
@ObservedObject var viewModel: SampleViewModel
func makeUIView(context: Context) -> UIButton {
var configuration = UIButton.Configuration.plain()
var container = AttributeContainer()
container.font = UIFont.boldSystemFont(ofSize: 16.0)
configuration.attributedTitle = AttributedString("Apple Login", attributes: container)
configuration.baseBackgroundColor = .white
configuration.background.strokeWidth = 1.0
let button = UIButton(configuration: configuration)
button.addTarget(context.coordinator,
action: #selector(Coordinator.didTapButton),
for: .touchUpInside)
return button
}
func updateUIView(_: UIButton, context _: Context) {}
func makeCoordinator() -> Coordinator {
Coordinator(customButton: self)
}
class Coordinator: NSObject, ASAuthorizationControllerDelegate {
var customButton: CustomButton
init(customButton: CustomButton) {
self.customButton = customButton
}
@objc func didTapButton() {
let provider = ASAuthorizationAppleIDProvider()
let request = provider.createRequest()
request.requestedScopes = [.fullName, .email]
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.performRequests()
}
func authorizationController(controller: ASAuthorizationController,
didCompleteWithAuthorization authorization: ASAuthorization) {
// ViewModelで処理するなど customButton.viewModel.loginWithApple()
}
func authorizationController(controller _: ASAuthorizationController, didCompleteWithError error: Error) {
// ViewModelで処理するなど customButton.viewModel.showError()
}
}
}
おわりに
とくに整理する程の内容量ではないですが、iOS16から使えるsizeThatFits
は少し実装で使って試していきたいと思いました。
参考