【问题标题】:Can I swizzle didSelectRowAtIndexPath: of UITableViewDelegate?我可以调整 UITableViewDelegate 的 didSelectRowAtIndexPath: 吗?
【发布时间】:2013-10-12 01:50:03
【问题描述】:

问题是这样的:

我需要能够在一个包含大量 tableView 的大型现有应用程序中对 didSelectRowAtIndexPath 进行分析。

我的第一个想法是在 didSelectRowAtIndexPath 上进行方法调配:但我的应用程序崩溃并显示“无法识别的选择器已发送到实例”消息,具体取决于原始 didSelectRowAtIndexPath 实现中访问的内容。

这是我尝试在 UIViewController 类别中实现此目的的方法:

#import "UIViewController+Swizzle.h"

@implementation UIViewController (Swizzle)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPathSwizzled:(NSIndexPath *)indexPath {
    NSLog(@"Log something here");
    [self tableView:tableView didSelectRowAtIndexPathSwizzled:indexPath];
}

+ (void) initialize {
    BOOL conformsToTableViewDelegate = class_conformsToProtocol(self, @protocol(UITableViewDelegate));
    if(conformsToTableViewDelegate) {
        Method method1 = class_getInstanceMethod(self, @selector(tableView:didSelectRowAtIndexPath:));
        Method method2 = class_getInstanceMethod(self, @selector(tableView:didSelectRowAtIndexPathSwizzled:));
        method_exchangeImplementations(method1, method2);
    }
}


@end

这可以实现吗?如果是这样,我做错了什么?

谢谢!

【问题讨论】:

  • 这会导致所有数据源方法被混用,包括那些被 UIKit 用来在你的应用程序中实现 UIKit 功能的方法......你真的有这么多实现吗您不能只进行全局搜索并在每个方法中粘贴一行指标收集代码吗?
  • 感谢您的输入,但我不明白评论。如何将 method_exchangeImplementations(method1, method2);导致所有数据源方法被混合,包括 UIKit 使用的方法?我为 UIButtons 的 sendAction: 做了这个,它的效果很好。我想协议中的方法没有办法做到这一点
  • 这里还有一些其他问题;像这样使用+initialize 将覆盖UIViewController 中的+initialize,如果有的话。并且这段代码将导致UIViewController 或子类的每个实例 都使用该方法。这与“协议中的方法”无关,与改变 UIKit 的内部行为有关。
  • 嗯,这正是我打算让 didSelectRowAtIndexPath(UITableViewDelegate 协议的方法,在 UIKit 中没有内部行为)的实现。 swizzling 将仅发生在符合ToTableViewDelegate 的 UIViewController 实例上,因此实现了 didSelectRowAtIndexPath。确实该方法是可选的,我应该再次检查,但问题是我遇到了崩溃并且不明白为什么。此外,swizzling 只会添加一行代码来收集指标,不会以任何其他方式改变原始实现(如果有的话)。
  • 我尝试在 UIApplicationDelegate 中调配一个方法,但它不起作用...我尝试在初始化时调配它以调配 didFinishLaunching。它不会崩溃,但方法不会 swizzle... 我读到 bbum 说修改是禁止的,但我相信 swizzling 是由 Apple 授权用于市场应用程序的。我已经在接口中混合了方法,但我从来没有在协议中这样做......

标签: objective-c uitableview ios5 uiviewcontroller swizzling


【解决方案1】:

给出答案可能会迟到,但希望它会帮助其他一些开发人员。下面的链接对我有很大帮助。

https://www.jianshu.com/p/9a93ae99fb27

   extension UITableView {

        @objc static func swizzleTableView() {

          guard self == UITableView.self else {
            return
          }

          let originalTableViewDelegateSelector = #selector(setter: self.delegate)
          let swizzledTableViewDelegateSelector = #selector(self.nsh_set(delegate:))

          let originalTableViewMethod = class_getInstanceMethod(self, originalTableViewDelegateSelector)
          let swizzledTableViewMethod = class_getInstanceMethod(self, swizzledTableViewDelegateSelector)

          method_exchangeImplementations(originalTableViewMethod!,
                                         swizzledTableViewMethod!)
        }

        @objc open func nsh_set(delegate: UITableViewDelegate?) {
          nsh_set(delegate: delegate)

          guard let delegate =  delegate else { return }

          let originalDidSelectSelector = #selector(delegate.tableView(_:didSelectRowAt:))
          let swizzleDidSelectSelector = #selector(self.tableView(_:didSelectRowAt:))

          let swizzleMethod = class_getInstanceMethod(UITableView.self, swizzleDidSelectSelector)
          let didAddMethod = class_addMethod(type(of: delegate), swizzleDidSelectSelector, method_getImplementation(swizzleMethod!), method_getTypeEncoding(swizzleMethod!))

          if didAddMethod {
            let didSelectOriginalMethod = class_getInstanceMethod(type(of: delegate), NSSelectorFromString("tableView:didSelectRowAt:"))
            let didSelectSwizzledMethod = class_getInstanceMethod(type(of: delegate), originalDidSelectSelector)
            if didSelectOriginalMethod != nil && didSelectSwizzledMethod != nil {
              method_exchangeImplementations(didSelectOriginalMethod!, didSelectSwizzledMethod!)
            }
          }
      }

      @objc open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.tableView(tableView, didSelectRowAt: indexPath)

      }
    }

【讨论】:

    猜你喜欢
    • 2012-08-31
    • 2015-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    相关资源
    最近更新 更多