String manipulation without memory leaks?

大憨熊 提交于 2020-01-01 03:26:07

问题


I'd like to do a series of string substitutions to removed xml-escaped chars such as '&'.

1) Is there an existing UIKit function that can do this?

2) If not, what's the best way to do it without leaking memory? Here's the idea:

-(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;
}

But doesn't that leak memory with each assignment? Or does stringByReplacingOccurrencesOfString return autoreleased strings? How do we confirm that stringByReplacingOccurrencesOfString strings are autoreleased? Or should we wrap them with [... autorelease]?

Even if they are autoreleased, it's preferable to avoid autorelease on the iPhone. (See here). So then we would do:

-(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
}     

But that's pretty ugly code. What's the best way to write this code to do multiple substitutions? How would you do it?


回答1:


Any cocoa method which returns a new object via a method that does not start with init or contain the word copy will return an autoreleased object. So the above code should have noleaks.

Although it may be easier to use a NSMutableString here. Then you just modify the string in place rather than creating a pile of autoreleased string objects, which should make things cleaner.

Also, how about a dictionary of mappings that you iterate through, finding the key and replacing with the value of each item. Maybe even save this as a plist in your app for easy tweaking later.




回答2:


As Squeegy said, all of the above methods you reference return autoreleased objects. The second code example will crash because you are overreleasing the string objects.

Squeegy pointed one way of handling this, using NSMutableStrings. I'd recommend that approach. For example, the following rewrite of your method:

-(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];
}

only returns an autoreleased NSMutableString at the end.

Even better would be if you passed in a pointer to an NSMutableString pointer (NSMutableString **). That way, you could modify the string that you'd created outside of your method without creating a new temporary string. If this seems strange, take a look at methods that deal with NSError instances as an example.

EDIT: Ignore my statement about needing a double pointer in the previous paragraph. As erikprice points out, you just need to pass in an NSMutableString pointer. The double pointer is only needed if you create a new NSMutableString instance in your method to replace the one being passed in, which is not the case here.




回答3:


I recommend you read the Cocoa memory management rules.



来源:https://stackoverflow.com/questions/531550/string-manipulation-without-memory-leaks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!