前言
最近公司项目有类游戏答题的要求, 选对的题目, 答案和动画不一样, 但是界面是用for循环做的, 这样就得提取相应答案按钮对应的其他控件来换图片或者换动画, 一共十几个题型, 用tag记录实在是太蛋疼就直接用关联对象给控件命名了, 记起来也方便.
关联对象介绍
实现
这样给系统控件添加方法, 一般就是用分类, 所以用分类来实现类似view.tag的功能.
新建一个UIView+YNViewName
的类目
声明文件:
#import <UIKit/UIKit.h>
@interface UIView (YNViewName)
- (UIView *)yn_viewNamed:(NSString *)name;
@property (copy, nonatomic) NSString *yn_viewName;
@end
实现文件:
记得先引用#import <objc/runtime.h>
, 关联对象也是在runtime基础上做文章.
#import "UIView+YNViewName.h"
#import <objc/runtime.h>
static const void *YNViewNameKey = @"YNViewName";
@implementation UIView (YNViewName)
- (void)setYn_viewName:(NSString *)yn_viewName {
objc_setAssociatedObject(self, YNViewNameKey, yn_viewName, OBJC_ASSOCIATION_COPY_NONATOMIC);;
}
- (NSString *)yn_viewName {
return objc_getAssociatedObject(self, YNViewNameKey);
}
- (UIView *)yn_viewNamed:(NSString *)name {
if (!name) {
return nil;
}
return [self viewWithName:name];
}
- (UIView *)viewWithName:(NSString *)aName {
if (!aName) {
return nil;
}
if ([self.yn_viewName isEqualToString:aName]) {
return self;
}
// 子视图递归
for (UIView *subview in self.subviews) {
UIView *theView = [subview yn_viewNamed:aName];
if (theView) {
return theView;
break;
}
}
return nil;
}
@end
用法
SB或者XIB
使用SB或者XIB, 可以不声明对象, 这种做法好与不好不做讨论. 详见demo.
代码
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(100, 400, 50, 25)];
imageView.backgroundColor = [UIColor blackColor];
imageView.yn_viewName = imageViewName;
[self.view addSubview:imageView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(100, 450, 50, 25);
button.backgroundColor = [UIColor greenColor];
[button addTarget:self action:@selector(changeColor) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
}
- (void)changeColor {
UIImageView *imageView = (UIImageView *)[self.view yn_viewNamed:imageViewName];
imageView.backgroundColor = [UIColor grayColor];
}