2012-01-08 31 views
2

我有一个小函数,我想要重写,以便该函数对每个类都有效。 目前我有10个功能相同的功能,但每个功能都适用于另一个功能。 我知道,我必须用思考去做,但我不太确定如何去做。 我已经阅读此链接: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.htmlIphone:使用反射替换函数

我谈论的职能是:

-(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?

+2

从技术上讲,在objc中,它没有反射,它是运行时类型编辑。 – 2012-01-08 16:02:45

回答

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...方法做任何更改。

有关协议的更多信息:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html

+0

嗨!谢谢。我认为这可能是做到这一点的方法。我会试着看看我能用协议做些什么。 – DeFlo 2012-01-08 18:26:09

0

编辑:清除所有我的回答是:

我认为这是不可能的检查,如果一个类有指定类型的成员变量。你只能检查一个类是否有指定的方法。因此,在这种情况下,如果您将所有NSMutableArray列表设为相同的名称,然后为此列表创建一个声明的属性,然后在您的... GetReferencedNested方法中执行respondsToSelector,那么这将是最好的。

因此,例如,在所有类的创建这个属性:

@property (nonatomic, retain) NSMutableArray * list; 

然后在..MissionGetReferencedNested方法:

if ([modelObject respondsToSelector:@selector(list)]) 
    ... 

纠正我,如果我错了.. 。

+0

我认为,这不是我正在寻找的。我的目标不是写这个modelObject.MissionSectionList。相反,我想,如果有一个NSMutableArray,采取这个数组,并做modelObject.Array ...我想这样做,因为我有很多这样的类,我不想每次都做一个案例的区别。 – DeFlo 2012-01-08 16:40:45

+0

我想我会先用这些协议尝试一下这个想法。我想我不允许改名字。但如果协议不起作用,我会尝试你的想法。谢谢:) – DeFlo 2012-01-08 18:28:30

+0

这是错误的。你可以检查ivars。 – k1th 2012-01-08 18:34:39

0

在款式方面我也想跟着ABHI的建议。

但如果你真的要检查的是你被卡住和一类,例如建立一个NSCountedSet与第一NSMutableArray的变量,你可以找到,你可以做这样的:

#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 

当然这个真实世界的使用非常有限,因为它取决于你知道第一个数组将会是你感兴趣的数组。

0

我认为我必须去使用运行时类型编辑(http:// developer。 apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html)

与协议的想法是好的,但我不得不改变类中的很多东西(这是不可能的/允许的)。我的意图只是改变功能,以便我对所有类都只有一个功能。

我想用运行时类型编辑,我可以检查我有什么类和属性(?)我是对吗? 有人已经使用运行时类型编辑?