高效开发iOS系列(runtime篇) -- 巧妙运用对象关联(Associated Objects)来设计alertview
热身 (简单介绍)
这个鬼
(objc_AssociationPolicy : 对象关联)
可以给某对象关联其他对象, 这些对象通过"键"
来区分. 存储对象值的时候, 可以指明"存储策略"
, 用以维护相应的"内存管理语义"
.存储策略由名为objc_AssociationPolicy的枚举所定义. 同时拥有与之等效@property
的属性. …(此处省略十万字的理论)
本篇重点是讲述如何巧妙利用这个东西
(关联)
, 来让我们高效的编写objective-c
. 也可以理解为实战篇
.在高效开发iOS系列里, 大部分都是偏向于实战的技巧方法与总结来提升iOS开发效率, 几乎都不讲理论,所以需要具备一点基础. 而本篇讲的则是
objc_AssociationPolicy(关联)
和alertview
之间的实战技巧, 如果还不会Associated Objects
或者想要更深入更全面的认识Associated Objects
理论的小伙伴们, 可以查看这篇理论篇文章入门 : http://blog.csdn.net/biggercoffee/article/details/50135477
来一起干一票
繁琐的alertview的事件处理, 早就看它不爽了
// button 点击执行的方法
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
[alertView show];
}
// alertview 点击执行的delegate方法,前提 需要self实现UIAlertViewDelegate协议
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
NSLog(@"执行逻辑操作");
}
如上代码, 这样写确实没错, 但是如果一个页面有多个alertview, 而且点击的时候都要执行不同的逻辑尼? 则要在alertview的delegate方法中写很多的if else
语句,可读性,扩展性等等
都非常差, 如下代码示例:
// button1 点击执行的方法
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
alertView.tag = 1000;
[alertView show];
}
// button2 点击执行的方法
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
alertView.tag = 2000;
[alertView show];
}
// button3 点击执行的方法 ...等等很多alertview
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
alertView.tag = 3000;
[alertView show];
}
// alertview 点击执行的delegate方法,前提 需要self实现UIAlertViewDelegate协议
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView.tag == 1000) {
NSLog(@"alertView1 执行逻辑操作");
}
else if (alertView.tag == 2000) {
NSLog(@"alertView2 执行逻辑操作");
}
else if (alertView.tag == 3000) {
NSLog(@"alertView3 执行逻辑操作");
}
// ...等等很多alertview
}
上面这一大串代码不用解释, 一眼看着都不爽.在delegate
的方法中根据tag或者成员变量的alert等很多方式来标注alertview的唯一性, 然后在根据不同的alertview和点击不同的button来执行逻辑,一堆if else
太繁琐了.
用block
来代替delegate
,现在看如下代码示例 :
// button1 点击执行的方法
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
[alertView show];
[alertView zxp_clickedButtonAtIndexWithBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
NSLog(@"---%zi",buttonIndex);
}];
}
// button2 点击执行的方法
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
[alertView show];
[alertView zxp_clickedButtonAtIndexWithBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
NSLog(@"---%zi",buttonIndex);
}];
}
// button3 点击执行的方法
- (IBAction)alertClick:(id)sender {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
[alertView show];
[alertView zxp_clickedButtonAtIndexWithBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
NSLog(@"---%zi",buttonIndex);
}];
}
开始解剖 -> 三步走
第一步: 创建一个alertview 的category, 并提供与delegate方法一样操作方式的apis第二步: 在category内部把delegate交给其他class来管理并把block也传递给delegate管理的class
第三步: 管理delegate的class调用block即可
示例代码:
.h文件
@interface UIAlertView (zxp_block)
- (void)zxp_clickedButtonAtIndexWithBlock:(void(^)(UIAlertView *alertView,NSInteger buttonIndex))block;
@end
.m文件
#import <objc/runtime.h>
static const char *ZXPDelegateKey = "!ZXPDelegateKey!";
#pragma mark - class
@interface ZXPAlertViewDelegate : NSObject <UIAlertViewDelegate>
{
//block变量
void(^_block)();
}
//初始化的时候传入一个block
- (instancetype)initWithBlock:(void(^)())block;
@end
@implementation ZXPAlertViewDelegate
- (instancetype)initWithBlock:(void(^)())block
{
self = [super init];
if (self) {
//设置关联对象, 值为self
objc_setAssociatedObject(self, ZXPDelegateKey, self, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
_block = block;
}
return self;
}
#pragma mark - delegate methods
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (_block) {
//执行block
_block(alertView,buttonIndex);
}
}
@end
#pragma mark - category
@implementation UIAlertView (zxp_block)
- (void)zxp_clickedButtonAtIndexWithBlock:(void(^)(UIAlertView *alertView,NSInteger buttonIndex))block {
//获取delegate对象
id delegate = objc_getAssociatedObject([[ZXPAlertViewDelegate alloc] initWithBlock:block], ZXPDelegateKey);
//设置delegate为其他对象
self.delegate = delegate;
}
@end