Link는 앱에서 웹을 연결할 수 있도록 하지만 사파리 앱을 통해서 웹을 열게 됩니다. 하지만 사용자의 관심을 이끌어내는 것은 중요하기 때문에 앱 안에서 사파리 웹을 열 수 있도록 SafariServices 프레임워크를 제공합니다.
SafariServices 프레임워크는 UX를 향상시키는데 도움이 되는 프레임워크입니다. 이 프레임워크는 SFSafariViewController 클래스를 만들어 독자적인 뷰에서 웹페이지와 툴을 나타낼 수 있는 ViewController를 제공합니다.
다음은 SFSafariViewController의 initializer입니다.
SFSafariViewController(url: URL, configuration: Configuration) - 이 initializer는 새로운 사파리 뷰컨트롤러를 만들어 url 인자값으로 설정된 URL의 경로를 자동으로 연결합니다. configuration 인자는 SFSafariViewController 클래스에 포함되어 있는 프로퍼티로 entersReaderIfAvailable과 barCollapsingEnabled이 있습니다.
다음 코드는 sheet를 사용하여 사파리 뷰를 보여주는 코드입니다.
struct ContentView: View {
@State private var searchURL: URL = URL(string: "https://www.apple.com")!
@State private var openSheet: Bool = false
var body: some View {
VStack {
Button("Open Browser") {
openSheet = true
}.buttonStyle(.borderedProminent)
Spacer()
}.padding()
.sheet(isPresented: $openSheet) {
SafariBrowser(searchURL: $searchURL)
}
}
}
다음은 사파리 뷰를 만드는 코드입니다. 먼저 UIViewControllerRepresentable를 사용하여 UIViewController 를 반환할 수 있게 합니다. makeUIViewController 메서드를 사용하여 사파리 ViewController 반환하며 뷰를 생성합니다.
import SwiftUI
import SafariServices
struct SafariBrowser: UIViewControllerRepresentable {
@Binding var searchURL: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
let safari = SFSafariViewController(url: searchURL)
return safari
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {}
}
Configuring the view controller
SafariViewController는 다음과 같이 추가로 뷰를 설정할 수 있습니다
SFSafariViewController.Configuration(): SFSafariViewController 의 동작을 구성하기 위한 구조체입니다.
다음은 Configuration에 대표적인 구성요소들 입니다.
1. entersReaderIfAvailable: Bool
- Safari의 Reader 모드에 진입할지 여부를 결정합니다. 기본값은 false입니다. 만약 사용자의 기기에서 Reader 모드가 사용 가능하면, 설정에 따라 진입할 수 있습니다.
2. barCollapsingEnabled: Bool
- Safari 브라우저의 상단 바가 축소되어 화면 상단에 표시되는지 여부를 결정합니다. 기본값은 `true`입니다.
3. preferredBarTintColor: UIColor?
- Safari 브라우저의 상단 바 색상을 지정합니다.
4. preferredControlTintColor: UIColor?
- Safari 브라우저의 제어 요소(버튼 등)의 색상을 지정합니다.
5. dismissButtonStyle: SFSafariViewController.DismissButtonStyle
- Safari 브라우저에서 취소 버튼의 스타일을 결정합니다. .done 또는 .close 값을 가질 수 있습니다.
6. isToolbarHidden: Bool
- Safari 브라우저의 도구 모음(Toolbar)이 숨겨져 있는지 여부를 결정합니다.
7. entersReaderIfAvailable: Bool
- Safari의 Reader 모드에 진입할지 여부를 결정합니다.
8. barCollapsingEnabled: Bool
- Safari 브라우저의 상단 바가 축소되어 화면 상단에 표시되는지 여부를 결정합니다.
다음은 barCollapsingEnabled 를 true로 설정하여 화면을 내려도 bar가 축소되지 않도록 하는 예제입니다.
import SwiftUI
import SafariServices
struct SafariBrowser: UIViewControllerRepresentable {
@Binding var searchURL: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
let config = SFSafariViewController.Configuration()
config.barCollapsingEnabled = false
let safari = SFSafariViewController(url: searchURL, configuration: config)
return safari
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {}
}
dismissButtonStyle: 화면을 닫는 버튼의 스타일을 설정합니다
preferredBarTintColor: 배경과 navigation bar, toolbar의 색깔을 설정합니다
preferredControlTintColor: navigation bar과 toolbar의 색깔을 설정합니다
struct SafariBrowser: UIViewControllerRepresentable {
@Binding var searchURL: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
let safari = SFSafariViewController(url: searchURL)
safari.dismissButtonStyle = .close
safari.preferredBarTintColor = UIColor(red: 81/255, green: 91/255, blue: 119/255, alpha: 1.0)
safari.preferredControlTintColor = UIColor.white
return safari
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {}
}
Delegate
SafariServices 프레임워크는 프로토콜도 정의하여 사파리 View Controller가 프로세스를 관리할 수 있도록 합니다.
safariViewController(SFSafariViewController, didCompleteInitialLoad: Bool) - 이 메서드는 웹사이트가 로딩이 완료됐을 때 컨트롤러에 의해 호출됩니다.
safariViewControllerDidFinish(SFSafariViewController) - 이 메서드는 뷰가 dismiss 됐을 때 컨트롤러에 의해 호출됩니다.
safariViewControllerDidFinish(SFSafariViewController)
다음 예제 코드는 disabled 를 사용하여 사파리 브라우저의 disable 닫기 버튼이 눌렸음을 감지하고 만일 눌렸으면 sheet를 없앤 후 다시 버튼을 누를 수 없도록 만드는 코드입니다.
struct ContentView: View {
@State private var searchURL: URL = URL(string: "https://www.apple.com")!
@State private var openSheet: Bool = false
@State private var disableButton: Bool = false
var body: some View {
VStack {
Button("Open Browser") {
openSheet = true
}.buttonStyle(.borderedProminent)
.disabled(disableButton)
Spacer()
}.padding()
.sheet(isPresented: $openSheet) {
SafariBrowser(disable: $disableButton, searchURL: $searchURL)
}
}
}
위에서 SafariBrowser를 통해 컨트롤러에 $disableButton 을 SafariBrowser에서 makeCoordinator 메서드를 통해 SafariCoordinator로 넘겨 만일 SafariViewController가 닫히게 되었을 때 @Binding인 disableCoordinator를 true로 만들어 최상단 root view에 disableButton을 true로 만들 수 있는 코드입니다.
import SwiftUI
import SafariServices
struct SafariBrowser: UIViewControllerRepresentable {
@Binding var disable: Bool
@Binding var searchURL: URL
func makeUIViewController(context: Context) -> SFSafariViewController {
let config = SFSafariViewController.Configuration()
config.barCollapsingEnabled = false
let safari = SFSafariViewController(url: searchURL, configuration: config)
safari.delegate = context.coordinator
return safari
}
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {}
func makeCoordinator() -> SafariCoordinator {
SafariCoordinator(disableCoordinator: $disable)
}
}
class SafariCoordinator: NSObject, SFSafariViewControllerDelegate {
@Binding var disableCoordinator: Bool
init(disableCoordinator: Binding<Bool>) {
self._disableCoordinator = disableCoordinator
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
disableCoordinator = true
}
}
'SwiftUI' 카테고리의 다른 글
MPRemoteCommandCenter (잠금화면 미디어제어) (0) | 2024.03.03 |
---|---|
MPNowPlayingInfoCenter (잠금화면 미디어정보) (0) | 2024.03.03 |
Web Links - 웹 링크 연동시키기 (0) | 2024.01.17 |
addingPercentEncoding - 특수 기호 URL에 포함시키기 (0) | 2024.01.17 |
AppDelegate (UIWindowSceneDelegate, UIApplicationDelegate) (0) | 2024.01.16 |