1

我为我的一个项目写了一个小 NSString 类别,更好地实现了百分比转义:@im

plementation NSString (Escaping)
- (NSString *)stringByAddingSafePercentEscapesUsingEncoding:(NSStringEncoding)encoding
{
    NSRange wholeString = NSMakeRange(0, [self length]);
    NSMutableString *escaping = [NSMutableString stringWithString:[self stringByAddingPercentEscapesUsingEncoding:encoding]];
    [escaping replaceOccurrencesOfString:@"$" withString:@"%24" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"&" withString:@"%26" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"+" withString:@"%2B" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"," withString:@"%2C" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@";" withString:@"%3B" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"-" withString:@"%2D" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"=" withString:@"%3D" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"?" withString:@"%3F" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"@" withString:@"%40" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@" " withString:@"%20" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"\t" withString:@"%09" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"#" withString:@"%23" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"<" withString:@"%3C" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@">" withString:@"%3E" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"\"" withString:@"%22" options:NSCaseInsensitiveSearch range:wholeString];
    [escaping replaceOccurrencesOfString:@"\n" withString:@"%0A" options:NSCaseInsensitiveSearch range:wholeString];
    NSString *escaped = [NSString stringWithString:escaping];

    return escaped;
}
@end

在这个项目中,它工作得很好,我喜欢使用它。但是当我将它移植到另一个项目时,该代码通过 EXC_BAD_ACCESS。我可以在该代码中做得更好吗?

4

2 回答 2

1

我只是偶然发现了我的问题:

由于字符串在将一个字符替换为三个字符时会有效地改变其长度,因此字符串长度会随着每次替换而改变。因此,该类别的正确实现是:

@implementation NSString (Escaping)
- (NSString *)stringByAddingSafePercentEscapesUsingEncoding:(NSStringEncoding)encoding
{
    NSRange wholeString = NSMakeRange(0, [self length]);
    NSMutableString *escaping = [NSMutableString stringWithString:[self stringByAddingPercentEscapesUsingEncoding:encoding]];
    [escaping replaceOccurrencesOfString:@"$" withString:@"%24" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"&" withString:@"%26" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"+" withString:@"%2B" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"," withString:@"%2C" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@";" withString:@"%3B" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"-" withString:@"%2D" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"=" withString:@"%3D" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"?" withString:@"%3F" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"@" withString:@"%40" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@" " withString:@"%20" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"\t" withString:@"%09" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"#" withString:@"%23" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"<" withString:@"%3C" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@">" withString:@"%3E" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"\"" withString:@"%22" options:NSCaseInsensitiveSearch range:wholeString];
    wholeString = NSMakeRange(0, [escaping length]);
    [escaping replaceOccurrencesOfString:@"\n" withString:@"%0A" options:NSCaseInsensitiveSearch range:wholeString];
    NSString *escaped = [NSString stringWithString:escaping];

    return escaped;
}
@end
于 2012-08-07T11:40:04.693 回答
0

我认为应该是:

NSRange wholeString = NSMakeRange(0, [self length]-1);

如果您的 replaceOccurrencesOfString:withString:options:range: 方法遍历字符串中的最后一个字符,您将获得“错误访问”。

或者,您可以将类似的方法用于您的替换方法,这些方法已经在整个长度上进行迭代。但是,我不确定默认搜索选项是什么:

escaping = [escaping stringByReplacingOccurencesOfString:@"$" withString:@"%24"];
于 2012-07-31T21:49:17.713 回答