3

连接大字符串时,我得到一个 EXEC_BAD_ACCESS。

我从提要中阅读并创建我的 webview 我建立了我的字符串,如:

NSString *pageData = @"<h1>header</h1>";

pageData = [pageData stringByAppendingFormat@"<p>"];
pageData = [pageData stringByAppendingFormat@"self.bodyText"];
pageData = [pageData stringByAppendingFormat@"</p>"];
etc

我遇到的问题是 self.bodytext 是 21,089 个带有空格的字符,当我计算单词时。有没有更好的方法来做到这一点?

谢谢

4

4 回答 4

6

你肯定会想用NSMutableString 来做这样的事情:

NSMutableString * pageData = [NSMutableString stringWithCapacity:0];

[pageData appendFormat:@"<h1>header</h1>"];
[pageData appendFormat:@"<p>"];
...

NSMutableString是为这种顺序连接而设计的,其中基本的 NSString 类实际上并不意味着以这种方式使用。您的原始代码实际上会在您每次调用时分配一个新的 NSString stringByAppendFormat:,然后继续将您已经附加的数千个字符复制到其中。这很容易导致内存不足错误,因为随着您添加越来越多的调用,临时字符串的大小会呈指数增长。

调用时使用 NSMutableString 不会重新复制所有字符串数据appendFormat:,因为可变字符串维护一个内部缓冲区并简单地将新字符串附加到它的末尾。根据字符串的大小,您可能希望提前保留一大块内存(为...WithCapacity:参数使用有意义的数字)。但是除非你真的遇到性能问题,否则没有必要走那条路。

于 2010-05-04T16:10:37.160 回答
2

您的示例代码存在一些问题:

  1. 您应该使用 NSMutableString 通过附加多个部分来构建输出字符串。NSString 是一个不可变的类,这意味着每次调用时stringByAppendingFormat:都会产生创建额外的新 NSString 对象的开销,该对象需要由自动释放池收集和释放。

    NSMutableString * pageData = [NSMutableString stringWithCapacity:0];

  2. 您应该使用appendString:on yourNSMutableString来追加内容,而不是stringByAppendingFormat:or appendFormat:。格式方法旨在基于包含特殊字段作为占位符的格式说明符创建新字符串。有关详细信息,请参阅格式化字符串对象。当您只使用stringByAppendingFormat:像代码一样的文字字符串时,您会产生为不存在的占位符解析字符串的开销,更重要的是,如果字符串恰好有一个占位符(或看起来像一个) 在其中,您最终会EXEC_BAD_ACCESS遇到崩溃。当您的 bodyText 被附加时,很可能会发生这种情况。因此,如果您只是想附加一个 '

    ' 对你NSMutableString做这样的事情:

    [pageData appendString:@"<p>"];

  3. 如果要将self.bodyText属性的内容附加到字符串中,则不应将属性名称放在字符串文字中(即@“self.bodyText”是文字字符串“self.bodyText”,而不是内容属性。尝试:

    [pageData appendString:self.bodyText];

例如,您实际上可以使用格式规范组合示例代码的所有三行:

pageData = [pageData stringByAppendingFormat:@"<p>%@</p>", self.bodyText];

在格式规范%@中是一个占位符,表示将发送 descriptiondescriptionWithLocale:消息的结果插入对象。对于 anNSString这只是字符串的内容。

于 2010-05-04T20:07:24.130 回答
1

在处理任意字符串时使用 appendString: 而不是 appendFormat:。

pageData = [pageData stringByAppendingString:@"<p>"];
pageData = [pageData stringByAppendingString:@"self.bodyText"];
pageData = [pageData stringByAppendingString:@"</p>"];

或者不要使用任意字符串作为格式:

pageData = [pageData stringByAppendingFormat:@"<p>%@</p>" , @"self.bodyText"];

如果您要分段构建字符串,请使用 NSMutableString 而不是多个 stringBy 调用。

请记住 % 是格式化字符串和 url 转义的特殊字符,因此如果 bodyText 包含 url 很容易导致崩溃。

于 2010-05-04T18:51:34.223 回答
1

我怀疑字符串的长度真的是个问题。一个 50,000 个字符的字符串只有大约 100 KB。但是您要非常小心使用格式字符串。如果你的字符串包含一些看起来像格式说明符的东西,最好有一个相应的参数,否则如果你很幸运,你会得到垃圾,如果你不幸运,则会崩溃。我怀疑这是错误,因为您的描述没有其他明显的问题。小心你放在那里的内容,并避免将动态文本放入格式字符串中——只需将 a%@放入格式字符串中并将动态文本作为参数传递即可。

于 2010-05-04T18:43:46.930 回答