Skip to content

Instantly share code, notes, and snippets.

@pookjw
Last active March 14, 2024 10:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pookjw/78ce2ff52905105a1796d53b90d55a41 to your computer and use it in GitHub Desktop.
Save pookjw/78ce2ff52905105a1796d53b90d55a41 to your computer and use it in GitHub Desktop.
UIHostingConfiguration for iOS 14 & 15
import UIKit
import SwiftUI
struct BPHostingConfiguration<Content: View>: UIContentConfiguration {
fileprivate let content: Content
init(@ViewBuilder content: () -> Content) {
self.content = content()
}
func makeContentView() -> any UIView & UIContentView {
HostingView<Content>(configuration: self)
}
func updated(for state: any UIConfigurationState) -> BPHostingConfiguration {
return self
}
}
fileprivate final class HostingView<Content: View>: UIView, UIContentView {
private let hostingController: UIHostingController<Content>
private var _configuration: BPHostingConfiguration<Content>
var configuration: any UIContentConfiguration {
@storageRestrictions(initializes: _configuration, hostingController)
init(newValue) {
let configuration: BPHostingConfiguration<Content> = newValue as! BPHostingConfiguration<Content>
_configuration = configuration as! BPHostingConfiguration
hostingController = .init(rootView: configuration.content)
}
get {
_configuration
}
set {
let configuration: BPHostingConfiguration<Content> = newValue as! BPHostingConfiguration<Content>
_configuration = configuration
hostingController.rootView = configuration.content
}
}
init(configuration: any UIContentConfiguration) {
self.configuration = configuration
super.init(frame: .null)
let hostingView: UIView = hostingController.view
hostingView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(hostingView)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
@pookjw
Copy link
Author

pookjw commented Mar 14, 2024

Example

import UIKit
import SwiftUI

class CollectionViewController: UICollectionViewController {
    private let cellRegistration: UICollectionView.CellRegistration<UICollectionViewListCell, NSNull> = .init { cell, indexPath, itemIdentifier in
        cell.contentConfiguration = BPHostingConfiguration  { 
            Text(indexPath.description)
        }
    }
    
    init() {
        let listConfiguration: UICollectionLayoutListConfiguration = .init(appearance: .insetGrouped)
        let collectionViewLayout: UICollectionViewCompositionalLayout = .list(using: listConfiguration)
        super.init(collectionViewLayout: collectionViewLayout)
    }
    
    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }


    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 300
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: nil)
    }
}

Simulator Screenshot - iPhone 15 Pro Max - 2024-03-14 at 19 13 58

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment