我怀疑这个名字实际上并没有泄漏,当你认为它是时它根本没有被释放。在 ARC 下,我相信它的scanUpToString:intoString:
定义类似于使用NSError
. 换句话说,它需要NSString * __autoreleasing *
. 因此,传递给它的任何值实际上都是自动释放的,并且在当前自动释放池耗尽之前不会被释放。假设您周围没有任何其他人,那将是运行循环再次运行的时候。如果该内存使用对您来说是个问题,则可以在循环周围放置一个显式的自动释放池,以便对象立即消失:
NSScanner *scanner = [[NSScanner alloc] initWithString:query];
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]];
@autoreleasepool
{
NSString *parameterString = [NSString new];
while ([scanner scanUpToString:ampersand intoString:¶meterString])
{
NSScanner *parameterScanner = [[NSScanner alloc] initWithString:parameterString];
NSString *name = [NSString new];
[parameterScanner scanUpToString:isEqual intoString:&name];
NSString *value = [parameterString substringFromIndex:([name length] + 1)];
[parameters setObject:value forKey:name];
}
}
但这可能是不必要的,并且运行循环无论如何都会清除对象。
也就是说,仍然存在一个小问题,这意味着编译器正在为您创建一个额外的临时变量。您的name
变量是隐式__strong
的,因此编译器会插入一个临时变量,__autoreleasing
并为您复制周围的值。NSString
您可以通过明确声明为自动释放来避免这种情况。正如 rckoeness 所说,你也不需要init
它,因为它scanUpToString:intoString:
正在为你做这件事(这就是为什么它必须__autoreleasing
放在首位)。(有关更多信息,请参阅http://developer.apple.com/library/mac/ipad/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html)。
所以,总的来说,我认为你实际上希望你的代码看起来像这样:
NSScanner *scanner = [[NSScanner alloc] initWithString:query];
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"&?"]];
NSString __autoreleasing *parameterString = nil;
while ([scanner scanUpToString:ampersand intoString:¶meterString])
{
NSScanner *parameterScanner = [[NSScanner alloc] initWithString:parameterString];
NSString __autoreleasing *name = nil;
[parameterScanner scanUpToString:isEqual intoString:&name];
NSString *value = [parameterString substringFromIndex:([name length] + 1)];
[parameters setObject:value forKey:name];
}
希望有帮助!
我有另一个想法,也许name
只是一个红鲱鱼。泄漏将显示分配发生的位置,但name
在此循环之外继续存在,当它添加到parameters
. 我假设它是一个NSMutableDictionary
或类似的,基于选择器。如果我是你,我会确认name
实例没有被泄露,因为该字典(或后来从字典中读取这些键的东西)正在泄露。