首页 新闻 会员 周边 捐助

iOS 给原生类(如:UIButton类)拓展一个Block成员属性

0
悬赏园豆:100 [已关闭问题] 关闭于 2014-07-08 16:33

//iOS 给原生类(如:UIButton类)拓展一个Block成员属性

//iOS,Block,Category,runtime

 

/*

 用网上的方法可以实现用category加一般的属性,但是加Block属性后有问题(估计是内存管理的问题)

 备注:Block里面只打印或者简单的画UIOK,一旦用到ViewcontrollerViewcontroller属性或者Block外的变量就会crash

 以下代码分别是

 ①、UIbuttoncategory申明文件(.h文件)部分代码

 ②、UIbuttoncategory实现文件(.m文件)部分代码

 ③、ViewController中使用UIbutton的拓展方法和拓展属性Block

 */

 

 

///////////////////////////////////////////////////////////////////////////////

//--------------------------------

#import

typedef void(^buttonHandler)(UIButton *sender);

@interface UIButton (Utility)

@property (nonatomic, copy) buttonHandler eventHandler;

#pragma mark - block button(handler+cacheMode+isResized) 图片不占内存+拉伸

/**

 *  block button(handler+cacheMode+isResized) 图片不占内存+拉伸

 *

 *  @param frame             coordinate and rectangle

 *  @param superview         supperview

 *  @param title             button tittle

 *  @param titleSelected     titleSelected

 *  @param imageName         imageName

 *  @param imageNameSelected imageNameSelected

 *  @param cacheMode         图片是否加载到内存

 *  @param isResized         图片是否拉伸

 *  @param handler           handler

 *

 *  @return button obj

 */

- (id)initWithFrame:(CGRect)frame

         supperview:(UIView *)superview

              title:(NSString *)title

      titleSelected:(NSString *)titleSelected

              image:(NSString *)imageName

  imageNameSelected:(NSString *)imageNameSelected

     ImageCacheMode:(ImageCacheMode)cacheMode

          isResized:(ImageResized)isResized

      actionHandler:(buttonHandler)handler;

@end

 

 

///////////////////////////////////////////////////////////////////////////////

//--------------------------------

实现文件.m文件(部分代码)部分

#import "UIButton+Utility.h"

#import "Utility.h"

#import <objc/runtime.h>

static const void *UtilityKey = &UtilityKey;

@implementation UIButton (Utility)

#pragma mark - extension member

@dynamic eventHandler;

- (buttonHandler)eventHandler {

    return objc_getAssociatedObject(self, UtilityKey);

}

- (void)setEventHandler:(buttonHandler)eventHandler {

    objc_setAssociatedObject(self, UtilityKey, eventHandler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (void)buttonPressed:(UIButton *)sender {

    NSLog(@"buttonPressed:\nbtn===000:%@\nbtn===111:%@", sender, self);

    if (self.eventHandler) {

        self.eventHandler(sender);

    }

}

#pragma mark - block button(handler+cacheMode+isResized) 图片不占内存+拉伸

/**

 *  block button(handler+cacheMode+isResized) 图片不占内存+拉伸

 *

 *  @param frame             coordinate and rectangle

 *  @param superview         supperview

 *  @param title             button tittle

 *  @param titleSelected     titleSelected

 *  @param imageName         imageName

 *  @param imageNameSelected imageNameSelected

 *  @param cacheMode         图片是否加载到内存

 *  @param isResized         图片是否拉伸

 *  @param handler           handler

 *

 *  @return button obj

 */

- (id)initWithFrame:(CGRect)frame

         supperview:(UIView *)superview

              title:(NSString *)title

      titleSelected:(NSString *)titleSelected

              image:(NSString *)imageName

  imageNameSelected:(NSString *)imageNameSelected

     ImageCacheMode:(ImageCacheMode)cacheMode

          isResized:(ImageResized)isResized

      actionHandler:(buttonHandler)handler {

  self = [super initWithFrame:frame];

  if (self) {

      //set title

      if (title) {

          [self setTitle:title forState:UIControlStateNormal];

      }

      if (titleSelected) {

          [self setTitle:titleSelected forState:UIControlStateSelected];

          [self setTitle:titleSelected forState:UIControlStateHighlighted];

      }

      

      //set image

      if (imageName) {

          [self setBackgroundImage:getImageWithCacheAndResized(imageName, cacheMode, isResized) forState:UIControlStateNormal];

      }

      if (imageNameSelected) {

          [self setBackgroundImage:getImageWithCacheAndResized(imageNameSelected, cacheMode, isResized) forState:UIControlStateSelected];

          [self setBackgroundImage:getImageWithCacheAndResized(imageNameSelected, cacheMode, isResized) forState:UIControlStateHighlighted];

      }

      //set block

      if (handler) {

          self.eventHandler = handler;

          

          //add action

          [self addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];

      }

      

      [superview addSubview:self];

      [self release];

  }

  returnself;

}

@end

      

      

///////////////////////////////////////////////////////////////////////////////

//--------------------------------

//ViewController中使用UIbutton的拓展方法和拓展属性Block

@interface ViewController ()

@end

@implementation ViewController

- (void)loadView {

  [super loadView];

  

  __block ViewController *vc = self;

  NSString *sss = @"Block attribute";

  [[UIButton alloc] initWithFrame:self.view.frame supperview:self.view title:nil titleSelected:nil image:@"common_dialog_new_bg" imageNameSelected:nil ImageCacheMode:ImageCacheModeNoCache isResized:ImageIsResized actionHandler:^(UIButton *sender) {

    NSLog(@"blcokButton");              //只写这一行代码不会crash

    NSLog(@"blcokButton:, %@", sss);    //只写这行代码会crash

               

    //用以下代码也会crash

    SubViewController *subVC = [[SubViewController alloc] init];

    [vc presentViewController:subVC animated:YES completion:nil];

    [subVC release];

    }];

}

@end

ericiOS的主页 ericiOS | 菜鸟二级 | 园豆:204
提问于:2014-07-08 15:47
< >
分享
所有回答(1)
0

 objc_setAssociatedObject(self, UtilityKey, eventHandler, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

这个方法中OBJC_ASSOCIATION_RETAIN_NONATOMIC用

OBJC_ASSOCIATION_COPY_NONATOMIC代替就没有内存管理的问题了

ericiOS | 园豆:204 (菜鸟二级) | 2014-07-08 16:26
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册