【发布时间】:2021-12-04 21:21:42
【问题描述】:
如何在 UITableViewCell 内部的 UIView 上添加 SwiftUI,通常使用 uihostingcontroller 可以将 SwiftUI 视图作为子级添加到 ViewController 但我们该怎么做这在 UITableViewCell
上【问题讨论】:
如何在 UITableViewCell 内部的 UIView 上添加 SwiftUI,通常使用 uihostingcontroller 可以将 SwiftUI 视图作为子级添加到 ViewController 但我们该怎么做这在 UITableViewCell
上【问题讨论】:
我能够得到这样的工作:
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 可能发生的所有各种配置更改。
【讨论】:
使用 @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"))
}
}
【讨论】: