前言:这是我偶然间看见的一种利用runtime原理写向右侧滑返回上一页的类扩展,
用起来很方便,直接将扩展拉进项目里面即可,然后所有的push的控制器都可以右滑返回上一页了
首先需要了解一下 runtme的关联方法objc_setAssociatedObject
关联对象不是为类\对象添加属性或者成员变量(因为在设置关联后也无法通过ivarList或者propertyList取得) ,而是为类添加一个相关的对象,通常用于存储类信息,例如存储类的属性列表数组,为将来字典转模型的方便。
objc_setAssociatedObject方法的参数解释:
-
第一个参数id object, 当前对象
-
第二个参数const void *key, 关联的key,是c字符串
-
第三个参数id value, 被关联的对象的值
-
第四个参数objc_AssociationPolicy policy关联引用的规则
使用方式一:给分类添加属性
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 给系统NSObject类动态添加属性name
NSObject *objc = [[NSObject alloc] init];
objc.name = @"哈哈";
NSLog(@"%@",objc.name);
}
@end
// 定义关联的key
static const char *key = "name";
@implementation NSObject (Property)
- (NSString *)name
{
// 根据关联的key,获取关联的值。
return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name
{
// 第一个参数:给哪个对象添加关联
// 第二个参数:关联的key,通过这个key获取
// 第三个参数:关联的value
// 第四个参数:关联的策略
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end```
使用方式二:给对象添加关联对象。
/**
-
删除点击
-
@param recId 购物车ID
*/
- (void)shopCartCell:(BSShopCartCell *)shopCartCell didDeleteClickedAtRecId:(NSString *)recId
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"确认要删除这个宝贝" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
// 传递多参数
objc_setAssociatedObject(alert, "suppliers_id", @"1", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(alert, "warehouse_id", @"2", OBJC_ASSOCIATION_RETAIN_NONATOMIC);
alert.tag = [recId intValue];
[alert show];
}
/**
- 确定删除操作
*/
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSString *warehouse_id = objc_getAssociatedObject(alertView, "warehouse_id");
NSString *suppliers_id = objc_getAssociatedObject(alertView, "suppliers_id");
NSString *recId = [NSString stringWithFormat:@"%ld",(long)alertView.tag];
}
}
下面是右滑返回 ,我做了详细注释,
import@interface UINavigationController (XWFullScreenLeftSlidPop)
@property(strong, nonatomic) UIPanGestureRecognizer * xw_popgestureRecoginizer;
@end```
//// UINavigationController+XWFullScreenLeftSlidPop.m// KouDaiGuangBo//// Created by 文 on 2016/12/26.// Copyright © 2016年 CSC. All rights reserved.//#import "UINavigationController+XWFullScreenLeftSlidPop.h"#import@interface XWFullScreenPopGestureRecognizerDelegate :NSObject@property(weak, nonatomic) UINavigationController * navigationController;
@end
@implementation XWFullScreenPopGestureRecognizerDelegate
-(BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer
{
NSLog(@"----%ld",self.navigationController.viewControllers.count);
// 判断是否是更新
// if (self.navigationController.viewControllers.count<=1) {
//
// return NO;
// }
// 如果正在转场动画
if ([[self.navigationController valueForKey:@"_isTransitioning"] boolValue]) {
return NO;
}
//判断手指移动方向
CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];
if (translation.x<=0) {
// 左滑
return NO;
}
return YES;
}
@end
@implementation UINavigationController (XWFullScreenLeftSlidPop)
+(void)load
{
// 交叉方法替换系统的 pushViewController
Method methodNomer = class_getInstanceMethod([self class], @selector(pushViewController:animated:));
Method othermethod = class_getInstanceMethod([self class],@selector(XW_pushViewController:animated:));
method_exchangeImplementations(methodNomer, othermethod);
}
-(void)XW_pushViewController:(UIViewController *)ViewController animated:(BOOL)animated
{
// 替换的目的是为了 添加一个自己的手势
//拿到navigationController原有的pop手势:self.interactivePopGestureRecognizer
// self.interactivePopGestureRecognizer是navigationController自带的pop手势
if(![self.interactivePopGestureRecognizer.view.gestureRecognizers containsObject:self.xw_popgestureRecoginizer])// 判断是否是自己的手势
{
// 添加自己的手势
[self.interactivePopGestureRecognizer.view addGestureRecognizer:self.xw_popgestureRecoginizer];
NSArray * tagets =[self.interactivePopGestureRecognizer valueForKey:@"targets"];
id internalTarget = [tagets.firstObject valueForKey:@"target"];
SEL internalAction = NSSelectorFromString(@"handleNavigationTransition:");
// 拦截系统的所有的handleNavigationTransition:换成自己自己添加的手势来识别
self.xw_popgestureRecoginizer.delegate = [self xw_fullscreenPopGestuieRecoginzerDelegate];
// 自己的手势调用系统的手势方法 handleNavigationTransition
[self.xw_popgestureRecoginizer addTarget:internalTarget action:internalAction];
// 禁止系统的手势交互
self.interactivePopGestureRecognizer.enabled = NO;
}
if (![self.viewControllers containsObject:ViewController]) {
// 交叉方法调用系统的pushViewController:方法
// 调用XW_pushViewController = 调用pushViewController 因为这两个方法互换了
[self XW_pushViewController:ViewController animated:animated];
}
}
-(XWFullScreenPopGestureRecognizerDelegate*)xw_fullscreenPopGestuieRecoginzerDelegate
{
// 给navigationController 添加一个xw_fullscreenPopGestuieRecoginzerDelegate 属性
// 获取关联对象
XWFullScreenPopGestureRecognizerDelegate *delegate = objc_getAssociatedObject(self, _cmd);
//如果未关联重新关联
if (!delegate) {
delegate = [[XWFullScreenPopGestureRecognizerDelegate alloc] init];
objc_setAssociatedObject(self, _cmd, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//返回关联对象
return delegate;
}
-(UIPanGestureRecognizer *)xw_popgestureRecoginizer
{
// 给navigationController 添加一个xw_popgestureRecoginizer属性
// 获取关联对象
UIPanGestureRecognizer *panGestureRecoginizer =objc_getAssociatedObject(self, _cmd);
//如果未关联重新关联
if (!panGestureRecoginizer) {
panGestureRecoginizer =[[UIPanGestureRecognizer alloc] init];
panGestureRecoginizer.maximumNumberOfTouches = 1;
//将self与panGestureRecoginizer关联起来
objc_setAssociatedObject(self, _cmd, panGestureRecoginizer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//返回关联对象
return panGestureRecoginizer;
}
@end```
网友评论