tjg*_*184 8 objective-c objective-c-blocks
我有以下代码.我偶尔会得到一个SIGSEGV.我有一种感觉,我错过了一些关于使用块的内存管理的东西.传递被替换的Urls是否安全,这是自动释放到这个块?那么修改实例变量formattedText呢?
NSMutableSet* replacedUrls = [[[NSMutableSet alloc] init] autorelease];
NSError *error = nil;
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:
(NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber)
error:&error];
if (error) {
return;
}
[detector enumerateMatchesInString:self.formattedText
options:0
range:NSMakeRange(0, [self.formattedText length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
@try {
if (result.resultType == NSTextCheckingTypePhoneNumber) {
if (!result.phoneNumber) {
// not sure if this is possible
return;
}
self.formattedText = [self.formattedText stringByReplacingOccurrencesOfString:result.phoneNumber
withString:[NSString stringWithFormat:@"<a href=\"tel://%@\">%@</a>", result.phoneNumber, result.phoneNumber]];
}
else if (result.resultType == NSTextCheckingTypeLink) {
if (!result.URL) {
// not sure if this is possible
return;
}
NSString* fullUrl = [result.URL absoluteString];
if (!fullUrl) {
return;
}
if ([replacedUrls containsObject:fullUrl]) {
return;
}
// not sure if this is possible
if ([result.URL host] && [result.URL path]) {
NSString* urlWithNoScheme = [NSString stringWithFormat:@"%@%@", [result.URL host], [result.URL path]];
// replace all http://www.google.com to www.google.com
self.formattedText = [self.formattedText stringByReplacingOccurrencesOfString:fullUrl
withString:urlWithNoScheme];
// replace all www.google.com with http://www.google.com
NSString* replaceText = [NSString stringWithFormat:@"<a href=\"%@\">%@</a>", fullUrl, fullUrl];
self.formattedText = [self.formattedText stringByReplacingOccurrencesOfString:urlWithNoScheme
withString:replaceText];
[replacedUrls addObject:fullUrl];
}
}
}
@catch (NSException* ignore) {
// ignore any issues
}
}];
Run Code Online (Sandbox Code Playgroud)
您遇到的问题似乎与内存管理有关。您首先搜索字符串self.formattedText。这意味着,当进行此搜索时,您的NSDataDetector实例可能需要访问字符串来读取字符等。只要self.formattedText不被释放,这一切都很好。通常,即使对于这样的块方法,调用者也有责任保留参数直到函数调用结束。
当您在匹配发现块内更改 的值时,self.formattedText旧值将自动释放(假设这是一个retain属性)。我不知道 NSDataDetector 可能会进行缓存,或者与自动释放池等相关的问题,但我非常确定这可能会导致问题。
我的建议是你 [NSString stringWithString:self.formattedText]作为enumerateMatchesInString:参数传递,而不是简单的self.formattedText. 这样,您向 NSDataDetector 传递一个实例,该实例在自动释放池耗尽之前不会被释放。