runtime 學習關聯(lián)對象(附帶一個:全屏側滑返回擴展)

前言:這是我偶然間看見的一種利用runtime原理寫向右側滑返回上一頁的類擴展,
用起來很方便,直接將擴展拉進項目里面即可,然后所有的push的控制器都可以右滑返回上一頁了

首先需要了解一下 runtme的關聯(lián)方法objc_setAssociatedObject

關聯(lián)對象不是為類\對象添加屬性或者成員變量(因為在設置關聯(lián)后也無法通過ivarList或者propertyList取得) ,而是為類添加一個相關的對象,通常用于存儲類信息,例如存儲類的屬性列表數(shù)組,為將來字典轉模型的方便。

objc_setAssociatedObject方法的參數(shù)解釋:

  1. 第一個參數(shù)id object, 當前對象

  2. 第二個參數(shù)const void *key, 關聯(lián)的key,是c字符串

  3. 第三個參數(shù)id value, 被關聯(lián)的對象的值

  4. 第四個參數(shù)objc_AssociationPolicy policy關聯(lián)引用的規(guī)則

使用方式一:給分類添加屬性


@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

// 給系統(tǒng)NSObject類動態(tài)添加屬性name

NSObject *objc = [[NSObject alloc] init];

objc.name = @"哈哈";

NSLog(@"%@",objc.name);

}

@end

// 定義關聯(lián)的key

static const char *key = "name";

@implementation NSObject (Property)

- (NSString *)name

{

// 根據(jù)關聯(lián)的key,獲取關聯(lián)的值。

return objc_getAssociatedObject(self, key);

}

- (void)setName:(NSString *)name

{

// 第一個參數(shù):給哪個對象添加關聯(lián)

// 第二個參數(shù):關聯(lián)的key,通過這個key獲取

// 第三個參數(shù):關聯(lián)的value

// 第四個參數(shù):關聯(lián)的策略

objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

@end```



使用方式二:給對象添加關聯(lián)對象。



/**

  • 刪除點擊

  • @param recId 購物車ID

*/

  • (void)shopCartCell:(BSShopCartCell *)shopCartCell didDeleteClickedAtRecId:(NSString *)recId

{

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"確認要刪除這個寶貝" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];

// 傳遞多參數(shù)

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

{

// 交叉方法替換系統(tǒng)的 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:");

// 攔截系統(tǒng)的所有的handleNavigationTransition:換成自己自己添加的手勢來識別

self.xw_popgestureRecoginizer.delegate = [self xw_fullscreenPopGestuieRecoginzerDelegate];

// 自己的手勢調用系統(tǒng)的手勢方法 handleNavigationTransition

[self.xw_popgestureRecoginizer addTarget:internalTarget action:internalAction];

// 禁止系統(tǒng)的手勢交互

self.interactivePopGestureRecognizer.enabled = NO;

}

if (![self.viewControllers containsObject:ViewController]) {

// 交叉方法調用系統(tǒng)的pushViewController:方法

// 調用XW_pushViewController = 調用pushViewController 因為這兩個方法互換了

[self XW_pushViewController:ViewController animated:animated];

}

}

-(XWFullScreenPopGestureRecognizerDelegate*)xw_fullscreenPopGestuieRecoginzerDelegate

{

// 給navigationController 添加一個xw_fullscreenPopGestuieRecoginzerDelegate 屬性

// 獲取關聯(lián)對象

XWFullScreenPopGestureRecognizerDelegate *delegate = objc_getAssociatedObject(self, _cmd);

//如果未關聯(lián)重新關聯(lián)

if (!delegate) {

delegate = [[XWFullScreenPopGestureRecognizerDelegate alloc] init];

objc_setAssociatedObject(self, _cmd, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

//返回關聯(lián)對象

return delegate;

}

-(UIPanGestureRecognizer *)xw_popgestureRecoginizer

{

// 給navigationController 添加一個xw_popgestureRecoginizer屬性

// 獲取關聯(lián)對象

UIPanGestureRecognizer *panGestureRecoginizer =objc_getAssociatedObject(self, _cmd);

//如果未關聯(lián)重新關聯(lián)

if (!panGestureRecoginizer) {

panGestureRecoginizer =[[UIPanGestureRecognizer alloc] init];

panGestureRecoginizer.maximumNumberOfTouches = 1;

//將self與panGestureRecoginizer關聯(lián)起來

objc_setAssociatedObject(self, _cmd, panGestureRecoginizer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

//返回關聯(lián)對象

return panGestureRecoginizer;

}

@end```
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容