【问题标题】:Varying Return Type Objective-C or c改变返回类型 Objective-C 或 c
【发布时间】:2014-06-03 02:16:38
【问题描述】:

我怎样才能有一个可以返回任何类型的方法/函数?例如,有时类型需要为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;
}

【问题讨论】:

  • 你为什么要问C? C 不支持idNSString *。如果你想要任何 C 类型,你可能想要返回 void *
  • 你从哪里得到这些值?如果您有 iVar,请考虑使用属性,然后如果您想动态访问它们,请使用 valueForKey:?

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


【解决方案1】:

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

为了简化,你甚至可以使用装箱字面量,例如:

return @(1.1f);

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • -[NSDictionary objectForKey:] 正是这样做的,它可以返回任何类型。我们不知道他想做什么,他可能有一个包装函数,例如在数组-(id)objectForKey:(id)key atIndex:(NSUInteger)index 中对象一个字典的值。
    • NSDictionary 只能保存对象,因此它返回id,这是一个未知类型的对象。 NSDictionary 不返回简单类型,例如int
    • 我知道,我的意思是你的陈述:“这真的没有意义,因为你无法将值分配给任何东西,因为你不知道类型”
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      您需要启用objective-c++:将.m-file 重命名为.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;
      }
      

      【讨论】:

        【解决方案5】:

        我发现在 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");
        

        【讨论】:

        • 当然你需要知道变量类型。如果你知道类型和变量名,为什么不能直接调用:self-&gt;_window
        猜你喜欢
        • 2015-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-17
        • 2013-05-29
        • 2011-10-14
        • 2013-03-02
        相关资源
        最近更新 更多