对于一些无法子类化的实例对象来说,如果希望将一个对象与其绑定该如何做呢?

以下示例虚构了一个HyConsoleAlert类,User类将会使用该类在控制台显示定制的告警。如果User中包括多个Alert类则需要手动关联处理每个对应的回调方法,这显得异常麻烦。可以使用objc提供的关联对象模式:将处理例程在生成Alert对象时就与之绑定好,较为漂亮的解决了这个问题。下面上源代码:

#import <Foundation/Foundation.h>

static void *HyAlertkey = "HyAlertkey";

@protocol HyMakeChoose
-(void)makeChoose:(NSUInteger)index alertObject:(id)alertObj;
@end

@interface HyConsoleAlert:NSObject{
@private
    NSString *_title,*_msg;
    id <HyMakeChoose> __weak _delegate;
}
-(HyConsoleAlert*)initWithTitle:(NSString *) title andMsg:(NSString *) msg
    andDelegate:(id <HyMakeChoose>)delegate;
-(void)show;
@end

@implementation HyConsoleAlert
-(id)init{
    [NSException raise:@"ERR!" format:@"Invalid init method in HyConsoleAlert"];
    return nil;
}

-(HyConsoleAlert*)initWithTitle:(NSString *) title andMsg:(NSString *) msg
    andDelegate:(id <HyMakeChoose>) delegate{

    self = [super init];
    if(self){
        _title = [title copy];
        _msg = [msg copy];
        _delegate = delegate;
    }
    return self;
}

-(void)show{
    NSLog(@"%@\n%@",_title,_msg);
    NSLog(@"Yes or No?");
    int c;
    while(true){
        c = getchar();
        NSLog(@"DEBUG:getchar : '%c'",c);
        if(c == 'y' || c == 'Y')
            c = 1;
        else if(c == 'n' || c == 'N')
            c = 0;
        else
            continue;

        [_delegate makeChoose:c alertObject:self];
        break;
        }
}
@end

@interface User:NSObject <HyMakeChoose>{
    id _alert;
}
-(void)askUserQuestion;
@end

@implementation User

-(id)init{
    self = [super init];
    return self;
}

-(void)askUserQuestion{
    HyConsoleAlert *alert = [[HyConsoleAlert alloc] initWithTitle:@"hopy' question"
        andMsg:@"Are you human being"
        andDelegate:self];
    void (^block)(NSUInteger) = ^(NSUInteger index){
        if(index == 1)
            NSLog(@"your choose: YES!");
        else if(index == 0)
            NSLog(@"your choose : NO!");
        else
            NSLog(@"error!!!");
    };
    objc_setAssociatedObject(alert,HyAlertkey,block,    OBJC_ASSOCIATION_COPY);
    [alert show];
}

-(void)makeChoose:(NSUInteger)index alertObject:(id)alertObj{
    NSLog(@"alertObj is %@",alertObj);
    void (^block)(NSUInteger) = objc_getAssociatedObject(alertObj,HyAlertkey);
    block(index);
/*
    if(index == 1)
        NSLog(@"your choose: YES!");
    else if(index == 0)
        NSLog(@"your choose : NO!");
    else
        NSLog(@"error!!!");
*/
}
@end

int main(void){
    @autoreleasepool{
    /*
        User *user = [User new];
        HyConsoleAlert *alert = [[HyConsoleAlert alloc]initWithTitle:@"warning"
            andMsg:@"Are you human being?" andDelegate:user];
        [alert show];
    */
        User *user = [User new];
        [user askUserQuestion];
    }
    return 0;
}

