美文网首页
runtime 学习关联对象(附带一个:全屏侧滑返回扩展)

runtime 学习关联对象(附带一个:全屏侧滑返回扩展)

作者: 1剑天下 | 来源:发表于2016-12-28 00:00 被阅读31次

    前言:这是我偶然间看见的一种利用runtime原理写向右侧滑返回上一页的类扩展,
    用起来很方便,直接将扩展拉进项目里面即可,然后所有的push的控制器都可以右滑返回上一页了

    首先需要了解一下 runtme的关联方法objc_setAssociatedObject

    关联对象不是为类\对象添加属性或者成员变量(因为在设置关联后也无法通过ivarList或者propertyList取得) ,而是为类添加一个相关的对象,通常用于存储类信息,例如存储类的属性列表数组,为将来字典转模型的方便。

    objc_setAssociatedObject方法的参数解释:

    1. 第一个参数id object, 当前对象

    2. 第二个参数const void *key, 关联的key,是c字符串

    3. 第三个参数id value, 被关联的对象的值

    4. 第四个参数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```

    相关文章

      网友评论

          本文标题:runtime 学习关联对象(附带一个:全屏侧滑返回扩展)

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