2012-01-08 30 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)

與協議的想法是好的,但我不得不改變類中的很多東西(這是不可能的/允許的)。我的意圖只是改變功能,以便我對所有類都只有一個功能。

我想用運行時類型編輯,我可以檢查我有什麼類和屬性(?)我是對嗎? 有人已經使用運行時類型編輯?