5

问题是这样的:

我需要能够在具有大量 tableViews 的大型现有应用程序中对 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

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

谢谢!

4

1 回答 1

3

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

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)

      }
    }
于 2019-12-10T07:20:17.590 回答