【问题标题】:String manipulation without memory leaks?没有内存泄漏的字符串操作?
【发布时间】:2009-02-10 09:01:17
【问题描述】:

我想对删除的 xml 转义字符(例如 '&')进行一系列字符串替换。

1) 是否有现有的 UIKit 函数可以做到这一点?

2) 如果不是,那么在不泄漏内存的情况下最好的方法是什么?想法是这样的:

-(NSString*) unescape:(NSString*)string
{
    string = [string stringByReplacingOccurrencesOfString:@"'" withString:@"'"];
    string = [string stringByReplacingOccurrencesOfString:@"&" withString:@"&"];
    string = [string stringByReplacingOccurrencesOfString:@""" withString:@"\""];
    string = [string stringByReplacingOccurrencesOfString:@">" withString:@">"];
    string = [string stringByReplacingOccurrencesOfString:@"&lt;" withString:@"<"];
    return string;
}

但不是每次分配都会泄漏内存吗?还是 stringByReplacingOccurrencesOfString 返回自动释放的字符串?我们如何确认 stringByReplacingOccurrencesOfString 字符串是自动释放的?还是应该用[... autorelease] 包装它们?

即使它们是自动发布的,最好避免在 iPhone 上自动发布。 (见here)。那么我们会这样做:

-(NSString*) unescape:(NSString*)string
{
    NSString* string2 = [string stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    // don't release 'string' because we didn't allocate or retain it
    NSString* string3 = [string2 stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    [string2 release];
    NSString* string4 = [string3 stringByReplacingOccurrencesOfString:@"&apos;" withString:@"'"];
    [string3 release];
    //...and so on
}     

但那是相当难看的代码。编写此代码进行多次替换的最佳方法是什么?你会怎么做?

【问题讨论】:

    标签: cocoa-touch memory-management


    【解决方案1】:

    任何通过不以init 开头或不包含单词copy 的方法返回新对象的可可方法都将返回一个自动释放的对象。所以上面的代码应该有noleaks。

    虽然在这里使用 NSMutableString 可能更容易。然后你只需在适当的位置修改字符串,而不是创建一堆自动释放的字符串对象,这应该会让事情变得更干净。

    另外,您如何遍历映射字典,找到key 并替换为每个项目的value。甚至可以将其保存为应用中的 plist,以便以后轻松调整。

    【讨论】:

      【解决方案2】:

      正如 Squeegy 所说,您引用的所有上述方法都返回自动释放的对象。第二个代码示例将崩溃,因为您过度释放字符串对象。

      Squeegy 指出了一种处理方法,即使用 NSMutableStrings。我会推荐这种方法。例如,以下重写您的方法:

      -(NSString*) unescape:(NSString*)string
      {
          NSMutableString *unescapedString = [[NSMutableString alloc] initWithString:string];
          [unescapedString replaceOccurrencesOfString:@"&apos;" withString:@"'" options:0 range:NSMakeRange(0, [unescapedString length])];
          [unescapedString replaceOccurrencesOfString:@"&amp;" withString:@"&" options:0 range:NSMakeRange(0, [unescapedString length])];
          [unescapedString replaceOccurrencesOfString:@"&quot;" withString:@"\"" options:0 range:NSMakeRange(0, [unescapedString length])];
          [unescapedString replaceOccurrencesOfString:@"&gt;" withString:@">" options:0 range:NSMakeRange(0, [unescapedString length])];
          [unescapedString replaceOccurrencesOfString:@"&lt;" withString:@"<" options:0 range:NSMakeRange(0, [unescapedString length])];
          return [unescapedString autorelease];
      }
      

      最后只返回一个自动释放的 NSMutableString。

      如果你传入一个指向 NSMutableString 指针 (NSMutableString **) 的指针会更好。这样,您可以修改在方法之外创建的字符串,而无需创建新的临时字符串。如果这看起来很奇怪,请以处理 NSError 实例的方法为例。

      编辑:忽略我在上一段中关于需要双指针的声明。正如 erikprice 所指出的,您只需要传入一个 NSMutableString 指针。仅当您在方法中创建一个新的 NSMutableString 实例来替换传入的实例时才需要双指针,这里不是这种情况。

      【讨论】:

      • 为什么它需要一个指向 NSMutableString 指针的指针?我认为使用 NSMutableString 的“要点”(呵呵)是它是可变的,所以你不能只传递一个简单的 NSMutableString 指针,并让方法体改变它指向的 NSMutableString 吗?
      • 你是对的。出于某种原因,我正在考虑在方法中创建一个全新的实例,这就是 NSError 发生的情况。我会修正文本。
      【解决方案3】:

      我建议你阅读Cocoa memory management rules

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-21
        • 2014-04-30
        • 1970-01-01
        • 2011-08-29
        • 2013-04-03
        • 2013-09-05
        • 2011-06-12
        • 2018-12-17
        相关资源
        最近更新 更多