我有一个小函数,我想重写,所以该函数对每个类都有效。 目前我有10个相同的功能,所有功能都相同,但每个功能都适用于另一个类。 我知道,我必须用反射来做,但我不太确定如何做到这一点。 我已经阅读了这个链接: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
我所说的功能是:
-(NSCountedSet *)MissionGetReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.MissionSectionList];
return setOfObjects;
}
-(NSCountedSet *)MissionGetSectionReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.DamageAccountList];
return setOfObjects;
}
MissionSectionList和DamageAccountList都是来自两个不同类的NSMutableArrays。 是否有可能看到一个类是否包含NSMutableArray,如果是,那么它应该调用.... modelObject.MyMutableArray?
答案 0 :(得分:2)
你可以使用这样的反射:
- (NSCountedSet *)MissionGet:(id)modelObject
{
SEL propertySelector = NULL;
if ([modelObject respondsToSelector:@selector(MissionSectionList)]) {
propertySelector = @selector(MissionSectionList);
} else if ([modelObject respondsToSelector:@selector(DamageAccountList)]) {
propertySelector = @selector(DamageAccountList);
}
if (!propertySelector) {
[NSException raise:@"Invalid modelObject value" format:@"Model object %@ does not contain any recognised selectors", modelObject];
}
return [[NSCountedSet alloc] initWithArray:[modelObject performSelector:propertySelector]];
}
但可可程序员中更常见的技术是:
- (NSCountedSet *)MissionGet:(id <MyCustomProtocol>)modelObject
{
return [[NSCountedSet alloc] initWithArray:[modelObject missionArray]];
}
您将接受任何确认协议MyCustomProtocol
的对象。该协议在某个头文件中定义,使用:
@protocol MyCustomProtocol
@property (readonly) NSArray *missionArray;
@end
然后在每个类中,将其声明为实现协议:
@interface MissionSectionListClass <MyCustomProtocol>
添加方法实现:
@implementation MissionSectionListClass <MyCustomProtocol>
- (NSArray *)missionArray
{
return self.MissionSectionList;
}
@end
使用协议需要更多代码,但这是“正确”的方法。它允许您添加对新类的支持,而无需对MissiongGet...
方法进行任何更改。
答案 1 :(得分:0)
我认为无法检查某个类是否具有指定类型的成员变量。您只能检查类是否具有指定的方法。
因此,在这种情况下,最好是使所有NSMutableArray列表具有相同的名称,然后为此列表创建声明的属性,然后在... GetReferencedNested方法中执行respondsToSelector。
因此,例如,在您的所有类中创建此属性:
@property (nonatomic, retain) NSMutableArray * list;
然后在..MissionGetReferencedNested方法中:
if ([modelObject respondsToSelector:@selector(list)])
...
如果我错了,请纠正我......
答案 2 :(得分:0)
在风格方面,我也会遵循Abhi的建议。
但是如果你真的想要检查一个你坚持使用的类,例如用你能找到的第一个NSMutableArray变量构建一个NSCountedSet,你可以这样做:
#import "Utilities.h"
#import <Foundation/Foundation.h>
#import <objc/objc-runtime.h>
@implementation Utilities
+ (NSCountedSet*)initCountedSetWithFirstArrayinObject:(id)someObject {
unsigned int c;
Ivar *ivar_arr = class_copyIvarList([someObject class], &c);
for (unsigned int i = 0; i < c; i++) {
if ([@"@\"NSMutableArray\"" isEqualToString:
[NSString stringWithCString:ivar_getTypeEncoding(ivar_arr[i]) encoding:NSUTF8StringEncoding]
]) {
return [[NSCountedSet alloc] initWithArray:object_getIvar(someObject, ivar_arr[i])];
}
}
return nil;
}
@end
当然这对现实世界的使用非常有限,因为它取决于你知道第一个阵列将是你感兴趣的阵列。
答案 3 :(得分:0)
我想我必须使用运行时类型编辑。(http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html)
协议的想法很好,但我必须在课堂上改变很多东西。(这是不可能的/允许的)对我来说。我的意图只是改变函数,以便我只有一个函数用于所有类。
我认为通过运行时类型编辑,我可以检查我有哪些类和属性(?)我是对的吗? 有人已经使用了运行时类型编辑吗?