【问题标题】:convert std:vector to NSArray将 std:vector 转换为 NSArray
【发布时间】:2012-04-18 02:25:55
【问题描述】:

有没有一种好方法可以将vector<int32_t> 转换为NSNumberNSArray,或者循环并添加到NSMutableArray 几乎是唯一的方法?

【问题讨论】:

  • NSArray 不能包含原始类型 NSInteger 的元素。
  • @RichardJ.RossIII 实际上,它可以。我已经在我的回答中证明了这一点。

标签: c++ vector nsarray objective-c++


【解决方案1】:

如果您有一个对象向量,您可以执行以下操作:

NSArray *myArray = [NSArray arrayWithObjects:&vector[0] count:vector.size()];

但是,如果您的向量包含原始类型,例如NSIntegerintfloat 等,则您必须手动循环向量中的值并首先将它们转换为NSNumber

【讨论】:

  • 在使用这种方法时要非常小心向量对象的生命周期!
  • 这回答了我的问题。我确实有一个vector<int32_t>,所以不幸的是我必须遍历所有值。
  • 这对我不起作用。我得到“无法使用类型的右值初始化 'const __unsafe_unretained id *' 类型的参数......”
  • @Greg 第二种类型是什么?这是在 ARC 出现之前完成的,因此您可能需要转换指针。
  • 对不起,我太着急了,我误解了你的回答。你是对的——它有效。我认为用“Objective-C 对象的向量”之类的东西来澄清会更清楚。如果经过编辑,我愿意更改我的投票。
【解决方案2】:

是的,您可以使用以下方法从std::vector<NSInteger> 创建NSIntegers 中的NSArray

// thrown together as a quick demo. this could be improved.
NSArray * NSIntegerVectorToNSArrayOfNSIntegers(const std::vector<NSInteger>& vec) {

  struct MONCallback {
    static const void* retain(CFAllocatorRef allocator, const void* value) {
      /* nothing to do */
      return value;
    }

    static void release(CFAllocatorRef allocator, const void* value) {
      /* nothing to do */
    }

    static CFStringRef copyDescription(const void* value) {
      const NSInteger i(*(NSInteger*)&value);
      return CFStringCreateWithFormat(0, 0, CFSTR("MON - %d"), i);
    }

    static Boolean equal(const void* value1, const void* value2) {
      const NSInteger a(*(NSInteger*)&value1);
      const NSInteger b(*(NSInteger*)&value2);
      return a == b;
    }
  };

  const CFArrayCallBacks callbacks = {
    .version = 0,
    .retain = MONCallback::retain,
    .release = MONCallback::release,
    .copyDescription = MONCallback::copyDescription,
    .equal = MONCallback::equal
  };

  const void** p((const void**)&vec.front());
  NSArray * result((NSArray*)CFArrayCreate(0, p, vec.size(), &callbacks));
  return [result autorelease];  
}

void vec_demo() {
  static_assert(sizeof(NSInteger) == sizeof(NSInteger*), "you can only use pointer-sized values in a CFArray");

  std::vector<NSInteger> vec;
  for (NSInteger i(0); i < 117; ++i) {
    vec.push_back(i);
  }
  CFShow(NSIntegerVectorToNSArrayOfNSIntegers(vec));
}

但是,您需要非常谨慎地使用此集合。 Foundation 期望元素为NSObjects。如果您将它传递给需要NSObjects 数组的外部API,它可能会导致错误(阅读:objc_msgSend 中的EXC_BAD_ACCESS)。

通常,人们会将它们转换为NSNumber。只有当另一个 API 需要它(Apple 有一些)时,我才会在我的程序中使用 NSArrayNSIntegers —— 它们只是不能很好地结合在一起。

【讨论】:

  • 我的意思实际上是NSNumber,但是 +1 以获得一个有趣的答案!
猜你喜欢
  • 2010-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多