我正在ARC自动转换项目中工作。
我有一个存储在NSString *_documentDataString
。
现在我有了这个循环:
- (void)scanParts
{
NSString *boundary = [boundaryPrefix stringByAppendingString:_header.boundary];
NSMutableArray *parts = [NSMutableArray array];
NSInteger currentLocation = [_documentDataString rangeOfString:boundary].location;
BOOL reachedTheEnd = NO;
while(!reachedTheEnd)
{
NSInteger nextBoundaryLocation = [[_documentDataString substringFromIndex:currentLocation + 1]
rangeOfString:boundary].location;
if(nextBoundaryLocation == NSNotFound)
{
reachedTheEnd = YES;
}
else
{
nextBoundaryLocation += currentLocation + 1;
//[parts addObject:[_documentDataString substringWithRange:
// NSMakeRange(currentLocation, nextBoundaryLocation - currentLocation)]];
currentLocation = nextBoundaryLocation;
}
}
}
但是,我开始收到这些错误:
malloc: *** mmap(size=6496256) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
出了什么问题?
我在运行此循环时甚至开始出现此错误:
while(true)
{
NSInteger nextBoundaryLocation = [[_documentDataString substringFromIndex:currentLocation + 1]
rangeOfString:boundary].location;
}
答案 0 :(得分:5)
中的
substringFromIndex:
NSInteger nextBoundaryLocation = [[_documentDataString substringFromIndex:currentLocation + 1]
rangeOfString:boundary].location;
创建一个(临时的,自动释放的)子字符串,该子字符串仅在当前时被释放 autoreleasepool被销毁(例如,当程序控制返回主事件循环时)。
您可以用
替换该代码NSInteger nextBoundaryLocation = [_documentDataString rangeOfString:boundary
options:0
range:NSMakeRange(currentLocation + 1, [_documentDataString length] - (currentLocation + 1))].location;
(希望)避免创建临时字符串。请注意,nextBoundaryLocation
然后相对于字符串的开头,所以
nextBoundaryLocation += currentLocation + 1;
不再需要了。
或者,你可以简单地用
替换完整的循环NSArray *parts = [_documentDataString componentsSeparatedByString:boundary];
答案 1 :(得分:0)
看起来文档太大而无法像通常使用(合理)常规大小的字符串那样操作它,原因是在字符串对象的内存分配过程中出现错误。
对于您的特定情况,您可能需要使用NSInputStream
,基本上可以逐字节而不是一次性读取文件的数据。
查看以下问题Objective-C: Reading a file line by line
Apple在InputStreams上提供的文档 https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSInputStream_Class/Reference/Reference.html
简而言之,根据文档,您需要执行以下操作:
首先打开文件
- (void)setUpStreamForFile:(NSString *)path {
// iStream is NSInputStream instance variable
iStream = [[NSInputStream alloc] initWithFileAtPath:path];
[iStream setDelegate:self];
[iStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[iStream open];
}
编写代码以处理流中有更多可用字节时的操作(虽然它不是文件的末尾)
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
if(!_data) {
_data = [[NSMutableData data] retain];
}
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)stream read:buf maxLength:1024];
if(len) {
[_data appendBytes:(const void *)buf length:len];
// bytesRead is an instance variable of type NSNumber.
[bytesRead setIntValue:[bytesRead intValue]+len];
} else {
NSLog(@"no buffer!");
}
break;
}
答案 2 :(得分:0)
你也可以NSInputStream
,它会减少你的内存使用量。
iOS设备上的14MB大量退出。