Objective c 是什么导致SIGSEGV使用块?

Objective c 是什么导致SIGSEGV使用块?,objective-c,objective-c-blocks,Objective C,Objective C Blocks,我有以下代码。我偶尔会得到一个SIGSEGV。我觉得我缺少了一些关于使用块进行内存管理的东西。通过自动释放到此块的replacedUrls安全吗?修改实例变量formattedText怎么样 NSMutableSet* replacedUrls = [[[NSMutableSet alloc] init] autorelease]; NSError *error = nil; NSDataDetector *detector = [NSDataDetector dat

我有以下代码。我偶尔会得到一个SIGSEGV。我觉得我缺少了一些关于使用块进行内存管理的东西。通过自动释放到此块的replacedUrls安全吗?修改实例变量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
            }
        }];
NSMutableSet*replacedUrls=[[NSMutableSet alloc]init]autorelease];
n错误*错误=nil;
NSDataDetector*detector=[NSDataDetector DataDetectorWithType:
(NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber)
错误:&错误];
如果(错误){
返回;
}
[检测器枚举匹配安装:self.formattedText
选项:0
范围:NSMakeRange(0,[self.formattedText长度])
usingBlock:^(NSTextCheckingResult*结果,NSMatchingFlags标志,布尔*停止){
@试一试{
if(result.resultType==NSTextCheckingTypePhoneNumber){
如果(!result.phoneNumber){
//不确定这是否可行
返回;
}
self.formattedText=[self.formattedText stringByReplacingOccurrencesOfString:result.phoneNumber
withString:[NSString stringWithFormat:@',result.phoneNumber,result.phoneNumber]];
}
else if(result.resultType==NSTextCheckingTypeLink){
如果(!result.URL){
//不确定这是否可行
返回;
}
NSString*fullUrl=[result.URL绝对字符串];
如果(!fullUrl){
返回;
}
if([replacedUrls containsObject:fullUrl]){
返回;
}
//不确定这是否可行
if([result.URL主机]&&&[result.URL路径]){
NSString*urlWithNoScheme=[NSString stringWithFormat:@“%@%@”,[result.URL主机],[result.URL路径]];
//全部替换http://www.google.com 访问www.google.com
self.formattedText=[self.formattedText stringByReplacingOccurrencesOfString:fullUrl
带字符串:urlWithNoScheme];
//将所有www.google.com替换为http://www.google.com
NSString*replaceText=[NSString stringWithFormat:@',fullUrl,fullUrl];
self.formattedText=[self.formattedText stringByReplacingOccurrencesOfString:urlWithNoScheme
带字符串:replaceText];
[replacedUrls addObject:fullUrl];
}
}
}
@捕获(NSException*忽略){
//忽略任何问题
}
}];

您遇到的问题似乎与内存管理有关。首先搜索字符串
self.formattedText
。这意味着,在进行此搜索时,您的
NSDataDetector
实例可能需要访问字符串以读取字符等。只要
self.formattedText
没有被释放,这一切都很好。通常,即使对于这样的块方法,调用方也有责任保留参数,直到函数调用结束

当您在match found块内更改
self.formattedText
的值时,旧值将自动释放(假设这是
retain
属性)。我不知道NSDataDetector可能会进行缓存,也不知道与自动释放池相关的问题,但我非常确定这可能会导致问题


我的建议是将
[NSString-stringWithString:self.formattedText]
作为
枚举匹配安装:
参数传递,而不是普通的
self.formattedText
。通过这种方式,您可以向NSDataDetector传递一个实例,该实例在自动释放池耗尽之前不会被释放。

经过一些阅读,我肯定看到了我将在何处创建一个保留周期,因为self将被保留。不过,我仍然不确定这将如何产生实际问题。最不可靠的一行是“if(error){return;}”,但我也不确定这是如何导致问题的(如果此时返回,代码将正常恢复,对吗?)。保持自我不一定会导致保持循环,保持循环也不会导致SIGSEGV;是的,那句台词很奇怪。我甚至不确定这是否必要。我想我是把它作为一种精神检查加上去的。在我们加入那条线之前,它得到了一个SIGSEGV。大多数if语句都是添加的,因为崩溃报告只是指向一般块,而不是特定行。追查这个问题有点烦人。在这里修改格式化文本安全吗?对于您关于优雅返回的问题,它确实返回得很好。我们所做的就是用正确转义的URL替换URL,以便它们正确地显示在控件中。可能会有更好的实施;奇怪的是,虽然我收到了报告,但我不能为自己的生活重新创造。要么是那个,要么就是这个。不管怎样,谢谢你的帮助。非常感谢。我还没有完全测试过这一点,但我认为你的答案是值得的。:)