【问题标题】:Iphone: Replace functions using reflectionIphone:使用反射替换函数
【发布时间】:2012-01-08 15:52:34
【问题描述】:

我有一个要重写的小函数,因此该函数对每个类都有效。 目前我有 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?

【问题讨论】:

  • 从技术上讲,在 objc 中,它不是反射,而是运行时类型编辑。

标签: iphone reflection swizzling


【解决方案1】:

你可以像这样使用反射:

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

【讨论】:

  • 嗨!谢谢你。我认为这可能是做到这一点的方法。我会试试看,看看我还能用协议做什么。
【解决方案2】:

编辑:清除了我对此的所有答案:

我认为不可能检查一个类是否具有指定类型的成员变量。你只能检查一个类是否有指定的方法。

因此,在这种情况下,最好将所有 NSMutableArray 列表设为同名,然后为该列表创建一个声明的属性,然后在您的 ...GetReferencedNested 方法中执行 respondsToSelector。

因此,例如,在您的所有班级中创建此属性:

@property (nonatomic, retain) NSMutableArray * list;

然后在 ..MissionGetReferencedNested 方法中:

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

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

【讨论】:

  • 我想,这不是我想要的。我的目标不是写这个modelObject.MissionSectionList。相反,我想要,如果有一个 NSMutableArray,取这个数组并做 modelObject.Array... 我想做这个,因为我有很多这样的类,我不想每次都做区分。
  • 我想我会先用协议尝试这个想法。我认为我不允许更改名称。但如果协议不起作用,我会试试你的想法。谢谢:)
【解决方案3】:

在风格方面,我也会遵循 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

当然,这在现实世界中的用途非常有限,因为这取决于您是否知道第一个数组将是您感兴趣的数组。

【讨论】:

    【解决方案4】:

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

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

    我认为通过运行时类型编辑,我可以检查我拥有哪些类和属性(?)对吗? 有人已经使用运行时类型编辑了吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多