Objective-C Runtime之着魔的UIAlertView

原文出處: ian博客(@ianisme )   html

傳統的UIAlertView:

在一個類中有多個UIAlertView,不一樣的UIAlertView對應不一樣的事件,咱們使用的傳統方法以下:ios

Objective-Cgit

1github

2安全

3atom

4spa

5.net

6orm

7htm

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

#pragma mark - action method

 

- (IBAction)firstButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.tag = 1001;

    [alertView show];

}

 

- (IBAction)secondButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.tag = 1002;

    [alertView show];

}

 

- (IBAction)ThirdButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.tag = 1003;

    [alertView show];

}

 

#pragma mark - delegate method

 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

    if (alertView.tag == 1001) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1001執行ok");

        }

    } else if (alertView.tag == 1002) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1002執行ok");

        }

    } else if (alertView.tag == 1003) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1003執行ok");

        }

    }

}

咱們要給每一個UIAlertView賦值一個tag值,在delegate方法中還要進行tag的判斷以及buttonIndex的判斷,太繁瑣了。

着魔的UIAlertView:

下面咱們使用Category和Associated Objects進行魔法修改

建立一個UIAlertView的Category

UIAlertView+ActionBlock.h

Objective-C

1

2

3

4

5

6

7

8

9

#import <UIKit/UIKit.h>

 

typedef void (^AlertCallBack)(UIAlertView *, NSUInteger);

 

@interface UIAlertView (ActionBlock)<UIAlertViewDelegate>

 

@property (nonatomic, copy) AlertCallBack callBack;

 

@end

UIAlertView+ActionBlock.m

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

#if TARGET_IPHONE_SIMULATOR

#import <objc/objc-runtime.h>

#else

#import <objc/runtime.h>

#import <objc/message.h>

#endif

 

@implementation UIAlertView (ActionBlock)

 

- (void)setCallBack:(AlertCallBack)callBack

{

    objc_setAssociatedObject(self, @selector(callBack), callBack, OBJC_ASSOCIATION_COPY_NONATOMIC);

    self.delegate = self;

}

 

- (AlertCallBack)callBack

{

    return objc_getAssociatedObject(self, @selector(callBack));

}

 

#pragma mark - delegate method

 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

    if (self.callBack) {

        self.callBack(alertView, buttonIndex);

    }

}

在主類中取消delegate,使用block屬性

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#pragma mark - action method

 

- (IBAction)firstButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){

        if (buttonIndex == 1) {

            NSLog(@"魔法alertView1001執行ok");

        }

    };

    [alertView show];

}

 

- (IBAction)secondButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){

        if (buttonIndex == 1) {

            NSLog(@"魔法alertView1002執行ok");

        }

    };

    [alertView show];

}

 

- (IBAction)ThirdButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){

        if (buttonIndex == 1) {

            NSLog(@"魔法alertView1003執行ok");

        }

    };

    [alertView show];

}

咱們經過使用Category給UIAlertView擴展了一個block屬性,當block被設置後就會調用setCallBack方法,觸發self.delegate = self,即主類中的UIAlertView的delegate方法被Category中的方法覆蓋。這樣不只有效解決問題,還解決了其餘人修改該類的安全性(block被去掉後,原delegate恢復)

以下不給tag值爲1003的UIAlertView設置block,即調用原delegate方法。

Objective-C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

- (IBAction)firstButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){

        if (buttonIndex == 1) {

            NSLog(@"魔法alertView1001執行ok");

        }

    };

    alertView.tag = 1001;

    [alertView show];

}

 

- (IBAction)secondButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.callBack = ^(UIAlertView *alertView, NSUInteger buttonIndex){

        if (buttonIndex == 1) {

            NSLog(@"魔法alertView1002執行ok");

        }

    };

    alertView.tag = 1002;

    [alertView show];

}

 

- (IBAction)ThirdButtonClick:(id)sender {

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"title" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];

    alertView.tag = 1003;

    [alertView show];

}

 

- (IBAction)fourthButtonClick:(id)sender {

    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"title" message:@"message" preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"cancel" style:UIAlertActionStyleCancel handler:nil];

    UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *alertAction){

        NSLog(@"若是你是iOS8以上的應用,這個適合你,簡單明瞭");

    }];

    [alertController addAction:cancelAction];

    [alertController addAction:okAction];

    [self presentViewController:alertController animated:YES completion:nil];

}

 

#pragma mark - delegate method

 

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

{

    if (alertView.tag == 1001) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1001執行ok");

        }

    } else if (alertView.tag == 1002) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1002執行ok");

        }

    } else if (alertView.tag == 1003) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1003執行ok");

        }

    } else if (alertView.tag == 1004) {

        if (buttonIndex == 1) {

            NSLog(@"普通alertView1004執行ok");

        }

    }

}

相關Demo下載:

https://github.com/ianisme/UIAlertViewBYRuntime_Demo

總結:

經過Associated Objects咱們有效的解決了UIAlertView的繁瑣問題,若是您是開發iOS8以上的應用,建議您棄用UIAlertView,蘋果的UIAlertController已經有了更好的解決方案。QQ技術交流羣290551701

相關文章
相關標籤/搜索