Skip to content

Instantly share code, notes, and snippets.

@cozzin
Last active August 14, 2021 09:02
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 cozzin/b55ec5a894ad8e7a1a5f8e08fecfc19a to your computer and use it in GitHub Desktop.
Save cozzin/b55ec5a894ad8e7a1a5f8e08fecfc19a to your computer and use it in GitHub Desktop.
UIHostingCell
@available(iOS 13.0, *)
final class FixedSafeAreaInsetsHostingViewController<Content: SwiftUI.View>: UIHostingController<Content> {
override var prefersStatusBarHidden: Bool {
return false
}
override init(rootView: Content) {
super.init(rootView: rootView)
UIView.classInit
}
@objc required dynamic init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIView {
fileprivate static let classInit: Void = {
guard let originalSafeAreaInsets = class_getInstanceMethod(UIView.self, #selector(getter: UIView.safeAreaInsets)),
let fixedSafeAreaInsets = class_getInstanceMethod(UIView.self, #selector(fix_safeAreaInsets)) else {
return
}
guard let originalSafeAreaLayoutGuide = class_getInstanceMethod(UIView.self, #selector(getter: UIView.safeAreaLayoutGuide)),
let fixedSafeAreaLayoutGuide = class_getInstanceMethod(UIView.self, #selector(fix_safeAreaLayoutGuide)) else {
return
}
method_exchangeImplementations(originalSafeAreaInsets, fixedSafeAreaInsets)
method_exchangeImplementations(originalSafeAreaLayoutGuide, fixedSafeAreaLayoutGuide)
}()
private var isHostingView: Bool {
// _TtGC7SwiftUI14_UIHostingViewGSqV3Edu15PageWordRowItem__
let className = NSStringFromClass(classForCoder)
return className.contains("SwiftUI") && className.contains("_UIHostingView")
}
private var isNeedFixSafeArea: Bool {
guard let next = next, NSStringFromClass(next.classForCoder).contains("FixedSafeAreaInsetsHostingViewController") else {
return false
}
return isHostingView
}
@objc private func fix_safeAreaInsets() -> UIEdgeInsets {
isNeedFixSafeArea ? .zero : fix_safeAreaInsets()
}
@objc private func fix_safeAreaLayoutGuide() -> UILayoutGuide? {
isNeedFixSafeArea ? nil : fix_safeAreaLayoutGuide()
}
}
import UIKit
import SwiftUI
@available(iOS 14.0, *)
public final class UIHostingCell<Content>: UITableViewCell where Content: View {
private let hostingController = UIHostingController<Content?>(rootView: nil)
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(hostingController.view)
hostingController.view.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
hostingController.view.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
hostingController.view.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
hostingController.view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public override func prepareForReuse() {
super.prepareForReuse()
hostingController.rootView = nil
}
public func configure(with view: Content) {
hostingController.rootView = view
setNeedsLayout()
}
}
import UIKit
import SwiftUI
@available(iOS 14.0, *)
public final class UIHostingCell<Content>: UITableViewCell where Content: View {
// ...생략...
public override func prepareForReuse() {
super.prepareForReuse()
hostingController.willMove(toParent: nil)
hostingController.rootView = nil
hostingController.removeFromParent()
}
public func configure(view: Content, parent: UIViewController?) {
parent?.addChild(hostingController)
hostingController.rootView = view
hostingController.view.invalidateIntrinsicContentSize()
hostingController.didMove(toParent: parent)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment