Objective-c中的自定义属性属性

时间:2011-02-07 07:45:59

标签: objective-c ios attributes properties

可以像在VB.NET中一样在Objective-C中创建自定义属性属性吗?例如,在VB.NET中,您可以创建“Browsable”属性并在运行时读取它以确定是否应显示属性。

Public Class Employee
    <Browsable(True)> _
    Public Property Property1() As String
        Get

        End Get
        Set(ByVal Value As String)

        End Set
    End Property

    <Browsable(False)> _
    Public Property Property2() As String
        Get

        End Get
        Set(ByVal Value As String)

        End Set
    End Property
End Class

我想在Objective-C中做同样的事情,即使它是一个只能在编译时设置且根本无法更改的固定属性。

我要做的是为我的类的属性添加一个属性,以确定是否应该序列化属性。

我知道标准的Objective-C属性(只读,非原子等),但那些对我没有帮助......除非你有创造性地使用它们。我还研究了使用__attribute__(("Insert attribute here"))关键字的C属性,但C具有特定用途的特定属性,我甚至不确定您是否可以在运行时读取它们。如果我错过了一个可以帮助我的话,请告诉我。

我尝试使用typdef。例如:

typdef int serializableInt;
serializableInt myInt;

并使用property_getAttributes() Objective-C运行时函数,但它告诉我的是myInt是一个int。我想在这种情况下,typedef非常像一个宏......除非我能在运行时创建一个serializableInt类型的变量。无论如何,这里有property_getAttributes()来自{{1}}的值Apple's documentation

另一个要求是该属性必须与NSObject子类以及原始数据类型一起使用。我想到了将类黑名单或白名单添加到类中以便告诉我要跳过或序列化哪些属性的想法,这基本上是相同的想法。我只是试图将黑/白名单移动到属性,这样当你看到一个类的头文件时它很容易理解,它在我创建的任何类中都是一致的,并且它不易出错。

此外,这是需要考虑的事情。我真的不需要attribue有一个值(TRUE或FALSE; 1,2,3;或其他),因为属性本​​身就是值。如果属性存在,则序列化;否则,跳过。

感谢任何帮助。如果您确定在Objective-C上无法做到这一点,请告诉我。感谢。

5 个答案:

答案 0 :(得分:3)

如果要将属性添加到属性,类,方法或ivar,可以尝试使用github.com/libObjCAttr。它真的很容易使用,通过cocoapods添加它,然后你可以添加这样的属性:

@interface Foo

RF_ATTRIBUTE(YourAttributeClass, property1 = value1)
@property id bar;

@end

在代码中:

YourAttributeClass *attribute = [NSDate RF_attributeForProperty:@"bar" withAttributeType:[YourAttributeClass class]];
// Do whatever you want with attribute, nil if no attribute with specified class
NSLog(@"%@", attribute.property1)

答案 1 :(得分:1)

除非我错过了你的观点......

我建议宣布一个协议。然后使用objc对象的实例作为采用该协议的objc类中的变量。

@interface MONProtocol

- (BOOL)isSerializable;
- (BOOL)isBrowsable;

/* ... */

@end

@interface MONInteger : NSObject <MONProtocol>
{
    int value;
}

- (id)initWithInt:(int)anInt;

@end

@interface MONIntegerWithDynamicProperties : NSObject <MONProtocol>
{
    int value;
    BOOL isSerializable;
    BOOL isBrowsable;
}

- (id)initWithInt:(int)anInt isSerializable:(BOOL)isSerializable isBrowsable:(BOOL)isBrowsable;

@end

// finally, a usage
@interface MONObjectWithProperties : NSObject
{
    MONInteger * ivarOne;
    MONIntegerWithDynamicProperties * ivarTwo;
}

@end

如果你想共享一些实现,那么只需继承NSObject并扩展基类。

然后,您可以为要表示的类型/结构编写一些变体。

答案 2 :(得分:1)

我到目前为止看到的其他答案的不足之处在于它们是作为实例方法实现的,即在查询此元数据之前,您需要拥有一个实例。可能存在适当的边缘情况,但关于类的元数据应该作为类方法实现,就像Apple那样,例如:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key { }

我们可以想象我们自己沿着类似的路线:

+ (BOOL)keyIsBrowsable:(NSString*)key { }

+ (NSArray*)serializableProperties { }

让我们假设我们的类名为FOOBar,我们想知道baz键是否可浏览。无需创建FOOBar,我们可以说:

if ([FOOBar keyIsBrowsable:@"baz"]} { ... }

使用这种可以使用自定义属性完成的技术,您可以做很多事情。 (除了需要来自编译器IIRC的Serializable属性之类的东西。)然而,关于自定义属性的好处是,很容易区分什么是元数据和什么是内在的元数据。类的实际功能,但我认为这是一个小小的收获。

(当然,您可能必须检查keyIsBrowsable:选择器是否存在,就像您必须检查是否存在特定的自定义属性一样。同样,自定义属性略有增加在这里,因为我们可以告诉.NET运行时将它们全部交给我们。)

答案 3 :(得分:0)

我在序列化对象时遇到了类似的问题。我的解决方案是添加一个@property (nonatomic, readonly) NSArray *serialProperties;,它有一个自定义的getter,它返回应该序列化的(子)类属性的名称(作为NSString *)。

例如:

- (NSArray *)serialProperties {
    return @[@"id", @"lastModified", @"version", @"uid"];
}

或者在子类中:

- (NSArray *)serialProperties {
    NSMutableArray *sp = [super serialProperties].mutableCopy;
    [sp addObject:@"visibleName"];
    return sp;
}

然后,您可以通过[self dictionaryWithValuesForKeys:self.serialProperties]轻松获取所有媒体资源及其价值。

答案 4 :(得分:0)

除了sdk提供的内容之外,您无法添加自定义属性。 。 但是有一个工作要实现你的目标...

@interface classTest:NSObject

   @property(strong,nonatomic)NSString *firstName;

   @property(strong,nonatomic)NSString *lastName;

   @property(strong,nonatomic)NSMutableDictionary *metaData;

@end
@implementation classTest

 - (id) init
{

 self = [super init];
 //Add meta data
  metaData=[[NSmutableDictionary alloc]init];

  //
  if( !self ) return nil;
  return self;
 }

@end

所以使用字典添加和检索元数据......

我希望它有所帮助....