【问题标题】:Is there a function like substringFromIndex that uses less memory?有没有像 substringFromIndex 这样使用更少内存的函数?
【发布时间】:2011-12-06 23:58:06
【问题描述】:

IOS Api 中是否有一个类似于 substringFromIndex 的函数,除了使用更少的内存(我正在使用非常非常大的字符串)。如果我必须实现该功能,我将如何去做?

提前致谢

【问题讨论】:

  • 有没有办法制作这样的功能,我该怎么做?

标签: iphone string memory substring


【解决方案1】:

是的,但它有点迂回,有潜在危险

这就是你要做的:

NSString *veryLargeString = ...;
NSUInteger startingIndex = ...;
NSData *veryLargeStringData = [veryLargeString dataUsingEncoding:NSUTF8StringEncoding];

const void *bytes = [veryLargeStringData bytes];
const void *subBytes = bytes + startingIndex;
NSUInteger subLength = [veryLargeStringData length] - startingIndex;

NSString *substring = [[NSString alloc] initWithBytesNoCopy:subBytes length:subLength encoding:NSUTF8StringEncoding freeWhenDone:NO];

这是在做什么:

  1. 它将非常大的字符串作为一系列字节获取;我很漂亮确定这实际上并没有复制字节,但一定要使用 Instruments 来验证。如果您可以将这个超长字符串作为NSData 开头而不是NSString,那么您可以更加确信不会复制任何内容。
  2. NSData获取实际的字节缓冲区
  3. 使用一些指针算法索引字节缓冲区
  4. 计算出剩余多少缓冲区
  5. 用字节缓冲区创建一个新的NSString,但告诉它复制字节,并NSString被释放时释放缓冲区

那么,为什么这很危险?基本上,如果字节缓冲区从 NSStrings 下方消失,Bad Things™ 可能会发生(可能会崩溃)。

但是,如果您对此很聪明,这将允许您在不复制底层字节的情况下创建子字符串。


邪念

您可以将veryLargeString 设为substring 上的保留关联对象(即,基本上将substring 设为veryLargeString 的所有者)。这将确保veryLargeString 的寿命至少与substring 一样长。你会这样做:

static char ParentStringKey;

objc_setAssociatedObject(substring, &ParentStringKey, veryLargeString, OBJC_ASSOCIATION_RETAIN);

substring 被释放时,它也会自动释放它在veryLargeString 上的保留。

【讨论】:

  • 非常感谢,我马上试试。解释也很好
  • 您也可以使用NSStringcStringUsingEncoding: 方法得到char *,然后使用<string.h> 中的C 库函数或简单的指针算法来处理它。可以节省几个字节的内存,因为它不使用临时的NSData 对象。您仍然可以将 initWithBytesNoCopy: 方法用于最终的 NSString 对象。
  • +1 表示 Bad Things(TM) ......好吧,这是一个非常好的解决方案。
  • @Mac 确保您可以这样做直接进入字节缓冲区。但是NSData 的大小只会多出几个字节;可能不值得担心。另外,我认为管理NSDatachar* 的生命周期会更容易(出于同样的原因,保留/释放优于malloc/free)。
  • 更新了答案,现在的狡猾度增加了 42%!
猜你喜欢
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多