zoukankan      html  css  js  c++  java
  • objective-c 中的关联介绍

    objective-c 中的关联介绍

    转载请注明CSDN博客上的出处:
    http://blog.csdn.net/daiyibo123/article/details/46471993


    如何设置关联

    我们可以使用下面的方法来关联属性:

    objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    1. 被关联的对象,下面举的例子中关联到了UIAlertView
    2. 要关联的对象的键值,一般设置成静态的,用于获取关联对象的值
    3. 要关联的对象的值,从接口中可以看到接收的id类型,所以能关联任何对象
    4. 关联时采用的协议,有assign,retain,copy等协议,具体可以参考官方文档

    可以通过下面的方法来获取我们刚刚关联的object:

    objc_getAssociatedObject(id object, const void *key);
    1. 被关联的对象
    2. 要关联的对象的键值,一般设置成静态的,用于获取关联对象的值

    简单运用

    下面是简单地viewController类,黏贴直接可以运行:

    #import <UIKit/UIKit.h>
    @interface ViewController : UIViewController
    
    @end
    #import "ViewController.h"
    #import <objc/runtime.h>
    
    static char kUITableViewIndexKey;
    
    @interface ViewController ()
    @end
    
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(0, 200, [UIScreen mainScreen].bounds.size.width, 50)];
        lable.backgroundColor = [UIColor lightGrayColor];
        lable.text = @"关联属性";
        lable.textColor = [UIColor blackColor];
    
    
        objc_setAssociatedObject(self, &kUITableViewIndexKey, lable, OBJC_ASSOCIATION_RETAIN_NONATOMIC);//设置一个关联
    
        [self.view addSubview:objc_getAssociatedObject(self, &kUITableViewIndexKey)];//获取刚刚关联的lable
    }
    @end

    注:在获取和设置关联的时候,调用的被关联对象(代码中用的是self)和关联键值(代码中用kUITableViewIndexKey)都必须是同一个对象。这样才可以保证能获取到关联对象。


    个人理解

    下面是键值的较好的运用:

    代码介绍:一个仿系统的TabBarController类(RDVTabBarController,这个是第三方库,下载地址:https://github.com/robbdimitrov/RDVTabBarController)

    在创建RDVTabBarController时,建立了两个UIViewController的扩展,扩展中建立关联,关联代码如下:

    @interface UIViewController (RDVTabBarControllerItemInternal)
    
    - (void)rdv_setTabBarController:(RDVTabBarController *)tabBarController;
    
    @end
    
    @interface UIViewController (RDVTabBarControllerItem)
    
    @property(nonatomic, readonly) RDVTabBarController *rdv_tabBarController;
    
    @end
    @implementation UIViewController (RDVTabBarControllerItemInternal)
    
    - (void)rdv_setTabBarController:(RDVTabBarController *)tabBarController {
        objc_setAssociatedObject(self, @selector(rdv_tabBarController), tabBarController, OBJC_ASSOCIATION_ASSIGN);
    }
    @end
    
    @implementation UIViewController 
    (RDVTabBarControllerItem)
    
    - (RDVTabBarController *)rdv_tabBarController{
        RDVTabBarController *tabBarController = objc_getAssociatedObject(self, @selector(rdv_tabBarController));
        //这里使用的递归算法
        if (!tabBarController && self.parentViewController) {
            tabBarController = [self.parentViewController rdv_tabBarController];
        }
    
        return tabBarController;
    }
    @end

    然后在RDVTabBarController创建中调用ViewController的扩展方法rdv_setTabBarController:(因为RDVTabBarController也是ViewController的子类,所以可以调用)。通过这个方法设置关联,将TabBarViewController中的childView都和TabBarViewController关联起来。

    下面是RDVTabBarController中调用扩展方法设置关联的代码:
    (这个简化了其他与关联无关的代码,需要了解其他的,自己从github上下载这个第三方库看源码。)

    - (void)setViewControllers:(NSArray *)viewControllers {        
    
    if (viewControllers && [viewControllers isKindOfClass:[NSArray class]]) {
           //向TabBarViewController中添加关联
            for (UIViewController *viewController in viewControllers) {
                [viewController rdv_setTabBarController:self];
            }
        } else {
            //没有向TabBarViewController中添加viewController,删除关联,删除TabBarViewCOntroller中的childViewController
            for (UIViewController *viewController in _viewControllers) {
                [viewController rdv_setTabBarController:nil];
            }
            _viewControllers = nil;
        }
    }

    完成了上面的设置之后,我们就在项目中,直接通过当前运行的viewController来获取tabBarViewController这个属性了。

    下面是示范代码:

    [self.rdv_tabBarController setTabBarHidden:!_viewController.rdv_tabBarController.tabBarHidden animated:YES];
    
    //通过点运算符,调用UIViewController中的扩展方法:`rdv_tabBarController`。然后在`rdv_tabBarController`扩展方法中,递归寻找和RDVTabBarViewController关联的属性。

    运行结果简介:

    简单运行一个demo,po打出相关RDVTabBarController中相关信息:

    • 放入TabBarController中的四个NavigationViewController
      存放结果

    • 第一个NavigationViewController,push推入下一个viewController;推入之后,运行上面的“直接通过当前运行的viewController来获取tabBarViewController”中的代码:

    编辑内容

    搜索关联

    在这里递归寻找关联值,第一个ViewController地址为:’0x7f9378e750a0‘没有进行关联,找不到。然后跳到父视图中,地址为:‘0x7f9378d39a70’有相关,找到,不需要在向下寻找。递归结束,找到关联值,返回结果。

    小结:

    这里,通过扩展和关联的结合使用,将RDVTabBarController这个实例属性,和当前的ViewController结合起来。这种思想,在以后自己编写第三方库函数的时候,值得借鉴!
    总体来说,associative的主要原理,就是把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分。


    参考:

    http://m.blog.csdn.net/blog/csz0102/19555673

  • 相关阅读:
    POJ 3468 A Simple Problem with Integers
    BZOJ 4430 Guessing Camels
    POJ 2309 BST
    POJ 1990 MooFest
    cf 822B Crossword solving
    cf B. Black Square
    cf 828 A. Restaurant Tables
    Codefroces 822C Hacker, pack your bags!
    [HDU 2255] 奔小康赚大钱
    [BZOJ 1735] Muddy Fields
  • 原文地址:https://www.cnblogs.com/AbeDay/p/5026907.html
Copyright © 2011-2022 走看看