如何通过代码手动实现 table 特定行的 Peek & Pop 功能?
How to implement Peek & Pop Feature of specific row of a table manually via code?
目标
我正在尝试将查看和弹出功能添加到我的 table 行
您没有从表格视图中获取单元格。所以步骤如下:
- 使用
UIViewControllerPreviewingDelegate
方法中的位置点获取 indexPath
。
- 使用
indexPath
从 tableView
获取单元格。
- 获取单元格后,将单元格框架转换为表格视图框架。
- 将框架作为 sourceRect 提供给
previewingContext
。
代码如下:
在viewDidLoad
if self.traitCollection.forceTouchCapability == .available {
registerForPreviewing(with: self, sourceView: tableView)
}
在扩展中:
extension ProfileViewController: UIViewControllerPreviewingDelegate {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
if let indexPath = tableView.indexPathForRow(at: location), let cell = tableView.cellForRow(at: indexPath) {
previewingContext.sourceRect = tableView.convert(cell.frame, to: self.tableView)
guard let detailViewController = storyboard?.instantiateViewController(withIdentifier: "profileDetail") as? ProfileDetailViewController else {
return nil
}
return detailViewController
}
return nil
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
}
通常,我会使用简单的单元格扩展来做到这一点:
class ForceTouchCell: UITableViewCell {
var previewingContext: UIViewControllerPreviewing?
func registerPreview(on controller: UIViewController, with delegate: UIViewControllerPreviewingDelegate) {
self.previewingContext = controller.registerForPreviewing(with: delegate, sourceView: self)
}
func unregisterPreview(on controller: UIViewController) {
guard let previewingContext = previewingContext else {
return
}
controller.unregisterForPreviewing(withContext: previewingContext)
self.previewingContext = nil
}
}
然后在控制器上:
class MyController: UIViewController, UITableViewDelegate {
var tableView: UITableView!
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
guard traitCollection.forceTouchCapability != previousTraitCollection?.forceTouchCapability else {
return
}
let visibleCells = tableView.visibleCells
.compactMap { [=11=] as? ForceTouchCell }
if traitCollection.forceTouchCapability == .available {
visibleCells.forEach {
[=11=].registerPreview(on: self, with: self)
}
} else {
visibleCells.forEach {
[=11=].unregisterPreview(on: self)
}
}
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let forceTouchCell = cell as? ForceTouchCell {
if self.traitCollection.forceTouchCapability == .available {
forceTouchCell.registerPreview(on: self, with: self)
}
}
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
if let forceTouchCell = cell as? ForceTouchCell {
forceTouchCell.unregisterPreview(on: self)
}
}
}
extension MyConroller: UIViewControllerPreviewingDelegate {
func previewingContext(
_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint
) -> UIViewController? {
guard
let cell = (previewingContext.sourceView as? ForceTouchCell),
let indexPath = tableView.indexPath(for: cell)
else {
return nil
}
// use the indexPath/cell to create preview controller
}
这个解决方案的好处在于它可以很容易地跨控制器共享,例如使用具有默认实现的协议。
目标
我正在尝试将查看和弹出功能添加到我的 table 行
您没有从表格视图中获取单元格。所以步骤如下:
- 使用
UIViewControllerPreviewingDelegate
方法中的位置点获取indexPath
。 - 使用
indexPath
从tableView
获取单元格。 - 获取单元格后,将单元格框架转换为表格视图框架。
- 将框架作为 sourceRect 提供给
previewingContext
。
代码如下:
在viewDidLoad
if self.traitCollection.forceTouchCapability == .available {
registerForPreviewing(with: self, sourceView: tableView)
}
在扩展中:
extension ProfileViewController: UIViewControllerPreviewingDelegate {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
if let indexPath = tableView.indexPathForRow(at: location), let cell = tableView.cellForRow(at: indexPath) {
previewingContext.sourceRect = tableView.convert(cell.frame, to: self.tableView)
guard let detailViewController = storyboard?.instantiateViewController(withIdentifier: "profileDetail") as? ProfileDetailViewController else {
return nil
}
return detailViewController
}
return nil
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
}
通常,我会使用简单的单元格扩展来做到这一点:
class ForceTouchCell: UITableViewCell {
var previewingContext: UIViewControllerPreviewing?
func registerPreview(on controller: UIViewController, with delegate: UIViewControllerPreviewingDelegate) {
self.previewingContext = controller.registerForPreviewing(with: delegate, sourceView: self)
}
func unregisterPreview(on controller: UIViewController) {
guard let previewingContext = previewingContext else {
return
}
controller.unregisterForPreviewing(withContext: previewingContext)
self.previewingContext = nil
}
}
然后在控制器上:
class MyController: UIViewController, UITableViewDelegate {
var tableView: UITableView!
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
guard traitCollection.forceTouchCapability != previousTraitCollection?.forceTouchCapability else {
return
}
let visibleCells = tableView.visibleCells
.compactMap { [=11=] as? ForceTouchCell }
if traitCollection.forceTouchCapability == .available {
visibleCells.forEach {
[=11=].registerPreview(on: self, with: self)
}
} else {
visibleCells.forEach {
[=11=].unregisterPreview(on: self)
}
}
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let forceTouchCell = cell as? ForceTouchCell {
if self.traitCollection.forceTouchCapability == .available {
forceTouchCell.registerPreview(on: self, with: self)
}
}
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
if let forceTouchCell = cell as? ForceTouchCell {
forceTouchCell.unregisterPreview(on: self)
}
}
}
extension MyConroller: UIViewControllerPreviewingDelegate {
func previewingContext(
_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint
) -> UIViewController? {
guard
let cell = (previewingContext.sourceView as? ForceTouchCell),
let indexPath = tableView.indexPath(for: cell)
else {
return nil
}
// use the indexPath/cell to create preview controller
}
这个解决方案的好处在于它可以很容易地跨控制器共享,例如使用具有默认实现的协议。