SwiftUI에서 전체 화면 모달 표시 (iOS13)
SwiftUI(iOS13)에서 전체 화면 모달 표시
오랜만의 기사가 됩니다. 좋은 아침 안녕하세요 화상입니다!
오늘은 재작년 Apple로부터 발표되어 화제가 되고 있는 SwiftUI에 대한 기사를 써 가고 싶습니다
SwiftUI 2는 iOS13에서는 사용할 수 없습니다.
현재(2021.3월 시점)에서는 SwiftUI는 ver.2까지 릴리스되고 있습니다만, 불행하게도 SwiftUI 2에서 릴리스된 기능은 iOS13에서 사용할 수 없습니다. SwiftUI 1에서는 일반적인 앱에 필요한 기능이 전혀 갖추어지지 않고, 2이상으로 라이브러리나 UIKit에 의존하게 됩니다.
필수급 라이브러리
SwiftUIX
↑ SwiftUI에 아직 구현되지 않은 것을 보완 해줍니다. 설명서가없는 것이 칠라 호라있는 것이 유감입니다 ...
그런데, 본제인 풀 스크린의 모달입니다만, 공식으로부터는 「.fullScreenCover」라고 하는 것이 준비되어 있습니다만 이쪽은 SwiftUI 2로부터 등장한 것이 되고 있어 유감스럽지만 iOS13에서는 사용할 수 없습니다.
그래서 이번 iOS13에서도 사용할 수있는 풀 스크린 모달을 만들어 갑시다!
※ 덧붙여서 필자, 처음 iOS 앱 구현이 SwiftUI가되어있어 UIKit도 현재 절찬 공부 중이므로 손 부드럽게 (웃음)
전체 화면 모달 구현
1. UIApplication 확장
UIApplication을 확장하여 최상위 컨트롤러를 얻는 메서드와 전체 화면 모달을 닫는 메서드를 만듭니다.
UIApplication+Extension.swiftextension UIApplication {
/// 一番上にあるコントローラーを取得する
public func getTopViewController() -> UIViewController? {
guard let window = UIApplication.shared
.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows.first else {
return nil
}
window.makeKeyAndVisible()
guard let rootViewController = window.rootViewController else {
return nil
}
var topController = rootViewController
while let newTopController = topController.presentedViewController {
topController = newTopController
}
return topController
}
/// フルスクリーンのモーダルを閉じる
public func closeModalView() {
UIApplication.shared.getTopViewController()?.dismiss(animated: true, completion: nil)
}
}
2. View 확장
다음은 SwiftUI의 View에서 SheetView나 FullCreenCover와 같이 풀 스크린 모달을 사용할 수 있도록 View를 확장해 나갑니다.
View+Extension.swiftextension View {
public func fullScreenView<Content>(
isPresented: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content
) -> some View where Content: View {
if isPresented.wrappedValue {
let window = UIApplication.shared.windows.last
window?.isHidden = true
let view = content()
let viewController = UIHostingController(rootView: view)
viewController.modalPresentationStyle = .fullScreen
DispatchQueue.main.async {
guard let tvc = UIApplication.shared.getTopViewController() else {
return
}
tvc.present(viewController, animated: true, completion: nil)
isPresented.wrappedValue = false
}
}
return self
}
}
실제로 사용해 보자!
실제로 View에서 사용합시다! 이번 적당한 샘플 View를 준비해 보았습니다!
이쪽 참고에 여러분 부디 사용해 보세요
ContentView.swiftstruct ContentView: View {
@State private var showModal: Bool = false
var body: some View {
VStack {
Spacer()
Button(action: {
showModal.toggle()
}, label: {
Text("フルスクリーンのモーダルを表示する")
})
Spacer()
}
.fullScreenView(isPresented: $showModal) {
ModalView()
}
}
}
struct ModalView: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
Button(action: {
UIApplication.shared.closeModalView()
}, label: {
Text("閉じる")
})
}
}
}
마지막으로
iOS13에서 SwiftUI와 Combine을 사용할 때 특히 iOS13.0에서 iOS13.2까지는 조심하십시오. 버그가 꽤 많이...
게다가, 우리가 나쁜 것에 시뮬레이션에서는 재현하지 않고 실기만으로 재현하는 버그도 몇가지 있습니다.
실제 기기가 없으면 SwiftUI를 iOS13에서 사용하지 않는 것이 좋습니다
그래도 iOS13을 포함하고 싶다면 최소한 iOS13.3 이상으로 만드십시오.
Let's Enjoy SwiftUI! !
Reference
이 문제에 관하여(SwiftUI에서 전체 화면 모달 표시 (iOS13)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/osyou84/items/955becc4c2a992b7e9dd
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
extension UIApplication {
/// 一番上にあるコントローラーを取得する
public func getTopViewController() -> UIViewController? {
guard let window = UIApplication.shared
.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows.first else {
return nil
}
window.makeKeyAndVisible()
guard let rootViewController = window.rootViewController else {
return nil
}
var topController = rootViewController
while let newTopController = topController.presentedViewController {
topController = newTopController
}
return topController
}
/// フルスクリーンのモーダルを閉じる
public func closeModalView() {
UIApplication.shared.getTopViewController()?.dismiss(animated: true, completion: nil)
}
}
extension View {
public func fullScreenView<Content>(
isPresented: Binding<Bool>,
@ViewBuilder content: @escaping () -> Content
) -> some View where Content: View {
if isPresented.wrappedValue {
let window = UIApplication.shared.windows.last
window?.isHidden = true
let view = content()
let viewController = UIHostingController(rootView: view)
viewController.modalPresentationStyle = .fullScreen
DispatchQueue.main.async {
guard let tvc = UIApplication.shared.getTopViewController() else {
return
}
tvc.present(viewController, animated: true, completion: nil)
isPresented.wrappedValue = false
}
}
return self
}
}
struct ContentView: View {
@State private var showModal: Bool = false
var body: some View {
VStack {
Spacer()
Button(action: {
showModal.toggle()
}, label: {
Text("フルスクリーンのモーダルを表示する")
})
Spacer()
}
.fullScreenView(isPresented: $showModal) {
ModalView()
}
}
}
struct ModalView: View {
var body: some View {
ZStack {
Color.green.edgesIgnoringSafeArea(.all)
Button(action: {
UIApplication.shared.closeModalView()
}, label: {
Text("閉じる")
})
}
}
}
Reference
이 문제에 관하여(SwiftUI에서 전체 화면 모달 표시 (iOS13)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/osyou84/items/955becc4c2a992b7e9dd텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)