变化的返回类型Objective-C或c

时间:2014-04-18 14:40:23

标签: objective-c c function methods return-type

我怎样才能有一个可以返回任何类型的方法/函数?例如,有时类型需要为float,有时需要为NSString*,因此id无效,因为float不是id }。如果它更容易,我不反对在c或c ++函数中这样做。

我需要动态返回类型的原因是因为我使用objc / runtime来获取Ivar。

我希望some_type可以做任何事情:

- (some_type)getIvarWithName:(const char *)name in:(id)obj
{
Ivar ivar(class_getInstanceVariable(object_getClass(obj),name));
return (some_type)ivar;
}

5 个答案:

答案 0 :(得分:3)

返回float包裹的NSNumber,然后您可以使用id返回类型。

为了简化它,你甚至可以使用拳击文字,例如:

return @(1.1f);

答案 1 :(得分:1)

首先要考虑的是为什么你需要一个可以返回任何类型的函数。它实际上没有意义,因为您无法将值分配给任何东西,因为您不知道类型。当然,严格处理Obj-C对象时情况不同,因为该语言使用id关键字的未知对象。未知的物体就像混合Honeycrisp苹果和Macintosh苹果(没有双关语),你想要做的就像混合Honeycrisp苹果和飞机!但是,如果您希望根据参数返回某个类型(例如,为int参数返回int,为float参数返回float),那么您可以重载功能。否则,只有我知道返回绝对任何东西的方式都是void指针(void *)。这将指向一大块可以真正成为任何东西的数据。但回到原来的问题。它代表什么,它有多长?祝你好运!

更新:正如其他答案所提到的,您可以将简单数据类型(intfloat等)包装在NSNumbers或NSValues等对象中,这些对象适合您的情况。但是当扩展到具有复杂类型(如结构)的更一般场景时,这些通常不能包含在内置类中。你需要使用Obj-C创建自己的类。

答案 2 :(得分:0)

Obj-C中没有这种多态性。 如果您事先知道将返回什么,那么您当然可以使用方法。 当您使用NSNumber作为浮点值时,重新启动ID将起作用。 您甚至可以引入一个带有数字或字符串的响应对象,并提供(bool) isNumber(bool) isString方法以供以后处理。

但是你真的要做什么?您在哪种情况下使用它,以及您真正想要实现的目标。对我来说,听起来好像可能有更好的解决方案。

答案 3 :(得分:0)

当然,这是一个奇怪的解决方案,但你有一个奇怪的问题。

您需要启用objective-c ++:将.m文件重命名为.mm 然后你的代码看起来像这样:

void weird_function(int a)
{
   switch (a)
   {
       case 0: throw @"Hello";
       default: throw a;
   }
}

void some_code(int a)
{
    try
    {
        weird_function(a);
    }
    catch (int a)
    {
         NSLog(@"Catch int: %d", a);
    }
    catch (NSString* str)
    {
         NSLog(@"Catch string: %@", str);
    }
}

你的方法可以实现类似的东西:

union ValueHolder
{
    void* voidPtrValue;
    int intValue;
    float floatValue;
    NSString* nssstringValue;
};

- (void)getIvarWithName:(const char *)name in:(id)obj
{
    ValueHolder vh;
    Ivar ivar = object_getInstanceVariable(obj,name, &vh.voidPtrValue));
    if (NULL == ivar)
        return;
    const char* encoding = ivar_getTypeEncoding(ivar);
    if (0 == strcmp(encoding, @encode(int)))
        throw vh.intValue;
    if (0 == strcmp(encoding, @encode(float)))
        throw vh.floatValue;
    if (0 == strcmp(encoding, "@\"NSString\""))
        throw vh.nsstringValue;
}

答案 4 :(得分:0)

我发现在c ++中使用模板可以使用自定义类型 以下代码最适合我的情况:

template <typename _type>
static inline _type & hookVar(id self, NSString*name)
{
    Ivar ivar(class_getInstanceVariable(object_getClass(self),[name UTF8String]));
    #if __has_feature(objc_arc)
    void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>((__bridge void *)self) + ivar_getOffset(ivar));
    #else
    void *pointer(ivar == NULL ? NULL : reinterpret_cast<char *>(self) + ivar_getOffset(ivar));
    #endif
    return *reinterpret_cast<_type *>(pointer);
}

要调用该函数,我只需使用:

NSWindow *win = hookVar<NSWindow*>(self, @"_window");