在类别接口/实现中设置新属性

时间:2010-11-04 16:16:47

标签: objective-c ios categories

好的,我有这个,但它不会工作:

@interface UILabel (touches)

@property (nonatomic) BOOL isMethodStep;

@end


@implementation UILabel (touches)

-(BOOL)isMethodStep {
    return self.isMethodStep;
}

-(void)setIsMethodStep:(BOOL)boolean {
    self.isMethodStep = boolean;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if(self.isMethodStep){
        // set all labels to normal font:
        UIFont *toSet = (self.font == [UIFont fontWithName:@"Helvetica" size:16]) ? [UIFont fontWithName:@"Helvetica-Bold" size:16] : [UIFont fontWithName:@"Helvetica" size:16];

        id superView = self.superview;
        for(id theView in [(UIView *)superView subviews])
            if([theView isKindOfClass:[UILabel class]])
                [(UILabel *)theView setFont:[UIFont fontWithName:@"Helvetica" size:16]];

        self.font = toSet;
    }
}

@end

如果我取出getter和setter方法然后它不起作用它告诉我我需要创建一些getter和setter方法(或使用@synthesize - 但在@implementation中放@synthesize也会引发错误)。但是使用getter和setter方法,我得到一个EXC_BAD_ACCESS和崩溃。有任何想法吗?感谢

汤姆

7 个答案:

答案 0 :(得分:39)

无法通过类别方法向现有类添加成员和属性。

https://developer.apple.com/library/content/documentation/General/Conceptual/DevPedia-CocoaCore/Category.html

一种可能的解决方法是编写“setter / getter-like”方法,该方法使用单例来保存变量,这些变量本来就是成员。

-(void)setMember:(MyObject *)someObject
{
    NSMutableDictionary *dict = [MySingleton sharedRegistry];
    [dict setObject:someObject forKey:self];
}

-(MyObject *)member
{
    NSMutableDictionary *dict = [MySingleton sharedRegistry];
    return [dict objectforKey:self];
}

或 - 当然 - 编写一个继承自UILabel的自定义类


请注意,现在可以在运行时注入关联对象The Objective C Programming Language: Associative References

答案 1 :(得分:4)

检查了所有答案,但未找到最常见的解决方案:

#import <objc/runtime.h>

static void const *key;

@interface ClassName (CategoryName)
@property (nonatomic) BOOL myProperty;
@end

@implementation ClassName (CategoryName)
- (BOOL)myProperty {
    return [objc_getAssociatedObject(self, key) boolValue];
}

- (void)setMyProperty:(BOOL)value {
    objc_setAssociatedObject(self, key, @(value), OBJC_ASSOCIATION_RETAIN);
}
@end

答案 2 :(得分:1)

实际上有一种方法可能并不理想,但确实有效 要使其工作,您需要为类X创建一个类别,并且只能在相同X的子类上使用(例如,类UIView (Background)可以与类{{1一起使用},但不直接与MyView : UIView

UIView

然后

// UIView+Background.h

@interface UIView (Background)

@property (strong, nonatomic) NSString *hexColor;

- (void)someMethodThatUsesHexColor;

@end

// UIView+Background.h

@implementation UIView (Background)

@dynamic hexColor; // Must be declared as dynamic

- (void)someMethodThatUsesHexColor {
    NSLog(@"Color %@", self.hexColor);
}

@end

使用此方法,您需要重新声明&#34;你的属性,但在那之后,你可以在你的类别中进行所有操作。

答案 3 :(得分:1)

您可以在运行时注入关联的对象。

#import <objc/runtime.h>

@interface UIView (Private)

@property (nonatomic, assign) CGPoint initialTouchPoint;
@property (nonatomic, strong) UIWindow *alertWindow;

@end

@implementation UIView (Private)

@dynamic initialTouchPoint, alertWindow;

- (CGPoint)initialTouchPoint {
    return CGPointFromString(objc_getAssociatedObject(self, @selector(initialTouchPoint)));
}

- (void)setInitialTouchPoint:(CGPoint)initialTouchPoint {
    objc_setAssociatedObject(self, @selector(initialTouchPoint), NSStringFromCGPoint(initialTouchPoint), OBJC_ASSOCIATION_RETAIN);
}

- (void)setAlertWindow:(UIWindow *)alertWindow {
    objc_setAssociatedObject(self, @selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIWindow *)alertWindow {
    return objc_getAssociatedObject(self, @selector(alertWindow));
}

@end

答案 4 :(得分:0)

编辑:警告:此属性对于该类的所有实例都具有唯一值。

这对我有用,但这只是因为我的应用程序中只有一个这个类的实例。

#import <AVFoundation/AVFoundation.h>

@interface AVAudioPlayer (AstroAVAudioPlayer)

@property (nonatomic) BOOL redPilot;

@end


#import "AVAudioPlayer+AstroAVAudioPlayer.h"

@implementation AVAudioPlayer (AstroAVAudioPlayer)

BOOL _redPilot;

-(void) setRedPilot:(BOOL)redPilot
{
    _redPilot = redPilot;
}

-(BOOL) redPilot
{
    return _redPilot;
}

@end

答案 5 :(得分:0)

我发现的一个解决方案就是给每个要标记为唯一标记的对象。

我制作了一个UILabel类别,为我的所有标签添加自定义字体,但有些我希望它们是粗体,所以我这样做了 - &gt;

- (void) layoutSubviews {
    [super layoutSubviews];
    [self addCustomFont];   
}

- (void) addCustomFont {
    if (self.tag == 22) {
        [self setFont:[UIFont fontWithName:SEGOE_BOLD size:self.font.pointSize]];
    }else{
        [self setFont:[UIFont fontWithName:SEGOE_LIGHT size:self.font.pointSize]];
    }
}

答案 6 :(得分:0)

似乎自 Xcode 7 (7.0.1,7A1001)以来,属性在类别中受支持。我注意到 Xcode 现在为 Core Data 子类生成类别。

例如,我收到了文件:

位置+ CoreDataProperties.h

#import "Location.h"

NS_ASSUME_NONNULL_BEGIN

@interface Location (CoreDataProperties)

@property (nullable, nonatomic, retain) NSNumber *altitude;
@property (nullable, nonatomic, retain) NSNumber *latitude;
@property (nullable, nonatomic, retain) NSNumber *longitude;

@end

NS_ASSUME_NONNULL_END

位置+ CoreDataProperties.m

#import "Location+CoreDataProperties.h"

@implementation Location (CoreDataProperties)

@dynamic altitude;
@dynamic latitude;
@dynamic longitude;

@end

所以看起来类别中的属性现在可能有效。我没有在非核心数据类上进行测试。

我注意到他们确实将类别文件包含在原始类中:

<强> Location.h

@interface Location : NSManagedObject

@end

#import "Location+CoreDataProperties.h"

这允许原始类编辑类别指定的属性。