高效开发iOS系列(runtime篇) -- 巧妙运用对象关联(Associated Objects)来设计alertview

原创 2015年12月22日 22:15:15

热身 (简单介绍)


这个鬼(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
版权声明:本文为博主原创文章,转载请注明出处。

iOS开发------runtime关联对象(动态添加属性)

如果想用一个系统的类,但是该类又不满足需求,首先肯定是继承自系统的类,重新构建一个类,但这种方法,如果我们需求的类之比原来的类多一个属性呢,继承似乎又显得比较麻烦,这个时候也许用runtime的关联对...
  • RunIntoLove
  • RunIntoLove
  • 2016年03月01日 10:43
  • 2108

OC学习之Runtime之关联对象

坚持 成长 每日一篇前言在Runtime中有一个我们经常忽略的特性就是关联对象特性。 关联对象类似于成员变量,不同的是关联对象是在类创建实例后添加进去的。所以不能通过Runtime的获取成员变量的方...
  • u014410695
  • u014410695
  • 2015年09月15日 10:06
  • 963

runtime之Associated Objects

#import Objective-C开发者应该小心谨慎地遵循这个危险咒语的各种准则。一个很好的原因的就是:混乱的运行时代码会改变运行在其架构之上的所有代码。 从利的角度来讲,  中的函数...
  • biggercoffee
  • biggercoffee
  • 2015年12月01日 23:06
  • 2260

iOS运行时机制之成员和属性,关联对象

runtime
  • u011342466
  • u011342466
  • 2016年03月07日 20:23
  • 935

Neoshine linux 中 << 的妙用;

Neoshine linux 中 记得自己曾经一度因为不能实现终端shell脚本不能够实现对程序的输入进行自动填充而困惑,今天终于解惑了;采用的关键命令就是下面我就用一个试验来完成这次测试--首先编写...
  • baymoon
  • baymoon
  • 2007年03月05日 17:23
  • 721

iOS开发:runtime原理简单分析和基本使用场景

一:rumtime原理简单分析 runtime是运行时库(Runtime Library),也简称运行时。 它是一个主要是C和汇编写的库,对C进行了特殊的处理,将结构体视为对象,将函数视为方法,使得C...
  • indulgeIn
  • indulgeIn
  • 2016年04月10日 12:25
  • 4133

IC设计基础系列之CDC篇5:跨时钟域信号处理 (发起请求信号和回传确定信号,有状态图,有代码)

来自:http://blog.csdn.net/skyplain1984/article/details/54782968 一、慢速多周期信号 Signal-in为clkA时钟域多周期信号。此...
  • Times_poem
  • Times_poem
  • 2017年06月11日 18:53
  • 479

iOS-关联属性Associate

iOS分类用的比较多,基本都是扩展方法,如果想要扩展属性,就要用到runtime了,使用 objc_getAssociatedObject objc_setAssociatedOb...
  • GrowingGiant
  • GrowingGiant
  • 2015年02月27日 23:55
  • 1249

ios runtime 动态属性objc_setAssociatedObject和objc_getAssociatedObject

// // ViewController.m // objc_runtime // // Created by 王飞 on 16/4/11. // Copyright © 2016年 com....
  • qq_16844001
  • qq_16844001
  • 2016年04月11日 15:25
  • 2330

Object-C基础知识问答

一个区分度很大的面试题 考察一个面试者基础咋样,基本上问一个 @property 就够了: @property 后面可以有哪些修饰符? 线程安全的: atomic,nonatomic 访问权限...
  • tyforfreedom
  • tyforfreedom
  • 2015年07月18日 15:39
  • 1162
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:高效开发iOS系列(runtime篇) -- 巧妙运用对象关联(Associated Objects)来设计alertview
举报原因:
原因补充:

(最多只允许输入30个字)