我可以调用UITableViewDelegate的didSelectRowAtIndexPath:

时间:2013-10-04 22:34:09

标签: objective-c uitableview ios5 uiviewcontroller swizzling

问题在于:

我需要能够在包含大量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

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

谢谢!

1 个答案:

答案 0 :(得分:0)

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

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)

      }
    }