obj-c编程19:关联对象的更多相关文章

  1. 并发编程 19—— 显式的Conditon 对象

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  2. 13_Python的面向对象编程-类class,对象object,实例instance

    1.面向对象概述 1.类是用来描述对象的工具,把拥有相同属性和行为的对象分为一组     2.对象是由类实例化出来的一个具体的对象         属性: 对象拥有的名词,用变量表示         ...

  3. 关联对象 AssociatedObject 完全解析

    我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类添加属性的需求,但是使用 @property 并不能在分类中正确创建实例变量和存取方法. 不过,通过 Objective-C ...

  4. Python记录14:面向对象编程 类和对象

    '''现在主流的编程思想有两种,一种是面向对象,一种是面向过程面向过程编程 核心是过程二字,过程指的是解决问题的步骤,即先干什么.再干什么.最后干什么... 基于该思想编写程序就好比再设计一条流水线, ...

  5. Runtime之成员变量&属性&关联对象

    上篇介绍了Runtime类和对象的相关知识点,在4.5和4.6小节,也介绍了成员变量和属性的一些方法应用.本篇将讨论实现细节的相关内容. 在讨论之前,我们先来介绍一个很冷僻但又很有用的一个关键字:@e ...

  6. admin.ModelAdmin 后台管理关联对象,某个字段怎么显示值

    admin.ModelAdmin 后台管理关联对象,某个字段如何显示值?对象 WxpAccount:              accountName = ... 对象 AccountMenu:    ...

  7. Runtime - Associated Objects (关联对象) 的实现原理

    主要围绕3个方面说明runtime-Associated Objects (关联对象) 1. 使用场景 2.如何使用 3.底层实现 3.1  实现原理 3.2 关联对象被存储在什么地方,是不是存放在被 ...

  8. Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)

    Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...

  9. JS面向对像编程四—— prototype 对象

    http://blog.csdn.net/fanwenjieok/article/details/54575560 大部分面向对象的编程语言,都是以“类”(class)作为对象体系的语法基础.Java ...

随机推荐

  1. Java的多态及注意事项

    什么是多态: 多态不但能够改善代码的组织结构和可读性,还能够创建可扩展的程序.在Java中,所有的方法都是通过动态绑定实现多态的.将一个方法调用同一个方法主体关联起来被称作绑定.动态绑定的含义是在运行 ...

  2. hbase高性能读取数据

    有时需要从hbase中一次读取大量的数据,同时对实时性有较高的要求.可以从两方面进行考虑:1.hbase提供的get方法提供了批量获取数据方法,通过组装一个list<Get> gets即可 ...

  3. Dynamics CRM 站点地图中URL的&号编码问题

    现在大多数人对站点地图的操作都通过工具来执行,但如果你使用原始的编辑XML方式,并且你的SubArea中对应的不是某个Entity而是一串URL时,要注意了你的URL中如果带有与符号即&,那就 ...

  4. 深入浅出seesion和cookie

    session在计算机中,尤其是在网络应用中,称为"会话控制".session 对象存储特定用户会话所需的属性及配置信息.session跟踪是Web程序中常用的技术,用来跟踪用户的 ...

  5. Mybatis3.4.0不支持mybatis-spring1.2.5及以下版本

    今天将工程的Mybatis的版本由3.3.0升级到3.4.0导致程序运行错误,使用的mybatis-spring版本是1.2.3,错误内容如下,最后发现是SpringManagedTransactio ...

  6. Cocos2D iOS之旅:如何写一个敲地鼠游戏(七):弹出地鼠

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  7. Android初级教程人品计算器

    先看布局: main_activity.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/andr ...

  8. Docker教程:镜像构建和自动镜像构建dockerfile

    http://blog.csdn.net/pipisorry/article/details/50805379 Docker透过Dockerfile来记录建立Container映象文件的每一个步骤,可 ...

  9. Unity UGUI基础之InputField

    InputField(输入域):为文本输入控件,等同于NGUI的Input. 一.InputField组件: Text Component(文本组件):此输入域的文本显示组件,需带有Text组件. T ...

  10. Socket编程实践(7) --Socket-Class封装(改进版v2)

    本篇博客定义一套用于TCP通信比较实用/好用Socket类库(运用C++封装的思想,将socket API尽量封装的好用与实用), 从开发出Socket库的第一个版本以来, 作者不知道做了多少改进,  ...