├── UIViewRepresentableExamples
├── Assets.xcassets
│ ├── Contents.json
│ ├── stars.dataset
│ │ ├── Contents.json
│ │ └── stars.svg
│ ├── Ghostscript_Tiger.dataset
│ │ ├── Contents.json
│ │ └── Ghostscript_Tiger.svg
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── Resources
│ └── arnel-hasanovic-4oWSXdeAS2g-unsplash.jpg
├── ContentView.swift
├── Camera
│ ├── CameraExample.swift
│ ├── CameraPreview.swift
│ ├── CameraPreviewWrapperView.swift
│ └── DeviceCaptureView.swift
├── TextView
│ ├── TextViewExample.swift
│ └── TextView.swift
├── HTMLRenderingWebView
│ ├── HTMLRenderingWebViewExample.swift
│ └── HTMLRenderingWebView.swift
├── ShareSheet
│ ├── ShareButton.swift
│ ├── ShareExample.swift
│ └── ActivityViewControllerWrapper.swift
├── SVGView
│ ├── SVGViewExample.swift
│ ├── SVGExamples.swift
│ └── SVGView.swift
├── ScrollView
│ ├── LegacyScrollViewExample.swift
│ └── LegacyScrollView.swift
├── AppDelegate.swift
├── Base.lproj
│ └── LaunchScreen.storyboard
├── Menu.swift
├── MapKit
│ ├── MapView.swift
│ └── MapKitExample.swift
├── Info.plist
├── Constants.swift
└── SceneDelegate.swift
├── screenshots
├── screenshot_svg_small-fs8.png
├── screenshot_mapkit_small-fs8.png
├── screenshot_menu_small-fs8.png
└── screenshot_webkit_small-fs8.png
├── UIViewRepresentableExamples.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcshareddata
│ └── xcschemes
│ │ └── UIViewRepresentableExamples.xcscheme
└── project.pbxproj
├── README.md
├── LICENSE
└── .gitignore
/UIViewRepresentableExamples/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/screenshots/screenshot_svg_small-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bvankuik/UIViewRepresentableExamples/HEAD/screenshots/screenshot_svg_small-fs8.png
--------------------------------------------------------------------------------
/screenshots/screenshot_mapkit_small-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bvankuik/UIViewRepresentableExamples/HEAD/screenshots/screenshot_mapkit_small-fs8.png
--------------------------------------------------------------------------------
/screenshots/screenshot_menu_small-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bvankuik/UIViewRepresentableExamples/HEAD/screenshots/screenshot_menu_small-fs8.png
--------------------------------------------------------------------------------
/screenshots/screenshot_webkit_small-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bvankuik/UIViewRepresentableExamples/HEAD/screenshots/screenshot_webkit_small-fs8.png
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Resources/arnel-hasanovic-4oWSXdeAS2g-unsplash.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bvankuik/UIViewRepresentableExamples/HEAD/UIViewRepresentableExamples/Resources/arnel-hasanovic-4oWSXdeAS2g-unsplash.jpg
--------------------------------------------------------------------------------
/UIViewRepresentableExamples.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/ContentView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct ContentView: View {
4 | var body: some View {
5 | Menu()
6 | }
7 | }
8 |
9 | struct ContentView_Previews: PreviewProvider {
10 | static var previews: some View {
11 | ContentView()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Assets.xcassets/stars.dataset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "data" : [
3 | {
4 | "filename" : "stars.svg",
5 | "idiom" : "universal",
6 | "universal-type-identifier" : "public.svg-image"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Assets.xcassets/Ghostscript_Tiger.dataset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | },
6 | "data" : [
7 | {
8 | "idiom" : "universal",
9 | "filename" : "Ghostscript_Tiger.svg",
10 | "universal-type-identifier" : "public.svg-image"
11 | }
12 | ]
13 | }
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Camera/CameraExample.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct CameraExample: View {
4 | var body: some View {
5 | CameraPreview()
6 | .navigationBarTitle("Camera")
7 | }
8 | }
9 |
10 | struct CameraExample_Previews: PreviewProvider {
11 | static var previews: some View {
12 | CameraExample()
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UIViewRepresentableExamples
2 | Examples of using UIKit stuff in SwiftUI.
3 |
4 | The examples are not meant to be full-featured. Rather, they're small enough to
5 | quickly understand, but still show enough code so that you can quickly add the
6 | functions your project requires.
7 |
8 | # Screenshots
9 |  
10 |
11 |  
12 |
13 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/TextView/TextViewExample.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct TextViewExample: View {
4 | @State private var text = ""
5 |
6 | var body: some View {
7 | VStack {
8 | Text("Type something in the box below")
9 | Text("Current count: \(self.text.count)")
10 | TextView(text: self.$text)
11 | .border(Color.gray).padding()
12 | }.navigationBarTitle("UITextView example")
13 | }
14 | }
15 |
16 | struct TextViewExample_Previews: PreviewProvider {
17 | static var previews: some View {
18 | TextViewExample()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/HTMLRenderingWebView/HTMLRenderingWebViewExample.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct HTMLRenderingWebViewExample: View {
4 | @State var htmlString = ""
5 |
6 | var body: some View {
7 | VStack {
8 | HTMLRenderingWebView(htmlString: self.$htmlString, baseURL: .constant(nil))
9 | .padding(30).background(Color.gray)
10 | Button("Click this button") {
11 | self.htmlString = "
Test
Hello world!"
12 | }
13 | }.navigationBarTitle("Example HTML Rendering")
14 | }
15 | }
16 |
17 | struct HTMLRenderingWebViewExample_Previews: PreviewProvider {
18 | static var previews: some View {
19 | HTMLRenderingWebViewExample()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/ShareSheet/ShareButton.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShareButton.swift
3 | // UIViewRepresentableExamples
4 | //
5 | // Created by Bart van Kuik on 02/03/2023.
6 | // Copyright © 2023 DutchVirtual. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ShareButton: View {
12 | let url: URL?
13 |
14 | var body: some View {
15 | Text("Tap to share")
16 | .padding()
17 | .border(Color.blue)
18 | .background(Color.yellow)
19 | .overlay(ActivityViewControllerWrapper(url: self.url))
20 | .accessibilityAddTraits(.isButton)
21 | .accessibilityHint("Share")
22 | }
23 | }
24 |
25 | struct ShareButton_Previews: PreviewProvider {
26 | static var previews: some View {
27 | ShareButton(url: nil)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Camera/CameraPreview.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | // If you would use UIViewRepresentable, and you'd navigate to this view on iPad in landscape, then the orientation
4 | // would be wrong. Thus, we wrap the view in UIViewControllerRepresentable.
5 |
6 | struct CameraPreview: UIViewControllerRepresentable {
7 | func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIViewController {
8 | let viewController = UIViewController()
9 | viewController.view = CameraPreviewWrapperView()
10 | return viewController
11 | }
12 |
13 | func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext) {
14 | }
15 | }
16 |
17 | struct CameraPreview_Previews: PreviewProvider {
18 | static var previews: some View {
19 | CameraPreview()
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/SVGView/SVGViewExample.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct SVGViewExample: View {
4 | @State private var svgString = ""
5 |
6 | var body: some View {
7 | VStack {
8 | SVGView(svgString: self.$svgString)
9 | .border(Color.gray, width: 3)
10 | HStack(spacing: 20) {
11 | Button("Show tiger image") {
12 | self.svgString = SVGExamples.tiger
13 | }.padding()
14 | Button("Show text in oval") {
15 | self.svgString = SVGExamples.smallExample
16 | }.padding()
17 | }
18 | }
19 | }
20 | }
21 |
22 | struct SVGViewExample_Previews: PreviewProvider {
23 | static var previews: some View {
24 | // This won't show anything, you'll have to run a live preview
25 | SVGViewExample()
26 | .previewDevice("iPhone SE")
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/TextView/TextView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct TextView: UIViewRepresentable {
4 | @Binding var text: String
5 |
6 | func makeUIView(context: Context) -> UITextView {
7 | let textView = UITextView()
8 | textView.delegate = context.coordinator
9 | return textView
10 | }
11 |
12 | func updateUIView(_ uiView: UITextView, context: Context) {
13 | uiView.text = text
14 | }
15 |
16 | func makeCoordinator() -> Coordinator {
17 | Coordinator(self)
18 | }
19 |
20 | class Coordinator: NSObject, UITextViewDelegate {
21 | var parent: TextView
22 |
23 | func textViewDidChange(_ textView: UITextView) {
24 | self.parent.text = textView.text
25 | }
26 |
27 | init(_ parent: TextView) {
28 | self.parent = parent
29 | }
30 | }}
31 |
32 | struct TextView_Previews: PreviewProvider {
33 | static var previews: some View {
34 | TextView(text: .constant("Hello world"))
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/ScrollView/LegacyScrollViewExample.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct ScrollViewContent: View {
4 | @Binding var sampleText: String
5 |
6 | var body: some View {
7 | Text(self.sampleText)
8 | }
9 | }
10 |
11 | struct LegacyScrollViewExample: View {
12 | @State private var action = LegacyScrollView.Action.idle
13 | @State private var sampleText = Constants.lipsum[0]
14 |
15 | var body: some View {
16 | VStack(spacing: 0) {
17 | LegacyScrollView(axis: .vertical, action: self.$action) {
18 | ScrollViewContent(sampleText: self.$sampleText)
19 | }
20 | .padding(20)
21 | .background(Color.gray)
22 | Spacer()
23 | Button("Set offset") {
24 | self.sampleText += Constants.lipsum[0]
25 | }.padding()
26 | }.navigationBarTitle("ScrollView")
27 | }
28 | }
29 |
30 | struct LegacyScrollViewExample_Previews: PreviewProvider {
31 | static var previews: some View {
32 | LegacyScrollViewExample()
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 bvankuik
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Assets.xcassets/stars.dataset/stars.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/ShareSheet/ShareExample.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShareExample.swift
3 | // UIViewRepresentableExamples
4 | //
5 | // Created by Bart van Kuik on 02/03/2023.
6 | // Copyright © 2023 DutchVirtual. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ShareExample: View {
12 | static private let imageURL = Bundle.main.url(forResource: "arnel-hasanovic-4oWSXdeAS2g-unsplash", withExtension: "jpg")
13 | private let uiImage: UIImage? = {
14 | // Image by Arnel Hasanovic https://unsplash.com/@arnelhasanovic
15 | guard let url = Self.imageURL else {
16 | return nil
17 | }
18 | guard let data = try? Data(contentsOf: url) else {
19 | return nil
20 | }
21 | return UIImage(data: data)
22 | }()
23 |
24 | var body: some View {
25 | if let uiImage = self.uiImage {
26 | Image(uiImage: uiImage)
27 | ShareButton(url: Self.imageURL)
28 | } else {
29 | EmptyView()
30 | }
31 | }
32 | }
33 |
34 | struct ShareExample_Previews: PreviewProvider {
35 | static var previews: some View {
36 | ShareExample()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Camera/CameraPreviewWrapperView.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import AVFoundation
3 |
4 | class CameraPreviewWrapperView: UIView {
5 | private static func makeLabel(text: String) -> UILabel {
6 | let label = UILabel()
7 | label.adjustsFontForContentSizeCategory = true
8 | label.textAlignment = .center
9 | label.backgroundColor = UIColor.systemGray
10 | label.text = text
11 | label.autoresizingMask = [.flexibleWidth, .flexibleHeight]
12 | return label
13 | }
14 |
15 | override init(frame: CGRect) {
16 | super.init(frame: frame)
17 |
18 | if TARGET_OS_SIMULATOR != 0 {
19 | // We're in simulator, show at least something
20 | self.addSubview(Self.makeLabel(text: "No camera available in simulator"))
21 | } else if AVCaptureDevice.default(for: .video) == nil {
22 | self.addSubview(Self.makeLabel(text: "Camera not found"))
23 | } else {
24 | let deviceCaptureView = DeviceCaptureView()
25 | deviceCaptureView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
26 | self.addSubview(deviceCaptureView)
27 | }
28 | }
29 |
30 | required init?(coder: NSCoder) {
31 | fatalError("init(coder:) has not been implemented")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | @UIApplicationMain
4 | class AppDelegate: UIResponder, UIApplicationDelegate {
5 |
6 |
7 |
8 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
9 | // Override point for customization after application launch.
10 | return true
11 | }
12 |
13 | // MARK: UISceneSession Lifecycle
14 |
15 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
16 | // Called when a new scene session is being created.
17 | // Use this method to select a configuration to create the new scene with.
18 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
19 | }
20 |
21 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
22 | // Called when the user discards a scene session.
23 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
24 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
25 | }
26 |
27 |
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/HTMLRenderingWebView/HTMLRenderingWebView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import WebKit
3 |
4 | struct HTMLRenderingWebView: UIViewRepresentable {
5 | @Binding var htmlString: String
6 | @Binding var baseURL: URL?
7 | let meta = ""
8 |
9 | func makeUIView(context: Context) -> WKWebView {
10 | let webView = WKWebView()
11 | return webView
12 | }
13 |
14 | func updateUIView(_ uiView: WKWebView, context: Context) {
15 | if self.htmlString != context.coordinator.lastLoadedHTML {
16 | context.coordinator.lastLoadedHTML = self.htmlString
17 | uiView.loadHTMLString(self.meta + self.htmlString, baseURL: self.baseURL)
18 | }
19 | }
20 |
21 | func makeCoordinator() -> Coordinator {
22 | Coordinator(self)
23 | }
24 |
25 | class Coordinator: NSObject {
26 | var parent: HTMLRenderingWebView
27 | var lastLoadedHTML = ""
28 |
29 | init(_ parent: HTMLRenderingWebView) {
30 | self.parent = parent
31 | }
32 | }
33 | }
34 |
35 | struct WebView_Previews: PreviewProvider {
36 | static var previews: some View {
37 | HTMLRenderingWebView(htmlString: .constant("Test
"), baseURL: .constant(nil))
38 | .background(Color.gray)
39 | .previewDevice("iPhone 8")
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/SVGView/SVGExamples.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 |
3 | struct SVGExamples {
4 | // GNU Affero General Public License
5 | // https://commons.wikimedia.org/wiki/File:Ghostscript_Tiger.svg
6 | static var tiger: String = Self.loadAsset(assetName: "Ghostscript_Tiger")
7 | static var stars: String = Self.loadAsset(assetName: "stars")
8 |
9 | static let smallExample =
10 | """
11 |
22 | """
23 |
24 | static func loadAsset(assetName: String) -> String {
25 | guard let asset = NSDataAsset(name: assetName) else {
26 | fatalError("Couldn't find SVG in assets, did you actually make a Data Set (not image set) in your xcassets file?")
27 | }
28 |
29 | let data = asset.data
30 | if let string = String(data: data, encoding: .utf8) {
31 | return string
32 | } else {
33 | fatalError("Couldn't turn SVG asset into UTF8 string")
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Menu.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct PadMessage: View {
4 | var body: some View {
5 | Color.clear.overlay (
6 | GeometryReader { geometry in
7 | Text(geometry.size.width < geometry.size.height
8 | ? "Rotate to see the list of examples"
9 | : "No example selected"
10 | ).font(.headline).foregroundColor(.gray)
11 | }
12 | )
13 | }
14 | }
15 |
16 | struct Menu: View {
17 | var body: some View {
18 | NavigationView {
19 | List {
20 | NavigationLink(destination: HTMLRenderingWebViewExample()) {
21 | Text("HTML rendering WebView")
22 | }
23 | NavigationLink(destination: MapKitExample()) {
24 | Text("MapKit example")
25 | }
26 | NavigationLink(destination: TextViewExample()) {
27 | Text("TextView example")
28 | }
29 | NavigationLink(destination: LegacyScrollViewExample()) {
30 | Text("LegacyScrollView example")
31 | }
32 | NavigationLink(destination: SVGViewExample()) {
33 | Text("SVG Example")
34 | }
35 | NavigationLink(destination: CameraExample()) {
36 | Text("Camera Example")
37 | }
38 | NavigationLink(destination: ShareExample()) {
39 | Text("Share Example")
40 | }
41 | }
42 | .navigationBarTitle("Available examples")
43 |
44 | PadMessage()
45 | }
46 | }
47 | }
48 |
49 | struct Menu_Previews: PreviewProvider {
50 | static var previews: some View {
51 | Menu()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/ShareSheet/ActivityViewControllerWrapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ActivityViewControllerWrapper.swift
3 | // UIViewRepresentableExamples
4 | //
5 | // Created by Bart van Kuik on 02/03/2023.
6 | // Copyright © 2023 DutchVirtual. All rights reserved.
7 | //
8 |
9 | import SwiftUI
10 |
11 | struct ActivityViewControllerWrapper: UIViewControllerRepresentable {
12 | let url: URL?
13 |
14 | func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIViewController {
15 | let viewController = UIViewController()
16 | let action = UIAction(title: "", image: nil) { action in
17 | let activityViewController = UIActivityViewController(activityItems: [self.url as Any], applicationActivities: nil)
18 | activityViewController.popoverPresentationController?.sourceView = viewController.view // so that iPads won't crash
19 | viewController.present(activityViewController, animated: true, completion: nil)
20 | }
21 | let button = UIButton(frame: .zero, primaryAction: action)
22 | viewController.view = button
23 |
24 | return viewController
25 | }
26 |
27 | func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext) {
28 | }
29 | }
30 |
31 | struct ActivityViewControllerWrapper_Previews: PreviewProvider {
32 | static let url = Bundle.main.url(forResource: "arnel-hasanovic-4oWSXdeAS2g-unsplash", withExtension: "jpg")
33 |
34 | static var previews: some View {
35 | VStack {
36 | Text("Tap to share")
37 | .padding()
38 | .border(Color.blue)
39 | .background(Color.yellow)
40 | .overlay(
41 | ActivityViewControllerWrapper(url: Self.url)
42 | )
43 | }
44 | }
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/MapKit/MapView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import MapKit
3 |
4 | struct MapView: UIViewRepresentable {
5 | enum Action {
6 | case idle
7 | case reset(coordinate: CLLocationCoordinate2D)
8 | case changeType(mapType: MKMapType)
9 | }
10 |
11 | @Binding var centerCoordinate: CLLocationCoordinate2D
12 | @Binding var action: Action
13 |
14 | func makeUIView(context: Context) -> MKMapView {
15 | let mapView = MKMapView()
16 | mapView.delegate = context.coordinator
17 | mapView.centerCoordinate = self.centerCoordinate
18 | return mapView
19 | }
20 |
21 | func updateUIView(_ uiView: MKMapView, context: Context) {
22 | switch action {
23 | case .idle:
24 | break
25 | case .reset(let newCoordinate):
26 | uiView.delegate = nil
27 | uiView.centerCoordinate = newCoordinate
28 | DispatchQueue.main.async {
29 | self.centerCoordinate = newCoordinate
30 | self.action = .idle
31 | uiView.delegate = context.coordinator
32 | }
33 | case .changeType(let mapType):
34 | uiView.mapType = mapType
35 | }
36 | }
37 |
38 | func makeCoordinator() -> Coordinator {
39 | Coordinator(self)
40 | }
41 |
42 | class Coordinator: NSObject, MKMapViewDelegate {
43 | var parent: MapView
44 |
45 | func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
46 | parent.centerCoordinate = mapView.centerCoordinate
47 | }
48 |
49 | init(_ parent: MapView) {
50 | self.parent = parent
51 | }
52 | }
53 | }
54 |
55 | struct MapView_Previews: PreviewProvider {
56 | static let amsterdamCoordinate = CLLocationCoordinate2D(latitude: 52.37403, longitude: 4.88969)
57 |
58 | static var previews: some View {
59 | MapView(centerCoordinate: .constant(amsterdamCoordinate), action: .constant(.idle))
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSCameraUsageDescription
24 | to show an example of a camera
25 | UIApplicationSceneManifest
26 |
27 | UIApplicationSupportsMultipleScenes
28 |
29 | UISceneConfigurations
30 |
31 | UIWindowSceneSessionRoleApplication
32 |
33 |
34 | UISceneConfigurationName
35 | Default Configuration
36 | UISceneDelegateClassName
37 | $(PRODUCT_MODULE_NAME).SceneDelegate
38 |
39 |
40 |
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UISupportedInterfaceOrientations~ipad
55 |
56 | UIInterfaceOrientationPortrait
57 | UIInterfaceOrientationPortraitUpsideDown
58 | UIInterfaceOrientationLandscapeLeft
59 | UIInterfaceOrientationLandscapeRight
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/MapKit/MapKitExample.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import CoreLocation
3 | import MapKit
4 |
5 | extension CLLocationCoordinate2D {
6 | var description: String {
7 | String(format: "%.8f, %.8f", self.latitude, self.longitude)
8 | }
9 | }
10 |
11 | extension MapKitExample {
12 | struct PickerValues {
13 | let mapType: MKMapType
14 | let description: String
15 | }
16 | }
17 |
18 | struct MapKitExample: View {
19 | static let amsterdam = CLLocationCoordinate2D(latitude: 52.37403,
20 | longitude: 4.88969)
21 | @State private var centerCoordinate = Self.amsterdam
22 | @State private var action: MapView.Action = .idle
23 | @State private var mapPickerSelection: Int = 0
24 |
25 | let pickerValues: [PickerValues] = [// [.standard, .hybrid, .satellite]
26 | PickerValues(mapType: .standard, description: "Standard"),
27 | PickerValues(mapType: .hybrid, description: "Hybrid"),
28 | PickerValues(mapType: .satellite, description: "Satellite"),
29 | ]
30 |
31 | var body: some View {
32 | let binding = Binding(
33 | get: { self.mapPickerSelection},
34 | set: { newValue in
35 | self.action = .changeType(mapType: self.pickerValues[newValue].mapType)
36 | self.mapPickerSelection = newValue
37 | }
38 | )
39 | return VStack {
40 | MapView(centerCoordinate: self.$centerCoordinate, action: self.$action)
41 | Picker(selection: binding, label: Text("Map type")) {
42 | ForEach(self.pickerValues.indices) { index in
43 | Text(self.pickerValues[index].description).tag(index)
44 | }
45 | }.pickerStyle(SegmentedPickerStyle())
46 | Text("Centered on: " + self.centerCoordinate.description)
47 | Button("Reset") {
48 | self.action = .reset(coordinate: Self.amsterdam)
49 | }
50 | }
51 | .navigationBarTitle("MapKit Example")
52 | }
53 | }
54 |
55 | struct MapKitExample_Previews: PreviewProvider {
56 | static var previews: some View {
57 | MapKitExample()
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Constants.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | struct Constants {
4 | static let lipsum: [String] = [
5 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
6 | "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?",
7 | "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.",
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Camera/DeviceCaptureView.swift:
--------------------------------------------------------------------------------
1 | import AVFoundation
2 | import UIKit
3 |
4 | class DeviceCaptureView: UIView {
5 | private let previewLayer = AVCaptureVideoPreviewLayer()
6 |
7 | private func updateOrientation() {
8 | let orientation: AVCaptureVideoOrientation
9 | switch UIDevice.current.orientation {
10 | case .portrait:
11 | orientation = .portrait
12 | case .landscapeRight:
13 | orientation = .landscapeLeft
14 | case .landscapeLeft:
15 | orientation = .landscapeRight
16 | case .portraitUpsideDown:
17 | orientation = .portraitUpsideDown
18 | case .faceUp:
19 | orientation = .portrait
20 | case .faceDown:
21 | orientation = .portrait
22 | case .unknown:
23 | orientation = .portrait
24 | @unknown default:
25 | fatalError("Unknown orientation")
26 | }
27 | if self.previewLayer.connection?.isVideoOrientationSupported == true {
28 | self.previewLayer.connection?.videoOrientation = orientation
29 | }
30 | self.previewLayer.frame = self.frame
31 | }
32 |
33 | override func layoutSubviews() {
34 | super.layoutSubviews()
35 | self.updateOrientation()
36 | }
37 |
38 | override init(frame: CGRect) {
39 | guard let captureDevice = AVCaptureDevice.default(for: .video) else {
40 | fatalError("Couldn't find default capture device")
41 | }
42 |
43 | guard let captureDeviceInput = try? AVCaptureDeviceInput(device: captureDevice) else {
44 | super.init(frame: frame)
45 | return
46 | }
47 |
48 | let captureSession = AVCaptureSession()
49 | captureSession.addInput(captureDeviceInput)
50 |
51 | self.previewLayer.session = captureSession
52 | self.previewLayer.videoGravity = .resizeAspectFill
53 |
54 | super.init(frame: frame)
55 |
56 | self.layer.addSublayer(self.previewLayer)
57 | self.previewLayer.frame = self.frame
58 | captureSession.startRunning()
59 | }
60 |
61 | required init?(coder: NSCoder) {
62 | fatalError("init(coder:) has not been implemented")
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 | .DS_Store
92 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/SceneDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import SwiftUI
3 |
4 | class SceneDelegate: UIResponder, UIWindowSceneDelegate {
5 |
6 | var window: UIWindow?
7 |
8 |
9 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
10 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
11 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
12 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
13 |
14 | // Create the SwiftUI view that provides the window contents.
15 | let contentView = ContentView()
16 |
17 | // Use a UIHostingController as window root view controller.
18 | if let windowScene = scene as? UIWindowScene {
19 | let window = UIWindow(windowScene: windowScene)
20 | window.rootViewController = UIHostingController(rootView: contentView)
21 | self.window = window
22 | window.makeKeyAndVisible()
23 | }
24 | }
25 |
26 | func sceneDidDisconnect(_ scene: UIScene) {
27 | // Called as the scene is being released by the system.
28 | // This occurs shortly after the scene enters the background, or when its session is discarded.
29 | // Release any resources associated with this scene that can be re-created the next time the scene connects.
30 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
31 | }
32 |
33 | func sceneDidBecomeActive(_ scene: UIScene) {
34 | // Called when the scene has moved from an inactive state to an active state.
35 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
36 | }
37 |
38 | func sceneWillResignActive(_ scene: UIScene) {
39 | // Called when the scene will move from an active state to an inactive state.
40 | // This may occur due to temporary interruptions (ex. an incoming phone call).
41 | }
42 |
43 | func sceneWillEnterForeground(_ scene: UIScene) {
44 | // Called as the scene transitions from the background to the foreground.
45 | // Use this method to undo the changes made on entering the background.
46 | }
47 |
48 | func sceneDidEnterBackground(_ scene: UIScene) {
49 | // Called as the scene transitions from the foreground to the background.
50 | // Use this method to save data, release shared resources, and store enough scene-specific state information
51 | // to restore the scene back to its current state.
52 | }
53 |
54 |
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/SVGView/SVGView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 | import WebKit
3 |
4 | struct SVGView: UIViewRepresentable {
5 | @Environment(\.colorScheme) private var colorScheme
6 | @Binding private var svgString: String
7 | private let darkmodeStyle: String
8 | private let style =
9 | """
10 | html, body { margin:0; padding:0; overflow:hidden }
11 | :root {
12 | color-scheme: light dark;
13 | }
14 | svg { position:fixed; top:0; left:0; height:100%; width:100%;
15 | }
16 | """
17 |
18 | private let webView: WKWebView
19 |
20 | func makeUIView(context: Context) -> WKWebView {
21 | return self.webView
22 | }
23 |
24 | func updateUIView(_ uiView: WKWebView, context: Context) {
25 | if self.svgString != context.coordinator.lastLoadedString {
26 | context.coordinator.lastLoadedString = self.svgString
27 |
28 | let htmlString =
29 | "" +
33 | "" +
34 | "" +
35 | self.svgString +
36 | ""
37 | uiView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL)
38 | }
39 | }
40 |
41 | func makeCoordinator() -> Coordinator {
42 | Coordinator(self)
43 | }
44 |
45 | class Coordinator: NSObject {
46 | var parent: SVGView
47 | var lastLoadedString = ""
48 |
49 | init(_ parent: SVGView) {
50 | self.parent = parent
51 | }
52 | }
53 |
54 | init(svgString: Binding, darkmodeStyle: String = "") {
55 | let preferences = WKPreferences()
56 | preferences.javaScriptEnabled = false // JavaScript is not needed
57 | let config = WKWebViewConfiguration()
58 | config.preferences = preferences
59 |
60 | let webView = WKWebView(frame: CGRect(), configuration: config)
61 |
62 | webView.isOpaque = false
63 | webView.backgroundColor = .clear
64 | webView.isUserInteractionEnabled = false // to disable pinch gesture and scrolling
65 | self.webView = webView
66 | self._svgString = svgString
67 | self.darkmodeStyle = darkmodeStyle
68 | }
69 | }
70 |
71 | struct SVGView_Previews: PreviewProvider {
72 | static let darkmodeStyle =
73 | """
74 | svg {
75 | filter: grayscale(100%) invert(100%) brightness(200%);
76 | }
77 | """
78 | static var previews: some View {
79 | ForEach(ColorScheme.allCases, id: \.self) {
80 | SVGView(
81 | svgString: .constant(SVGExamples.stars),
82 | darkmodeStyle: Self.darkmodeStyle
83 | )
84 | .preferredColorScheme($0)
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples.xcodeproj/xcshareddata/xcschemes/UIViewRepresentableExamples.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/ScrollView/LegacyScrollView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | struct LegacyScrollView: UIViewRepresentable {
4 | enum Action {
5 | case idle
6 | case offset(x: CGFloat, y: CGFloat, animated: Bool)
7 | }
8 |
9 | let axis: Axis
10 | @Binding var action: Action
11 | private let uiScrollView: UIScrollView
12 |
13 | func makeCoordinator() -> Coordinator {
14 | Coordinator(self)
15 | }
16 |
17 | func makeUIView(context: Context) -> UIScrollView {
18 | return self.uiScrollView
19 | }
20 |
21 | func updateUIView(_ uiView: UIScrollView, context: Context) {
22 | switch self.action {
23 | case .offset(let x, let y, let animated):
24 | uiView.setContentOffset(CGPoint(x: x, y: y), animated: animated)
25 | DispatchQueue.main.async {
26 | self.action = .idle
27 | }
28 | default:
29 | break
30 | }
31 | }
32 |
33 | class Coordinator: NSObject {
34 | let legacyScrollView: LegacyScrollView
35 |
36 | init(_ legacyScrollView: LegacyScrollView) {
37 | self.legacyScrollView = legacyScrollView
38 | }
39 | }
40 |
41 | init(axis: Axis, action: Binding, @ViewBuilder content: () -> Content) {
42 | self.axis = axis
43 | self._action = action
44 | self.uiScrollView = UIScrollView()
45 |
46 | let hosting = UIHostingController(rootView: content())
47 | hosting.view.translatesAutoresizingMaskIntoConstraints = false
48 |
49 | self.uiScrollView.addSubview(hosting.view)
50 |
51 | let constraints: [NSLayoutConstraint]
52 | switch self.axis {
53 | case .horizontal:
54 | constraints = [
55 | hosting.view.leadingAnchor.constraint(equalTo: self.uiScrollView.contentLayoutGuide.leadingAnchor),
56 | hosting.view.trailingAnchor.constraint(equalTo: self.uiScrollView.contentLayoutGuide.trailingAnchor),
57 | hosting.view.topAnchor.constraint(equalTo: self.uiScrollView.topAnchor),
58 | hosting.view.bottomAnchor.constraint(equalTo: self.uiScrollView.bottomAnchor),
59 | hosting.view.heightAnchor.constraint(equalTo: self.uiScrollView.heightAnchor)
60 | ]
61 | case .vertical:
62 | constraints = [
63 | hosting.view.leadingAnchor.constraint(equalTo: self.uiScrollView.leadingAnchor),
64 | hosting.view.trailingAnchor.constraint(equalTo: self.uiScrollView.trailingAnchor),
65 | hosting.view.topAnchor.constraint(equalTo: self.uiScrollView.contentLayoutGuide.topAnchor),
66 | hosting.view.bottomAnchor.constraint(equalTo: self.uiScrollView.contentLayoutGuide.bottomAnchor),
67 | hosting.view.widthAnchor.constraint(equalTo: self.uiScrollView.widthAnchor)
68 | ]
69 | }
70 | self.uiScrollView.addConstraints(constraints)
71 | }
72 | }
73 |
74 | struct LegacyScrollView_Previews: PreviewProvider {
75 | @State static var action = LegacyScrollView.Action.offset(x: 100, y: 0, animated: false)
76 |
77 | static var previews: some View {
78 | LegacyScrollView(axis: .horizontal, action: self.$action) {
79 | Text(Constants.lipsum.joined(separator: "\n\n"))
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 50;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 8924D7DE2458A0B00010C4FE /* CameraExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8924D7DD2458A0B00010C4FE /* CameraExample.swift */; };
11 | 8924D7E02458A3920010C4FE /* CameraPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8924D7DF2458A3920010C4FE /* CameraPreview.swift */; };
12 | 8924D7E22458A4CD0010C4FE /* CameraPreviewWrapperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8924D7E12458A4CD0010C4FE /* CameraPreviewWrapperView.swift */; };
13 | 8924D7E42458A8480010C4FE /* DeviceCaptureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8924D7E32458A8480010C4FE /* DeviceCaptureView.swift */; };
14 | 896635EC23E0281500143527 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896635EB23E0281500143527 /* AppDelegate.swift */; };
15 | 896635EE23E0281500143527 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896635ED23E0281500143527 /* SceneDelegate.swift */; };
16 | 896635F023E0281500143527 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896635EF23E0281500143527 /* ContentView.swift */; };
17 | 896635F223E0281600143527 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 896635F123E0281600143527 /* Assets.xcassets */; };
18 | 896635F523E0281600143527 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 896635F423E0281600143527 /* Preview Assets.xcassets */; };
19 | 896635F823E0281600143527 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 896635F623E0281600143527 /* LaunchScreen.storyboard */; };
20 | 8966360023E0298600143527 /* Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896635FF23E0298600143527 /* Menu.swift */; };
21 | 8966360323E0359200143527 /* HTMLRenderingWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8966360223E0359200143527 /* HTMLRenderingWebView.swift */; };
22 | 8966360523E037C500143527 /* HTMLRenderingWebViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8966360423E037C500143527 /* HTMLRenderingWebViewExample.swift */; };
23 | 8975583023E9A2D500622733 /* LegacyScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8975582F23E9A2D500622733 /* LegacyScrollView.swift */; };
24 | 8975583223E9A3DD00622733 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8975583123E9A3DD00622733 /* Constants.swift */; };
25 | 8975583423E9B01100622733 /* LegacyScrollViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8975583323E9B01100622733 /* LegacyScrollViewExample.swift */; };
26 | 89CAE64223FB1AD100017997 /* SVGViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89CAE64123FB1AD100017997 /* SVGViewExample.swift */; };
27 | 89CAE64423FB1B2A00017997 /* SVGView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89CAE64323FB1B2A00017997 /* SVGView.swift */; };
28 | 89CAE64823FBC55000017997 /* SVGExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89CAE64723FBC55000017997 /* SVGExamples.swift */; };
29 | 89F328DC23E07A7C00B2CB1A /* MapKitExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F328DB23E07A7C00B2CB1A /* MapKitExample.swift */; };
30 | 89F328DE23E07E7E00B2CB1A /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F328DD23E07E7E00B2CB1A /* MapView.swift */; };
31 | 89F328E123E0804B00B2CB1A /* TextViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F328E023E0804B00B2CB1A /* TextViewExample.swift */; };
32 | 89F328E323E0808600B2CB1A /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89F328E223E0808600B2CB1A /* TextView.swift */; };
33 | /* End PBXBuildFile section */
34 |
35 | /* Begin PBXFileReference section */
36 | 8924D7DD2458A0B00010C4FE /* CameraExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraExample.swift; sourceTree = ""; };
37 | 8924D7DF2458A3920010C4FE /* CameraPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPreview.swift; sourceTree = ""; };
38 | 8924D7E12458A4CD0010C4FE /* CameraPreviewWrapperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPreviewWrapperView.swift; sourceTree = ""; };
39 | 8924D7E32458A8480010C4FE /* DeviceCaptureView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceCaptureView.swift; sourceTree = ""; };
40 | 896635E823E0281500143527 /* UIViewRepresentableExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIViewRepresentableExamples.app; sourceTree = BUILT_PRODUCTS_DIR; };
41 | 896635EB23E0281500143527 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
42 | 896635ED23E0281500143527 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
43 | 896635EF23E0281500143527 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
44 | 896635F123E0281600143527 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
45 | 896635F423E0281600143527 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
46 | 896635F723E0281600143527 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
47 | 896635F923E0281600143527 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
48 | 896635FF23E0298600143527 /* Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Menu.swift; sourceTree = ""; };
49 | 8966360223E0359200143527 /* HTMLRenderingWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLRenderingWebView.swift; sourceTree = ""; };
50 | 8966360423E037C500143527 /* HTMLRenderingWebViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLRenderingWebViewExample.swift; sourceTree = ""; };
51 | 8975582F23E9A2D500622733 /* LegacyScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyScrollView.swift; sourceTree = ""; };
52 | 8975583123E9A3DD00622733 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; };
53 | 8975583323E9B01100622733 /* LegacyScrollViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyScrollViewExample.swift; sourceTree = ""; };
54 | 89CAE64123FB1AD100017997 /* SVGViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SVGViewExample.swift; sourceTree = ""; };
55 | 89CAE64323FB1B2A00017997 /* SVGView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SVGView.swift; sourceTree = ""; };
56 | 89CAE64723FBC55000017997 /* SVGExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SVGExamples.swift; sourceTree = ""; };
57 | 89F328DB23E07A7C00B2CB1A /* MapKitExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapKitExample.swift; sourceTree = ""; };
58 | 89F328DD23E07E7E00B2CB1A /* MapView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = ""; };
59 | 89F328E023E0804B00B2CB1A /* TextViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextViewExample.swift; sourceTree = ""; };
60 | 89F328E223E0808600B2CB1A /* TextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextView.swift; sourceTree = ""; };
61 | /* End PBXFileReference section */
62 |
63 | /* Begin PBXFrameworksBuildPhase section */
64 | 896635E523E0281500143527 /* Frameworks */ = {
65 | isa = PBXFrameworksBuildPhase;
66 | buildActionMask = 2147483647;
67 | files = (
68 | );
69 | runOnlyForDeploymentPostprocessing = 0;
70 | };
71 | /* End PBXFrameworksBuildPhase section */
72 |
73 | /* Begin PBXGroup section */
74 | 8924D7DC2458A09F0010C4FE /* Camera */ = {
75 | isa = PBXGroup;
76 | children = (
77 | 8924D7DD2458A0B00010C4FE /* CameraExample.swift */,
78 | 8924D7DF2458A3920010C4FE /* CameraPreview.swift */,
79 | 8924D7E12458A4CD0010C4FE /* CameraPreviewWrapperView.swift */,
80 | 8924D7E32458A8480010C4FE /* DeviceCaptureView.swift */,
81 | );
82 | path = Camera;
83 | sourceTree = "";
84 | };
85 | 896635DF23E0281500143527 = {
86 | isa = PBXGroup;
87 | children = (
88 | 896635EA23E0281500143527 /* UIViewRepresentableExamples */,
89 | 896635E923E0281500143527 /* Products */,
90 | );
91 | sourceTree = "";
92 | };
93 | 896635E923E0281500143527 /* Products */ = {
94 | isa = PBXGroup;
95 | children = (
96 | 896635E823E0281500143527 /* UIViewRepresentableExamples.app */,
97 | );
98 | name = Products;
99 | sourceTree = "";
100 | };
101 | 896635EA23E0281500143527 /* UIViewRepresentableExamples */ = {
102 | isa = PBXGroup;
103 | children = (
104 | 8924D7DC2458A09F0010C4FE /* Camera */,
105 | 89CAE64023FB1AA200017997 /* SVGView */,
106 | 8975582C23E9985400622733 /* ScrollView */,
107 | 89F328DF23E0802A00B2CB1A /* TextView */,
108 | 89F328DA23E07A7000B2CB1A /* MapKit */,
109 | 8966360123E0357700143527 /* HTMLRenderingWebView */,
110 | 896635EB23E0281500143527 /* AppDelegate.swift */,
111 | 896635ED23E0281500143527 /* SceneDelegate.swift */,
112 | 8975583123E9A3DD00622733 /* Constants.swift */,
113 | 896635EF23E0281500143527 /* ContentView.swift */,
114 | 896635FF23E0298600143527 /* Menu.swift */,
115 | 896635F123E0281600143527 /* Assets.xcassets */,
116 | 896635F623E0281600143527 /* LaunchScreen.storyboard */,
117 | 896635F923E0281600143527 /* Info.plist */,
118 | 896635F323E0281600143527 /* Preview Content */,
119 | );
120 | path = UIViewRepresentableExamples;
121 | sourceTree = "";
122 | };
123 | 896635F323E0281600143527 /* Preview Content */ = {
124 | isa = PBXGroup;
125 | children = (
126 | 896635F423E0281600143527 /* Preview Assets.xcassets */,
127 | );
128 | path = "Preview Content";
129 | sourceTree = "";
130 | };
131 | 8966360123E0357700143527 /* HTMLRenderingWebView */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 8966360223E0359200143527 /* HTMLRenderingWebView.swift */,
135 | 8966360423E037C500143527 /* HTMLRenderingWebViewExample.swift */,
136 | );
137 | path = HTMLRenderingWebView;
138 | sourceTree = "";
139 | };
140 | 8975582C23E9985400622733 /* ScrollView */ = {
141 | isa = PBXGroup;
142 | children = (
143 | 8975583323E9B01100622733 /* LegacyScrollViewExample.swift */,
144 | 8975582F23E9A2D500622733 /* LegacyScrollView.swift */,
145 | );
146 | path = ScrollView;
147 | sourceTree = "";
148 | };
149 | 89CAE64023FB1AA200017997 /* SVGView */ = {
150 | isa = PBXGroup;
151 | children = (
152 | 89CAE64123FB1AD100017997 /* SVGViewExample.swift */,
153 | 89CAE64323FB1B2A00017997 /* SVGView.swift */,
154 | 89CAE64723FBC55000017997 /* SVGExamples.swift */,
155 | );
156 | path = SVGView;
157 | sourceTree = "";
158 | };
159 | 89F328DA23E07A7000B2CB1A /* MapKit */ = {
160 | isa = PBXGroup;
161 | children = (
162 | 89F328DB23E07A7C00B2CB1A /* MapKitExample.swift */,
163 | 89F328DD23E07E7E00B2CB1A /* MapView.swift */,
164 | );
165 | path = MapKit;
166 | sourceTree = "";
167 | };
168 | 89F328DF23E0802A00B2CB1A /* TextView */ = {
169 | isa = PBXGroup;
170 | children = (
171 | 89F328E023E0804B00B2CB1A /* TextViewExample.swift */,
172 | 89F328E223E0808600B2CB1A /* TextView.swift */,
173 | );
174 | path = TextView;
175 | sourceTree = "";
176 | };
177 | /* End PBXGroup section */
178 |
179 | /* Begin PBXNativeTarget section */
180 | 896635E723E0281500143527 /* UIViewRepresentableExamples */ = {
181 | isa = PBXNativeTarget;
182 | buildConfigurationList = 896635FC23E0281600143527 /* Build configuration list for PBXNativeTarget "UIViewRepresentableExamples" */;
183 | buildPhases = (
184 | 896635E423E0281500143527 /* Sources */,
185 | 896635E523E0281500143527 /* Frameworks */,
186 | 896635E623E0281500143527 /* Resources */,
187 | );
188 | buildRules = (
189 | );
190 | dependencies = (
191 | );
192 | name = UIViewRepresentableExamples;
193 | productName = UIViewRepresentableExamples;
194 | productReference = 896635E823E0281500143527 /* UIViewRepresentableExamples.app */;
195 | productType = "com.apple.product-type.application";
196 | };
197 | /* End PBXNativeTarget section */
198 |
199 | /* Begin PBXProject section */
200 | 896635E023E0281500143527 /* Project object */ = {
201 | isa = PBXProject;
202 | attributes = {
203 | LastSwiftUpdateCheck = 1130;
204 | LastUpgradeCheck = 1130;
205 | ORGANIZATIONNAME = DutchVirtual;
206 | TargetAttributes = {
207 | 896635E723E0281500143527 = {
208 | CreatedOnToolsVersion = 11.3.1;
209 | };
210 | };
211 | };
212 | buildConfigurationList = 896635E323E0281500143527 /* Build configuration list for PBXProject "UIViewRepresentableExamples" */;
213 | compatibilityVersion = "Xcode 9.3";
214 | developmentRegion = en;
215 | hasScannedForEncodings = 0;
216 | knownRegions = (
217 | en,
218 | Base,
219 | );
220 | mainGroup = 896635DF23E0281500143527;
221 | productRefGroup = 896635E923E0281500143527 /* Products */;
222 | projectDirPath = "";
223 | projectRoot = "";
224 | targets = (
225 | 896635E723E0281500143527 /* UIViewRepresentableExamples */,
226 | );
227 | };
228 | /* End PBXProject section */
229 |
230 | /* Begin PBXResourcesBuildPhase section */
231 | 896635E623E0281500143527 /* Resources */ = {
232 | isa = PBXResourcesBuildPhase;
233 | buildActionMask = 2147483647;
234 | files = (
235 | 896635F823E0281600143527 /* LaunchScreen.storyboard in Resources */,
236 | 896635F523E0281600143527 /* Preview Assets.xcassets in Resources */,
237 | 896635F223E0281600143527 /* Assets.xcassets in Resources */,
238 | );
239 | runOnlyForDeploymentPostprocessing = 0;
240 | };
241 | /* End PBXResourcesBuildPhase section */
242 |
243 | /* Begin PBXSourcesBuildPhase section */
244 | 896635E423E0281500143527 /* Sources */ = {
245 | isa = PBXSourcesBuildPhase;
246 | buildActionMask = 2147483647;
247 | files = (
248 | 89CAE64223FB1AD100017997 /* SVGViewExample.swift in Sources */,
249 | 8966360523E037C500143527 /* HTMLRenderingWebViewExample.swift in Sources */,
250 | 8924D7E22458A4CD0010C4FE /* CameraPreviewWrapperView.swift in Sources */,
251 | 89F328DE23E07E7E00B2CB1A /* MapView.swift in Sources */,
252 | 8924D7E02458A3920010C4FE /* CameraPreview.swift in Sources */,
253 | 8966360323E0359200143527 /* HTMLRenderingWebView.swift in Sources */,
254 | 89F328DC23E07A7C00B2CB1A /* MapKitExample.swift in Sources */,
255 | 896635EC23E0281500143527 /* AppDelegate.swift in Sources */,
256 | 89CAE64423FB1B2A00017997 /* SVGView.swift in Sources */,
257 | 896635EE23E0281500143527 /* SceneDelegate.swift in Sources */,
258 | 8966360023E0298600143527 /* Menu.swift in Sources */,
259 | 896635F023E0281500143527 /* ContentView.swift in Sources */,
260 | 89CAE64823FBC55000017997 /* SVGExamples.swift in Sources */,
261 | 8924D7E42458A8480010C4FE /* DeviceCaptureView.swift in Sources */,
262 | 89F328E123E0804B00B2CB1A /* TextViewExample.swift in Sources */,
263 | 89F328E323E0808600B2CB1A /* TextView.swift in Sources */,
264 | 8924D7DE2458A0B00010C4FE /* CameraExample.swift in Sources */,
265 | 8975583023E9A2D500622733 /* LegacyScrollView.swift in Sources */,
266 | 8975583223E9A3DD00622733 /* Constants.swift in Sources */,
267 | 8975583423E9B01100622733 /* LegacyScrollViewExample.swift in Sources */,
268 | );
269 | runOnlyForDeploymentPostprocessing = 0;
270 | };
271 | /* End PBXSourcesBuildPhase section */
272 |
273 | /* Begin PBXVariantGroup section */
274 | 896635F623E0281600143527 /* LaunchScreen.storyboard */ = {
275 | isa = PBXVariantGroup;
276 | children = (
277 | 896635F723E0281600143527 /* Base */,
278 | );
279 | name = LaunchScreen.storyboard;
280 | sourceTree = "";
281 | };
282 | /* End PBXVariantGroup section */
283 |
284 | /* Begin XCBuildConfiguration section */
285 | 896635FA23E0281600143527 /* Debug */ = {
286 | isa = XCBuildConfiguration;
287 | buildSettings = {
288 | ALWAYS_SEARCH_USER_PATHS = NO;
289 | CLANG_ANALYZER_NONNULL = YES;
290 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
292 | CLANG_CXX_LIBRARY = "libc++";
293 | CLANG_ENABLE_MODULES = YES;
294 | CLANG_ENABLE_OBJC_ARC = YES;
295 | CLANG_ENABLE_OBJC_WEAK = YES;
296 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
297 | CLANG_WARN_BOOL_CONVERSION = YES;
298 | CLANG_WARN_COMMA = YES;
299 | CLANG_WARN_CONSTANT_CONVERSION = YES;
300 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
301 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
302 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
303 | CLANG_WARN_EMPTY_BODY = YES;
304 | CLANG_WARN_ENUM_CONVERSION = YES;
305 | CLANG_WARN_INFINITE_RECURSION = YES;
306 | CLANG_WARN_INT_CONVERSION = YES;
307 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
308 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
309 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
310 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
311 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
312 | CLANG_WARN_STRICT_PROTOTYPES = YES;
313 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
314 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
315 | CLANG_WARN_UNREACHABLE_CODE = YES;
316 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
317 | COPY_PHASE_STRIP = NO;
318 | DEBUG_INFORMATION_FORMAT = dwarf;
319 | ENABLE_STRICT_OBJC_MSGSEND = YES;
320 | ENABLE_TESTABILITY = YES;
321 | GCC_C_LANGUAGE_STANDARD = gnu11;
322 | GCC_DYNAMIC_NO_PIC = NO;
323 | GCC_NO_COMMON_BLOCKS = YES;
324 | GCC_OPTIMIZATION_LEVEL = 0;
325 | GCC_PREPROCESSOR_DEFINITIONS = (
326 | "DEBUG=1",
327 | "$(inherited)",
328 | );
329 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
330 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
331 | GCC_WARN_UNDECLARED_SELECTOR = YES;
332 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
333 | GCC_WARN_UNUSED_FUNCTION = YES;
334 | GCC_WARN_UNUSED_VARIABLE = YES;
335 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
336 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
337 | MTL_FAST_MATH = YES;
338 | ONLY_ACTIVE_ARCH = YES;
339 | SDKROOT = iphoneos;
340 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
341 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
342 | };
343 | name = Debug;
344 | };
345 | 896635FB23E0281600143527 /* Release */ = {
346 | isa = XCBuildConfiguration;
347 | buildSettings = {
348 | ALWAYS_SEARCH_USER_PATHS = NO;
349 | CLANG_ANALYZER_NONNULL = YES;
350 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
352 | CLANG_CXX_LIBRARY = "libc++";
353 | CLANG_ENABLE_MODULES = YES;
354 | CLANG_ENABLE_OBJC_ARC = YES;
355 | CLANG_ENABLE_OBJC_WEAK = YES;
356 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
357 | CLANG_WARN_BOOL_CONVERSION = YES;
358 | CLANG_WARN_COMMA = YES;
359 | CLANG_WARN_CONSTANT_CONVERSION = YES;
360 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
361 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
362 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
363 | CLANG_WARN_EMPTY_BODY = YES;
364 | CLANG_WARN_ENUM_CONVERSION = YES;
365 | CLANG_WARN_INFINITE_RECURSION = YES;
366 | CLANG_WARN_INT_CONVERSION = YES;
367 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
368 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
369 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
370 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
371 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
372 | CLANG_WARN_STRICT_PROTOTYPES = YES;
373 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
374 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
375 | CLANG_WARN_UNREACHABLE_CODE = YES;
376 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
377 | COPY_PHASE_STRIP = NO;
378 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
379 | ENABLE_NS_ASSERTIONS = NO;
380 | ENABLE_STRICT_OBJC_MSGSEND = YES;
381 | GCC_C_LANGUAGE_STANDARD = gnu11;
382 | GCC_NO_COMMON_BLOCKS = YES;
383 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
384 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
385 | GCC_WARN_UNDECLARED_SELECTOR = YES;
386 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
387 | GCC_WARN_UNUSED_FUNCTION = YES;
388 | GCC_WARN_UNUSED_VARIABLE = YES;
389 | IPHONEOS_DEPLOYMENT_TARGET = 13.2;
390 | MTL_ENABLE_DEBUG_INFO = NO;
391 | MTL_FAST_MATH = YES;
392 | SDKROOT = iphoneos;
393 | SWIFT_COMPILATION_MODE = wholemodule;
394 | SWIFT_OPTIMIZATION_LEVEL = "-O";
395 | VALIDATE_PRODUCT = YES;
396 | };
397 | name = Release;
398 | };
399 | 896635FD23E0281600143527 /* Debug */ = {
400 | isa = XCBuildConfiguration;
401 | buildSettings = {
402 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
403 | CODE_SIGN_STYLE = Automatic;
404 | DEVELOPMENT_ASSET_PATHS = "\"UIViewRepresentableExamples/Preview Content\"";
405 | DEVELOPMENT_TEAM = 8LG5SA5X3R;
406 | ENABLE_PREVIEWS = YES;
407 | INFOPLIST_FILE = UIViewRepresentableExamples/Info.plist;
408 | LD_RUNPATH_SEARCH_PATHS = (
409 | "$(inherited)",
410 | "@executable_path/Frameworks",
411 | );
412 | PRODUCT_BUNDLE_IDENTIFIER = nl.vankuik.UIViewRepresentableExamples;
413 | PRODUCT_NAME = "$(TARGET_NAME)";
414 | SWIFT_VERSION = 5.0;
415 | TARGETED_DEVICE_FAMILY = "1,2";
416 | };
417 | name = Debug;
418 | };
419 | 896635FE23E0281600143527 /* Release */ = {
420 | isa = XCBuildConfiguration;
421 | buildSettings = {
422 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
423 | CODE_SIGN_STYLE = Automatic;
424 | DEVELOPMENT_ASSET_PATHS = "\"UIViewRepresentableExamples/Preview Content\"";
425 | DEVELOPMENT_TEAM = 8LG5SA5X3R;
426 | ENABLE_PREVIEWS = YES;
427 | INFOPLIST_FILE = UIViewRepresentableExamples/Info.plist;
428 | LD_RUNPATH_SEARCH_PATHS = (
429 | "$(inherited)",
430 | "@executable_path/Frameworks",
431 | );
432 | PRODUCT_BUNDLE_IDENTIFIER = nl.vankuik.UIViewRepresentableExamples;
433 | PRODUCT_NAME = "$(TARGET_NAME)";
434 | SWIFT_VERSION = 5.0;
435 | TARGETED_DEVICE_FAMILY = "1,2";
436 | };
437 | name = Release;
438 | };
439 | /* End XCBuildConfiguration section */
440 |
441 | /* Begin XCConfigurationList section */
442 | 896635E323E0281500143527 /* Build configuration list for PBXProject "UIViewRepresentableExamples" */ = {
443 | isa = XCConfigurationList;
444 | buildConfigurations = (
445 | 896635FA23E0281600143527 /* Debug */,
446 | 896635FB23E0281600143527 /* Release */,
447 | );
448 | defaultConfigurationIsVisible = 0;
449 | defaultConfigurationName = Release;
450 | };
451 | 896635FC23E0281600143527 /* Build configuration list for PBXNativeTarget "UIViewRepresentableExamples" */ = {
452 | isa = XCConfigurationList;
453 | buildConfigurations = (
454 | 896635FD23E0281600143527 /* Debug */,
455 | 896635FE23E0281600143527 /* Release */,
456 | );
457 | defaultConfigurationIsVisible = 0;
458 | defaultConfigurationName = Release;
459 | };
460 | /* End XCConfigurationList section */
461 | };
462 | rootObject = 896635E023E0281500143527 /* Project object */;
463 | }
464 |
--------------------------------------------------------------------------------
/UIViewRepresentableExamples/Assets.xcassets/Ghostscript_Tiger.dataset/Ghostscript_Tiger.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------