Я подозреваю, что имя на самом деле не течет, она просто не будет выпущен, когда вы думаете. Согласно ARC, я считаю, что scanUpToString:intoString:
будет определяться аналогично методам с использованием NSError
. Другими словами, требуется NSString * __autoreleasing *
. Поэтому любое значение, переданное ему, фактически автореализуется и не будет выпущено до тех пор, пока текущий пул авторасчетов не будет исчерпан. Предполагая, что у вас нет других, усеиваемых вокруг, это произойдет, когда цикл цикла снова пройдет. Если использование памяти является проблемой для вас, то можно было бы поместить явный autorelease бассейн вокруг петли, поэтому объекты уходят сразу:
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
как автореализацию. Вам также не нужно init
его, как сказал rckoeness, потому что 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
не просачиваются, потому что этот словарь (или что-то, что позже читает эти ключи из словаря) просачивается.
Вы видели эту утечку через инструмент «Утечки инструментов»? Если это так, спуститесь на нижнюю панель и измените опцию отображения с «Утечки» на «Циклы и корни», чтобы отобразить новые инструменты обнаружения цикла удержания. Это может показать, что цикл утечки отвечает за эту утечку в ARC. Кроме того, вы можете использовать функцию кучи в инструменте Allocations, чтобы определить, какие объекты точно просачиваются для каждого прохода над вышеуказанным кодом. –
Переменная имени протекает, каждый передает вышеприведенный код. Любое решение, как это решить? – Thys