【发布时间】:2011-12-06 23:58:06
【问题描述】:
IOS Api 中是否有一个类似于 substringFromIndex 的函数,除了使用更少的内存(我正在使用非常非常大的字符串)。如果我必须实现该功能,我将如何去做?
提前致谢
【问题讨论】:
-
有没有办法制作这样的功能,我该怎么做?
标签: iphone string memory substring
IOS Api 中是否有一个类似于 substringFromIndex 的函数,除了使用更少的内存(我正在使用非常非常大的字符串)。如果我必须实现该功能,我将如何去做?
提前致谢
【问题讨论】:
标签: iphone string memory substring
是的,但它有点迂回,有潜在危险
这就是你要做的:
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];
这是在做什么:
NSData 开头而不是NSString,那么您可以更加确信不会复制任何内容。NSData获取实际的字节缓冲区
NSString,但告诉它不复制字节,并不在NSString被释放时释放缓冲区那么,为什么这很危险?基本上,如果字节缓冲区从 NSStrings 下方消失,Bad Things™ 可能会发生(可能会崩溃)。
但是,如果您对此很聪明,这将允许您在不复制底层字节的情况下创建子字符串。
邪念:
您可以将veryLargeString 设为substring 上的保留关联对象(即,基本上将substring 设为veryLargeString 的所有者)。这将确保veryLargeString 的寿命至少与substring 一样长。你会这样做:
static char ParentStringKey;
objc_setAssociatedObject(substring, &ParentStringKey, veryLargeString, OBJC_ASSOCIATION_RETAIN);
当substring 被释放时,它也会自动释放它在veryLargeString 上的保留。
【讨论】:
NSString 的cStringUsingEncoding: 方法得到char *,然后使用<string.h> 中的C 库函数或简单的指针算法来处理它。可以节省几个字节的内存,因为它不使用临时的NSData 对象。您仍然可以将 initWithBytesNoCopy: 方法用于最终的 NSString 对象。
NSData 的大小只会多出几个字节;可能不值得担心。另外,我认为管理NSData 与char* 的生命周期会更容易(出于同样的原因,保留/释放优于malloc/free)。