Last active
April 3, 2025 09:58
-
-
Save rlnucci/31f116763d001ec2a93d30473703e117 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Foundation | |
| import SwiftUI | |
| // Implemented based on this article: | |
| // https://noahgilmore.com/blog/swiftui-self-sizing-cells | |
| // MARK: - HostingTableViewCell | |
| public final class HostingTableViewCell<Content: View>: UITableViewCell { | |
| private var hostingController = UIHostingController<Content?>(rootView: nil) | |
| public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { | |
| super.init(style: style, reuseIdentifier: reuseIdentifier) | |
| backgroundColor = .clear | |
| contentView.backgroundColor = .clear | |
| hostingController.view.backgroundColor = .clear | |
| } | |
| required init?(coder: NSCoder) { | |
| fatalError("init(coder:) is not supported") | |
| } | |
| public override func prepareForReuse() { | |
| super.prepareForReuse() | |
| hostingController.view.removeFromSuperview() | |
| hostingController = UIHostingController<Content?>(rootView: nil) | |
| } | |
| } | |
| // MARK: Public Methods | |
| public extension HostingTableViewCell { | |
| func set(rootView: Content, parentViewController: UIViewController) { | |
| hostingController = UIHostingController(rootView: rootView) | |
| hostingController.view.invalidateIntrinsicContentSize() | |
| let shouldMoveParentViewController = hostingController.parent != parentViewController | |
| if shouldMoveParentViewController { | |
| parentViewController.addChild(hostingController) | |
| } | |
| if hostingController.view.superview == nil { | |
| hostingController.view.translatesAutoresizingMaskIntoConstraints = false | |
| contentView.addSubview(hostingController.view) | |
| hostingController.view.constrainToSuperview() | |
| } | |
| if shouldMoveParentViewController { | |
| hostingController.didMove(toParent: parentViewController) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Foundation | |
| import UIKit | |
| import SwiftUI | |
| // MARK: PaymentSuccessViewController | |
| final class PaymentSuccessViewController: UIHostingController<PaymentSuccessView> { | |
| init(viewModel: PaymentSuccessViewModelImpl) { | |
| let rootView = PaymentSuccessView(viewModel: viewModel.eraseToAnyViewModel()) | |
| super.init(rootView: rootView) | |
| self.navigationItem.hidesBackButton = true | |
| viewModel.delegate = self | |
| } | |
| @objc required dynamic init?(coder aDecoder: NSCoder) { | |
| fatalError("init(coder:) is not supported") | |
| } | |
| } | |
| extension PaymentSuccessViewController: PaymentSuccessViewModelDelegate { | |
| func showAcountView() { | |
| viewHierarchyNavigator?.presentAccount() | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import UIKit | |
| import SwiftUI | |
| public struct TableCellWrapper<Cell>: UIViewRepresentable where Cell: UITableViewCell { | |
| public typealias UIViewType = Cell | |
| let cellType: Cell.Type | |
| let configure: ((Cell) -> Void)? | |
| public init(cellType: Cell.Type, configure: ((Cell) -> Void)? = nil) { | |
| self.cellType = cellType | |
| self.configure = configure | |
| } | |
| public func makeUIView(context: Context) -> Cell { | |
| let bundle = Bundle(for: Cell.self) | |
| let cell: Cell | |
| if bundle.path(forResource: Cell.nibName, ofType: "nib") != nil { | |
| let nib = UINib(nibName: Cell.nibName, bundle: bundle) | |
| cell = nib.instantiate(withOwner: nil, options: nil).first as! Cell | |
| } else { | |
| cell = Cell() | |
| } | |
| configure?(cell) | |
| return cell | |
| } | |
| public func updateUIView(_ uiView: Cell, context: Context) { | |
| uiView.prepareForReuse() | |
| configure?(uiView) | |
| } | |
| } |
@betraying , can't check right now, but I believe that will again re-render all of the table. Ideally there should be a way to keep the existing hostingController instance around instead of creating a new one each time
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@ULazdins
In my case, your code did not work properly. Sometimes, the reuse functionality did not work correctly.
However, if I add
hostingController = UIHostingController<Content?>(rootView: nil), then everything works fine