Objective-C是否具有与Java注释等效的function?

Objective-C是否具有与Java注释等效的function?

我想要做的是创build一个属性,并能够以某种方式访问​​一些关于它的元数据。

我想能够确定什么types的类应该在我的数组中,所以我想注释它以某种方式这样说。 然后稍后就可以通过像运行时库那样访问该注释,在那里我可以访问属性列表和它们的名字。

//Put some sort of annotation giving a class name. @property (strong) NSArray *myArray; 

你说:

我想能够确定什么types的类应该在我的数组中,所以我想注释它以某种方式这样说。 然后稍后就可以通过像运行时库那样访问该注释,在那里我可以访问属性列表和它们的名字。

在Objective-C中有几种方法可以做这种事情。 苹果的框架通过添加一个返回所需信息的类方法来做这种事情。 示例: KVO中的相关键 , +[CALayer needsDisplayForKey:]和相关方法 。

所以,让我们创build一个类方法,返回一个可以进入你的容器属性的类的数组,给定属性名称。 首先,我们将添加一个类别NSObject来实现该方法的通用版本:

 @interface NSObject (allowedClassesForContainerProperty) + (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name; @end @implementation NSObject (allowedClassesForContainerProperty) + (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name { if (class_getProperty(self, name.UTF8String)) { return @[ [NSObject class] ]; } else { [NSException raise:NSInvalidArgumentException format:@"%s called for non-existent property %@", __func__, name]; abort(); } } @end 

正如你所看到的,这个方法的默认版本没有做任何特别有用的事情。 但将其添加到NSObject意味着我们可以将消息发送到任何类,而不必担心该类是否实现该方法。

为了使消息返回有用的东西,我们在我们自己的类中覆盖它。 例如:

 @implementation MyViewController + (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name { if ([name isEqualToString:@"myArray"]) { return @[ [UIButton class], [UIImageView class] ]; } else { return [super allowedClassesForContainerPropertyWithName:name]; } } ... 

我们可以这样使用它:

 SomeViewController *vc = ...; SomeObject *object = ...; if ([[vc.class allowedClassesForContainerPropertyWithName:@"bucket"] containsObject:object.class]) { [vc.bucket addObject:object]; } else { // oops, not supposed to put object in vc.bucket } 

这个function没有本地支持,但你可以看看下面的解决scheme – https://github.com/epam/lib-obj-c-attr/这是编译时的属性实现。 定义基于定义的属性,而不是像其他解决scheme(如ObjectiveCAnnotate)中的注释。

Objective C不支持像Java这样的generics,但是因为语言非常灵活,你可以用简单的技巧和知识来完成几乎任何事情。 要实现一个通用的function,你可以在NSArray类上创build一个类别,并创build自己的方法来初始化数组,然后检查对象是否真的是你想要的对象的types。

我会在NSArray上写一个简单的类来拥有这样的function。 假设,我想我的数组保存类MyClass的对象只有我的类别看起来像,

 @interface NSArray(MyCategory) @end @implementation NSArray(MyCategory) -(NSArray*)arrayWithMyClasses:(NSArray*)classes{ if([classes count] > 0){ NSMutableArray *array = [[NSMutableArray alloc] init]; for(id anObj in classes){ NSAssert([anObj isKindOfClass:[MyClass class]], @"My array supports only objetcts of type MyClass"); [array addObject:anObj]; } return array; } return nil; } @end 

当然,它有一些限制。 由于您已经创build了自己的类别,因此您应该使用自己的方法来初始化并创build自己的数组。

不,Objective-C没有注释或generics支持。


实现这样的事情的一种方式是破解Clang来读取注释并将元数据对象关联到原始对象。 但是,你会被绑定到你的黑客编译器。

 NSString *v1 = [[NSString alloc] init]; // associate static char key; NSString *v2 = [[NSString alloc] init]; objc_setAssociatedObject ( v1, &key, v2, OBJC_ASSOCIATION_RETAIN ); // retrieve NSString *associate = (NSString *)objc_getAssociatedObject(v1, &key); 

使用协议进行资格审查并不会太麻烦,而且您可以testing集合是否实现了该协议,但是沿着这种方式您需要为同一个集合中的每个types创build一个类别。 这将需要在编译时使用macros的不同集合。 过于复杂。

 @interface Tomato:NSObject @end @implementation Tomato @end @protocol TomatoNSArray <NSObject> - (Tomato*)objectAtIndexedSubscript:(NSUInteger)index; - (void)setObject:(Tomato*)tomato atIndexedSubscript:(NSUInteger)index; @end // here is the problem, you would need to create one of this for each type @interface NSMutableArray (TomatoNSArray) <TomatoNSArray> @end int main(int argc, char *argv[]) { @autoreleasepool { NSMutableArray<TomatoNSArray> *tomatoes = [[NSMutableArray alloc] initWithCapacity:2]; tomatoes[0] = [Tomato new]; tomatoes[1] = [NSObject new]; // warning: incompatible pointer types } } 

Objective-C是否具有与Java注释等效的function?

不完全相同,但有,而且更好。 在Objective-C中,编译器必须在编译的代码中存储一些types和名称信息(因为语言是高度dynamic的,运行时会发生很多事情,而不是编译时间),例如方法名称(“select器”) ,方法types签名,关于属性的数据,协议等。然后, Objective-C运行时库可以访问这些数据。 例如,您可以通过编写来获取对象所具有的属性列表

 id object = // obtain an object somehow unsigned count; objc_property_t *props = class_copyPropertyList([object class], &count); 

或者你可以检查一个对象属于什么类:

 if ([object isKindOfClass:[NSArray class]]) { // do stuff } 

(是的,运行时库的一部分本身被包装到NSObject的一些方法中,其他的只有C函数API。)

如果您特别想存储关于对象或类的自定义元数据,可以使用关联的引用来完成。

我希望现在应该清楚,答案是否定的 ,而不是现在。

有些人发现了一些似乎适用于其特定用例的替代scheme。

但总的来说,在Objective-C中还没有可比较的特性。 恕我直言,锵元数据似乎为此提供了良好的基础,但只要没有从苹果的支持,这将无济于事,据我了解。

顺便说一句。 我想这应该是清楚的,但只是重申所有:需要两个变化来支持Java提供的注释。

  1. 该语言需要在源代码中扩展注释,例如methodes,properites,classes …。
  2. 访问注释信息需要一个标准接口。 这只能由苹果提供。

大多数替代解决scheme将注释信息移动到运行时并定义它们自己的接口。 objective-c运行时提供了一个标准的接口,但是只有一些技巧你可以注释属性,仍然是运行时人口。

典型的使用案例是一个IOC容器(例如Java中的Spring),它使用带注释的信息来注入其他对象。

我会build议打开一个苹果的function要求来支持这一点。

你的问题的答案是,Objective-C没有Java / C#中的注释的直接等价,虽然有些人认为你可能能够沿着相同的路线devise一些东西,但它可能是太多的工作否则不会通过召集。

为了解决您的特殊需求,请参阅此答案 ,其中显示了如何构build仅保存一种types对象的数组; 执行是dynamic的,而不是像参数types/generics那样是静态的,但是这就是你的注释,所以在这种情况下它可能符合你的特定需求。 HTH。

你需要一个Objective-C的元数据parsing器。 我已经使用ObjectiveCAnnotate(编译时可检索)和ROAnnotation(运行时可检索)。