以编程方式打开 UITableView 编辑操作按钮 [英] Open UITableView edit action buttons programmatically
问题描述
我有一个 UIPageViewController
,里面有 UITableViewControllers
,向左滑动手势在 UIPageViewController
之间发生冲突,无法在视图和UITableViewCells
手势打开编辑操作,所以我需要在单元格中单击某个按钮时显示编辑操作.
我的问题是我可以以编程方式显示编辑操作按钮而不是在滑动手势上显示它们吗?
Apple 有一个私有 API 可以让您执行此操作,但是,请注意这可能会导致您的应用被 App Store 拒绝,除非您混淆了上述的用法API 使用诸如Method Swizzling 之类的东西.以下是执行此操作的步骤:
创建一个名为
PrivateMethodRevealer
的协议,让您可以访问所需的私有 Apple API,即显示和取消编辑操作的 API.感谢编辑:这是一种使用方法 swizzling 隐藏 API 使用情况的快速方法.感谢本网站提供基本的这种方法的实现.请注意,我无法保证它会起作用,因为无法对其进行现场测试.
为此,将协议替换为以下代码,并在调用
setShowingDeleteConfirmation(true)
或_endSwipeToDeleteRowDidDelete(false)
的任何地方,将其替换为showRowActions()
和hideRowActions()
代替.然而,此方法似乎有一些意想不到的效果,例如UITableViewCell
在编辑操作可见时不响应用户交互.扩展 UITableViewCell {func showRowActions(arg1: Bool = true) {}公共覆盖静态功能初始化(){结构静态{静态 var 标记:dispatch_once_t = 0}保护 self === UITableViewCell.self else {return}dispatch_once(&Static.token) {让 hiddenString = String(":noitamrifnoCeteleDgniwohStes".characters.reverse())让 originalSelector = NSSelectorFromString(hiddenString)让 swizzledSelector = #selector(showRowActions(_:))让 originalMethod = class_getInstanceMethod(self, originalSelector)让 swizzledMethod = class_getInstanceMethod(self, swizzledSelector)class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))method_exchangeImplementations(originalMethod, swizzledMethod)}}}扩展 UITableView {func hideRowActions(arg1: Bool = false) {}公共覆盖静态功能初始化(){结构静态{静态 var 标记:dispatch_once_t = 0}保护 self === UITableView.self else {return}dispatch_once(&Static.token) {让 hiddenString = String(":eteleDdiDwoReteleDoTepiwSdne_".characters.reverse())让 originalSelector = NSSelectorFromString(hiddenString)让 swizzledSelector = #selector(hideRowActions(_:))让 originalMethod = class_getInstanceMethod(self, originalSelector)让 swizzledMethod = class_getInstanceMethod(self, swizzledSelector)class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))method_exchangeImplementations(originalMethod, swizzledMethod)}}}
I have a
UIPageViewController
that haveUITableViewControllers
inside it, and the swipe left gestures are conflicted between theUIPageViewController
to change between the views and theUITableViewCells
gesture to open the edit actions, so I need to show the edit actions when a certain button is clicked in the cell.My question is can I show the edit action buttons programmatically instead of showing them on the swipe gesture?
解决方案Apple has a private API that lets you do this, however, be warned that this may get your app rejected from the App Store unless you obfuscate the usage of said API using something like Method Swizzling. Here are the steps to do so:
Create a protocol called
PrivateMethodRevealer
that lets you access the required private Apple APIs, namely the ones to show and dismiss edit actions. Credits to this answer for providing this method of exposing private APIs. The methods in the protocol are declared asoptional
, so that in case Apple changes the name of the method, the app will not crash, but rather, it'll just not show the edit actions.@objc protocol PrivateMethodRevealer { optional func setShowingDeleteConfirmation(arg1: Bool) optional func _endSwipeToDeleteRowDidDelete(arg1: Bool) }
Note that although the methods refer to
delete
, this shows all theUITableViewRowAction
s that are on the cell.Create a function that handles the showing and hiding of the edit actions in your
UITableViewCell
subclass (if you have one), or create the method in aUITableViewCell
extension
. I will name this methodshowActions
for demonstrative purposes.Add the following body to your function:
func showActions() { (superview?.superview as? AnyObject)?._endSwipeToDeleteRowDidDelete?(false) (self as AnyObject).setShowingDeleteConfirmation?(true) }
This firstly dismisses any visible cells' editing actions, by calling
_endSwipeToDeleteRowDidDelete:
on theUITableView
(which is the cell's superview's superview), and then shows the cell's own editing actions (by callingsetShowingDeleteConfirmation:
). Note that we need to dismiss other cells' actions as showing multiple rows with edit actions is extremely buggy.If you want, you may also create a button in the
UIViewController
that dismisses any currently editing cells. To do this, just call the following method, wheretableView
is your reference to theUITableView
:(tableView as AnyObject)?._endSwipeToDeleteRowDidDelete?(false)
If the swipe gestures between your
UIPageViewController
andUITableViewCell
s are conflicting, simply override thetableView:editingStyleForRowAtIndexPath:
method to return.None
.In the end, your code might produce the following result
EDIT: Here is a quick way to hide the usage of your API using method swizzling. Credits to this website for providing the basic implementation of this method. Be warned that I can't guarantee that it'll work, as it isn't possible to test it live.
To do this, replace the protocols with the following code, and wherever you call
setShowingDeleteConfirmation(true)
or_endSwipeToDeleteRowDidDelete(false)
, replace it withshowRowActions()
andhideRowActions()
instead. This method appears to have some unintended effects however, such as theUITableViewCell
s not responding to user interaction whilst edit actions are visible.extension UITableViewCell { func showRowActions(arg1: Bool = true) {} public override static func initialize() { struct Static { static var token: dispatch_once_t = 0 } guard self === UITableViewCell.self else {return} dispatch_once(&Static.token) { let hiddenString = String(":noitamrifnoCeteleDgniwohStes".characters.reverse()) let originalSelector = NSSelectorFromString(hiddenString) let swizzledSelector = #selector(showRowActions(_:)) let originalMethod = class_getInstanceMethod(self, originalSelector) let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) method_exchangeImplementations(originalMethod, swizzledMethod) } } } extension UITableView { func hideRowActions(arg1: Bool = false) {} public override static func initialize() { struct Static { static var token: dispatch_once_t = 0 } guard self === UITableView.self else {return} dispatch_once(&Static.token) { let hiddenString = String(":eteleDdiDwoReteleDoTepiwSdne_".characters.reverse()) let originalSelector = NSSelectorFromString(hiddenString) let swizzledSelector = #selector(hideRowActions(_:)) let originalMethod = class_getInstanceMethod(self, originalSelector) let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) method_exchangeImplementations(originalMethod, swizzledMethod) } } }
这篇关于以编程方式打开 UITableView 编辑操作按钮的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!