在 UITableViewCell 内部的 UIView 上添加 SwiftUI [重复]

Posted

技术标签:

【中文标题】在 UITableViewCell 内部的 UIView 上添加 SwiftUI [重复]【英文标题】:Add SwiftUI on a UIView which is Inside of a UITableViewCell [duplicate] 【发布时间】:2021-12-04 21:21:42 【问题描述】:

如何在 UITableViewCell 内部的 UIView 上添加 SwiftUI,通常使用 uihostingcontroller 可以将 SwiftUI 视图作为子级添加到 ViewController 但我们该怎么做这在 UITableViewCell

【问题讨论】:

【参考方案1】:

我能够得到这样的工作:

import UIKit
import SwiftUI
import PlaygroundSupport

let cellIdentifier = "Swift Content"

struct CellContent : View 
    let title : String

    init(title: String) 
        self.title = title
    

    var body : some View 
        Text(title)
    


class SwiftUITableCell : UITableViewCell 
    var swiftContent = UIHostingController(rootView: CellContent(title: "Placeholder"))


let tableView = UITableView(frame: CGRect(x: 0,y: 0,width: 320,height: 480))
let dataSource = UITableViewDiffableDataSource<Int,String>(tableView: tableView) 
    (tableView: UITableView, indexPath: IndexPath, itemIdentifier: String) -> UITableViewCell? in
    let newCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as!SwiftUITableCell

    newCell.swiftContent = UIHostingController.init(rootView: CellContent(title: itemIdentifier))
    newCell.swiftContent.view.frame = newCell.contentView.bounds.inset(by: UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4))
    newCell.contentView.addSubview(newCell.swiftContent.view)

    return newCell


tableView.register(SwiftUITableCell.self, forCellReuseIdentifier: cellIdentifier)
tableView.dataSource = dataSource

var currentSnapshot = NSDiffableDataSourceSnapshot<Int, String>()
currentSnapshot.appendSections([0])
currentSnapshot.appendItems(["Foo", "Bar", "Baz"], toSection: 0)
dataSource.apply(currentSnapshot)

PlaygroundSupport.PlaygroundPage.current.liveView = tableView

为了使这更加“真实”,您必须设置您的 swift 视图来处理UITableViewCell 可能发生的所有各种配置更改。

【讨论】:

【参考方案2】:

使用 @Binding 更新状态

import SwiftUI
import UIKit

class TableTestVC: UIViewController, UITableViewDataSource, UITableViewDelegate 
    @IBOutlet weak var tableView: UITableView!
    var count = 50

    let demo = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."

    override func viewDidLoad() 
        super.viewDidLoad()

        tableView.register(TableTestCell.self, forCellReuseIdentifier: "TableTestCell")
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let range = (0 ... demo.count).randomElement() ?? 0
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableTestCell") as! TableTestCell
        cell.label = String(demo.prefix(range))
        return cell
    

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return count
    


class TableTestCell: UITableViewCell 
    lazy var view = TableTestCellView(label: self.labelBinder)
    var label: String = "none"

    lazy var labelBinder = Binding  self.label  set:  self.label = $0 

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) 
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        let sub = UIHostingController(rootView: view).view!
        contentView.addSubview(sub)
        sub.translatesAutoresizingMaskIntoConstraints = false
        sub.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
        sub.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
        sub.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
        sub.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
    

    @available(*, unavailable)
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    


struct TableTestCellView: View 
    @Binding var label: String

    var body: some View 
        Text(label)
            .padding()
            .multilineTextAlignment(.leading)
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .topLeading)
    


struct ContentView_Previews: PreviewProvider 
    static var previews: some View 
        TableTestCellView(label: .constant("Testing\nHello world"))
    

【讨论】:

以上是关于在 UITableViewCell 内部的 UIView 上添加 SwiftUI [重复]的主要内容,如果未能解决你的问题,请参考以下文章

无法点击 UITableViewCell 上 CustomCell 的 Tap Recognizer

将 UIView 移动到新的超级视图并从 UITableViewCell 再次返回

在 UITableViewCell 内部的 UIView 上添加 SwiftUI [重复]

内部带有TextView的快速自定义UITableViewCell消失

如何在UITableViewCell内部更新UITableView的高度约束

呈现从 UITableViewCell 内部启动的 UIActivityViewController