美文网首页
oc中method_exchangeImplementation

oc中method_exchangeImplementation

作者: 落叶兮兮 | 来源:发表于2020-06-16 17:34 被阅读0次

目前在做一个UIPageViewController滑动,上面的栏目跟着UIPageViewController的滑动而滑动,原本是使用delegate协议方法来实现的

    - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating: 
   (BOOL)finished previousViewControllers:(NSArray<UIViewController *> 
    *)previousViewControllers transitionCompleted:(BOOL)completed;

当complete为YES时,执行上方栏目的变化,但是这样做有点不顺畅的感觉,总是在UIPageViewController翻页完成之后才会执行上方的切换动画,想要解决这个问题,依旧使用协议方法

//当翻页动画开始时调用,这样会出现另外一个问题,当用户滑动到一半之后取消,那应该返回原来的那个viewController,但是下面这个方法依旧默认执行
- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray<UIViewController *> *)pendingViewControllers;

没有办法的情况下,开始使用method_exchangeImplementations来实现相应的功能,具体做法是增加一个UIPageViewController的分类,在load方法中使用交换方法,将viewDidload方法交换为我们自定义的方法,具体的代码如下:

Method originalMethod = class_getInstanceMethod([self class], @selector(viewDidLoad));
Method newMethod = class_getInstanceMethod([self class], @selector(scroll_viewDidLoad));
- (void)scroll_viewDidLoad {
    [self scroll_viewDidLoad];
    [self addObserverForScrollViewContentOffset];
}

在运行的过程中就出现了问题,xcode报错显示scroll_viewDidLoad方法找不到,明明是自己定义的方法,为什么系统会提示找不到呢?之后查询百度查到一个相应的解释,参考链接为:
https://blog.csdn.net/li198847/article/details/106452107

总的来说就是,我交换方法是写在UIPageViewController的分类中,交换成功后,

-  (void)scroll_viewDidLoad {
       [self  scroll_viewDidLoad];//因为已经交换方法,所以这句实际上是执行[self viewDidload]方法
}

而在UIPageViewController中并没有重写基类UIViewController的viewDidLoad方法,所以会报错,找不到该方法,解决办法是在使用method_exchangeImplementations之前增加一个判断,如果方法不存在,先将这个方法添加进去再进行交换。
具体的代码如下:

+ (BOOL)swizzleInstanceMethod:(SEL)origSelector withMethod:(SEL)newSelector {
    Method origMethod = class_getInstanceMethod(self, origSelector);
       Method newMethod = class_getInstanceMethod(self, newSelector);
       
       if (origMethod && newMethod) {
           if (class_addMethod(self, origSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
               class_replaceMethod(self, newSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
           } else {
               method_exchangeImplementations(origMethod, newMethod);
           }
           return YES;
       }
       return NO;
}

class_addMethod这个方法的实现会覆盖父类的方法实现,但不会取代本类中已存在的实现,如果本类中包含一个同名的实现,则函数会返回NO。以保证修改的就是当前类。

相应的demo代码在我的github中,链接为:
https://github.com/xuehuafeiwu1997/CollectionViewMultimethod-sliding.git
在文件appDelegate中使用MainViewController就是这次所说的demo代码。

相关文章

  • oc中method_exchangeImplementation

    目前在做一个UIPageViewController滑动,上面的栏目跟着UIPageViewController的...

  • iOS原生&JS交互

    OC 获取js中的key OC调用js方法 JS调用OC中不带参数的block JS调用OC中带参数的block ...

  • swift 调用 OC中的block

    OC中声明block; OC中实现block swift中实现

  • swift中数组enumerate

    1、OC写法 @brief OC中的enumerateObjectsUsingBlockObjective-C 中...

  • oc/Swift混编心得(基础篇)

    swift引用oc文件 需要在桥接文件中倒入oc头文件 oc调用swift需要在oc .m中倒入“项目吗-Swif...

  • quick cocos Lua与OC互相回调,苹果内购机制

    1.在需要调用oc中的lua方法中写入调用oc的接口方法,把参数传递进去给oc层使用 2.在对应oc中的方法中拿到...

  • objc_msgSend

    OC中消息的概念 OC中在对象上调用方法,用OC的术语叫“传递消息”。在OC中,如果向某对象传递消息,会使用动态绑...

  • 总纲

    一句代码创建常用UI控件类与对象OC中面向对象的编程思想OC基础语法复习OC中的协议OC中的block学习导航栏按...

  • OC 和 swift 互调

    swift中调用OC 如果想要在swift中调用OC,那么需要一个桥接文件(OC Bridging Header)...

  • Swift注释 添加编译等

    MARK TODO FIXME // MARK:类似OC中的#pragma mark ..MARK: -类似OC中...

网友评论

      本文标题:oc中method_exchangeImplementation

      本文链接:https://www.haomeiwen.com/subject/heurxktx.html