目前在做一个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代码。
网友评论