2

私は書き直したい小さな関数を持っているので、その関数はすべてのクラスで有効です。現時点では、すべて同じように機能する同じ関数が 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 は、どちらも 2 つの異なるクラスの NSMutableArray です。クラスが NSMutableArray で構成されているかどうかを確認することはできますか? はいの場合は .... modelObject.MyMutableArray を呼び出す必要がありますか?

4

4 に答える 4

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

于 2012-01-08T17:50:14.170 に答える
0

ランタイムタイプの編集を行う必要があると思います。 (http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html)

プロトコルのアイデアは良かったのですが、クラスで多くのことを変更する必要があります (これは不可能/許可されていません)。私の意図は、関数を変更して、すべてのクラスに対して関数が 1 つだけになるようにすることだけでした。

実行時の型編集で、自分が持っているクラスと属性を確認できると思います (?) そうですか? 誰かがすでに実行時の型編集に取り組んでいますか?

于 2012-01-09T08:44:11.853 に答える
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

もちろん、最初の配列が関心のあるものになることを知っているかどうかに依存するため、これは現実世界での使用が非常に限られています。

于 2012-01-08T18:33:28.110 に答える
0

編集:これに対する私の答えをすべてクリアしました:

クラスに指定された型のメンバー変数があるかどうかを確認することはできないと思います。クラスに指定されたメソッドがあるかどうかのみを確認できます。

したがって、この場合、すべての NSMutableArray リストを同じ名前にして、このリストの宣言済みプロパティを作成し、...GetReferencedNested メソッドで RespondsToSelector を実行するのが最善です。

したがって、たとえば、すべてのクラスでこのプロパティを作成します。

@property (nonatomic, retain) NSMutableArray * list;

そして、..MissionGetReferencedNested メソッドで:

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

間違っていたら訂正...

于 2012-01-08T16:25:32.450 に答える