Skip to content
This repository has been archived by the owner on Aug 11, 2024. It is now read-only.

Commit

Permalink
Add UIHostingView (#981)
Browse files Browse the repository at this point in the history
...a helper view that makes it easier to embed UIHostingControllers in a
parent view. Pass a parent controller into the initalizer, along with
the UIHostingController. It will add the UIHostingController to the
parent controller, and remove the UIHostingController from the parent
controller when the UIView is deinitialized.

This should make it easier for us to embed SwiftUI views in the block
editor.

Part of epic #214.
  • Loading branch information
gordonbrander authored Nov 3, 2023
1 parent 699dc7d commit 35e474f
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
95 changes: 95 additions & 0 deletions xcode/Subconscious/Shared/UIKit/UIHostingView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//
// UIHostingView.swift
// Subconscious (iOS)
//
// Created by Gordon Brander on 11/2/23.
//

import Foundation
import SwiftUI
import UIKit

// See here for another approach https://github.com/SwiftUIX/SwiftUIX/blob/master/Sources/Intermodular/Helpers/UIKit/UIHostingView.swift

// Get a view for a UIHostingController
// Assigns the UIHostingController to a parent controller
class UIHostingView<Content: View>: UIView {
/// A reference to the hosting controller for this UIHostingView.
/// We use this to remove hostingController from the parent controller
/// on deinit.
private var hostingController: UIHostingController<Content>

init(
frame: CGRect = .zero,
parent: UIViewController?,
hostingController: UIHostingController<Content>
) {
self.hostingController = hostingController
super.init(frame: frame)

// Add hosting controller to parent controller
if let parent = parent {
parent.addChild(hostingController)
}

// Add hosting controler view to this view
self.addSubview(hostingController.view)

// Set hosting controller view constraints to match this view's
// constraints.
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
hostingController.view.leadingAnchor.constraint(
equalTo: self.leadingAnchor
),
hostingController.view.trailingAnchor.constraint(
equalTo: self.trailingAnchor
),
hostingController.view.topAnchor.constraint(
equalTo: self.topAnchor
),
hostingController.view.bottomAnchor.constraint(
equalTo: self.bottomAnchor
)
])

// Notify hosting controller it moved to parent
// See https://developer.apple.com/documentation/uikit/view_controllers/creating_a_custom_container_view_controller
hostingController.didMove(toParent: parent)
}

convenience init(
frame: CGRect = .zero,
parent: UIViewController?,
view: Content
) {
self.init(
parent: parent,
hostingController: UIHostingController(rootView: view)
)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

deinit {
guard hostingController.parent != nil else {
return
}
hostingController.willMove(toParent: nil)
hostingController.view.removeFromSuperview()
hostingController.removeFromParent()
}
}

struct UIHostingView_Previews: PreviewProvider {
static var previews: some View {
UIViewPreviewRepresentable {
UIHostingView(
parent: nil,
view: Text("Hello from SwiftUI")
)
}
}
}
4 changes: 4 additions & 0 deletions xcode/Subconscious/Subconscious.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@
B89966C728B6EE2300DF1F8C /* Notebook.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89966C628B6EE2300DF1F8C /* Notebook.swift */; };
B89966C828B6EE2300DF1F8C /* Notebook.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89966C628B6EE2300DF1F8C /* Notebook.swift */; };
B89DBDDA2AF3EF3D003D2CE3 /* Tests_StringSplitAtRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89DBDD92AF3EF3D003D2CE3 /* Tests_StringSplitAtRange.swift */; };
B89DBDE02AF440C6003D2CE3 /* UIHostingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89DBDDF2AF440C6003D2CE3 /* UIHostingView.swift */; };
B89E30772911B51A00A4721F /* Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89E30762911B51A00A4721F /* Migration.swift */; };
B89E30782911B51A00A4721F /* Migration.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89E30762911B51A00A4721F /* Migration.swift */; };
B89E307D2911D7F900A4721F /* IntUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89E307C2911D7F900A4721F /* IntUtilities.swift */; };
Expand Down Expand Up @@ -735,6 +736,7 @@
B8925B3029C2320D001F9503 /* MemoDetailDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoDetailDescription.swift; sourceTree = "<group>"; };
B89966C628B6EE2300DF1F8C /* Notebook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notebook.swift; sourceTree = "<group>"; };
B89DBDD92AF3EF3D003D2CE3 /* Tests_StringSplitAtRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_StringSplitAtRange.swift; sourceTree = "<group>"; };
B89DBDDF2AF440C6003D2CE3 /* UIHostingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIHostingView.swift; sourceTree = "<group>"; };
B89E30762911B51A00A4721F /* Migration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Migration.swift; sourceTree = "<group>"; };
B89E307C2911D7F900A4721F /* IntUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntUtilities.swift; sourceTree = "<group>"; };
B8A1621329B2AB3A008322EB /* CloseButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseButtonView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1255,6 +1257,7 @@
B83E0E282A9D13CE009F18AE /* BlockEditor */,
B8AB08C92A9D518800998099 /* UIBarButtonItemUtilities.swift */,
B8CAF2102A9E89A30057D5DE /* UIFontHelpers.swift */,
B89DBDDF2AF440C6003D2CE3 /* UIHostingView.swift */,
B86DD5712AA0D33E00E1DEA5 /* UIStackViewHelpers.swift */,
B8AB08D52A9D52B300998099 /* UITextViewHelpers.swift */,
B8AB08CF2A9D522D00998099 /* UIViewDivider.swift */,
Expand Down Expand Up @@ -2203,6 +2206,7 @@
B86DFF2D27C0280B002E57ED /* EntryListView.swift in Sources */,
B8AB08BD2A9D502C00998099 /* ListBlockCell.swift in Sources */,
B86DFF3927C15B77002E57ED /* Config.swift in Sources */,
B89DBDE02AF440C6003D2CE3 /* UIHostingView.swift in Sources */,
B57D63BB29B1CA8B008BBB62 /* DidView.swift in Sources */,
B83E91D727692EC600045C6A /* FAB.swift in Sources */,
B848FDAA2991837900245115 /* DeveloperSettingsView.swift in Sources */,
Expand Down

0 comments on commit 35e474f

Please sign in to comment.