【问题标题】:Subclass UIButton to add a property子类 UIButton 添加属性
【发布时间】:2011-07-26 21:34:36
【问题描述】:

我想继承UIButton 以添加一些我需要的属性(不是方法...只有属性)。

这里是我的子类的代码:

//.h-----------------------
@interface MyButton : UIButton{
    MyPropertyType *property;
}

@property (nonatomic,retain) MyPropertyType *property;
@end

//.m--------------------------
@implementation MyButton
@synthesize property;

@end

这里是我如何使用这个类:

MyButton *btn = ((MytButton *)[MyButton buttonWithType:UIButtonTypeRoundedRect]);
btn.property = SomeDataForTheProperty;

我从哪里得到这个错误:

 -[UIRoundedRectButton setProperty:]: unrecognized selector sent to instance 0x593e920

因此,我从ButtonWithType 获得了一个UIRoundedRectButton(Mybutton *) 不能施放它... 我必须做什么才能获得MyButton 对象? -init 是唯一的解决方案吗?

谢谢!

【问题讨论】:

  • 我可以确认使用 init 方法可以正常工作,但我获得了 UIButtonTypeCustom ...不是roundRect
  • 子类化按钮在 iOS6 和 iOS7 中对我有用,我想知道这是否在早期的操作系统中被破坏了。

标签: iphone objective-c ios uibutton


【解决方案1】:

你需要做的:

MyButton *btn = [[MyButton alloc] init];

创建您的按钮。 buttonWithType:UIButtonTypeRoundedRect 只创建 UIButton 对象。

=== 编辑 ===

如果您希望使用 RoundedRect 按钮;那么我会提出以下建议。基本上,我们只需要创建一个带有我们想要的任何属性的 UIView 并将所需的按钮添加到该视图。


.h

@interface MyButton : UIView
{
    int property;
}

@property int property;
@end

.m

@implementation MyButton
@synthesize property;

- (id)initWithFrame:(CGRect)_frame
{
    self = [super initWithFrame:_frame];
    if (self)
    {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        btn.frame = self.bounds;
        [self addSubview:btn];
    }
    return self;
}

@end

用法:

MyButton *btn = [[MyButton alloc] initWithFrame:CGRectMake(0, 0, 200, 20)];
btn.property = 42;

[self.view addSubview:btn];

【讨论】:

  • 这个方法不限制你使用 UIButtonTypeCustom 类型的按钮吗?
  • 现在他无法访问任何按钮方法,除非他通过属性​​公开 btn。
  • @Joe:好的,它也可以提升为属性。或者你可以隐藏一些UIButton 功能。伟大的门面,韦克斯。
【解决方案2】:

尝试改用带有Associative References 的类别。它更简洁,适用于UIButton 的所有实例。

UIButton+Property.h

#import <Foundation/Foundation.h>

@interface UIButton(Property)

@property (nonatomic, retain) NSObject *property;

@end

UIButton+Property.m

#import "UIButton+Property.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_PROPERTY_KEY;

@dynamic property;

-(void)setProperty:(NSObject *)property
{
    objc_setAssociatedObject(self, &UIB_PROPERTY_KEY, property, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(NSObject*)property
{
    return (NSObject*)objc_getAssociatedObject(self, &UIB_PROPERTY_KEY);
}

@end

//示例用法

#import "UIButton+Property.h"

...

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button1.property = @"HELLO";
NSLog(@"Property %@", button1.property);
button1.property = nil;
NSLog(@"Property %@", button1.property);

【讨论】:

  • 我使用了NSObject,但类型可以是您定义的任何类型,包括MyPropertyTypeUIButton(Property) 非常通用,考虑将属性重命名为更有用的东西。
  • 不需要初始化,地址是关键。
  • 我真的不认为这是一个干净的解决方案...这是一个 hacky 解决方案。
  • @JoãoNunes 想解释一下"hacky" 是什么well documented solution
  • 在 UIButton 的情况下,我认为这是一个比子类化更好的解决方案,因为在子类上调用 buttonWithType: 不会返回具有继承方法的对象。
【解决方案3】:

我有一个简单的方案,它只涉及几个库方法,没有样板文件,并且您要添加的每个属性只需 3 行代码。下面添加了两个示例属性:startPoint 和 tileState。出于说明目的,这里是您需要为 tileState 之类的属性添加的行:

//@property (assign, nonatomic) SCZTileState tileState; // tileState line 1 
//@property (assign, nonatomic) SCZTileState tileState; // tileState line 2 
//@dynamic tileState;                                   // tileState line 3

我的blog post describing how this works有更多详细信息

UIButton+SCZButton.h

#import <UIKit/UIKit.h>

@interface UIButton (SCZButton)
@property (readwrite, nonatomic) id assocData;
@end

UIButton+SCZButton.m

//  UIButton+SCZButton.m
//  Copyright (c) 2013 Ooghamist LLC. All rights reserved.

#import "UIButton+SCZButton.h"
#import <objc/runtime.h>

@implementation UIButton (SCZButton)
- (id)assocData {
    id data = objc_getAssociatedObject(self, "SCZButtonData");
    return data;
}
- (void)setAssocData:(id)data {
    objc_setAssociatedObject(self, "SCZButtonData", data,  
                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

OOGTotallyTile.h

//  UIButton+OOGTotallyTile.m
//  Copyright (c) 2013 Ooghamist LLC. All rights reserved.
#import <UIKit/UIKit.h>
#import "UIButton+SCZButton.h"
#define kPointLabelTag 837459

typedef enum {
    SCZTileStatePlaced,
    SCZTileStateDropping,
    SCZTileStateDropped
} SCZTileState;

@interface SCZButtonData : NSObject
@property (assign, nonatomic) CGPoint startPoint;
@property (assign, nonatomic) SCZTileState tileState;   // tileState line 1
@end

@interface UIButton (OOGTotallyTile)
@property (readonly, nonatomic) SCZButtonData *buttonData;
@property (assign, nonatomic) CGPoint startPoint;
@property (assign, nonatomic) SCZTileState tileState;  // tileState line 2
@end

OOGTotallyTile.m

//  UIButton+OOGTotallyTile.m
//  Copyright (c) 2013 Ooghamist LLC. All rights reserved.

#import "OOGTotallyTile.h"

@implementation SCZButtonData
@end

@implementation UIButton (OOGTotallyTile)
@dynamic startPoint;
@dynamic tileState; // tileState line 3

- (SCZButtonData*)buttonData {
    if ( ! self.assocData) {
        self.assocData = [[SCZButtonData alloc] init];
    }
    return self.assocData;
}
- (id)forwardingTargetForSelector:(SEL)aSelector {
    id forwardingTarget = [super forwardingTargetForSelector:aSelector];
    if ( ! forwardingTarget) {
        return [self buttonData];
    }
    return forwardingTarget;
}
@end

【讨论】:

    猜你喜欢
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-04
    • 1970-01-01
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    相关资源
    最近更新 更多