obj-c编程19:关联对象

对于一些无法子类化的实例对象来说,如果希望将一个对象与其绑定该如何做呢?
以下示例虚构了一个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;
}

你可能感兴趣的:(objC,关联对象)