什么导致SIGSEGV使用块?

时间:2011-10-01 02:56:45

标签: 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
            }
        }];

1 个答案:

答案 0 :(得分:2)

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

当你的匹配找到阻止内部时,你更改了self.formattedText的值,旧的值会自动释放(假设这是一个retain属性)。我不知道NSDataDetector可能会做的缓存,或者与自动释放池等有关的问题,但我很确定这可能会导致问题。

我的建议是您传递 [NSString stringWithString:self.formattedText]作为enumerateMatchesInString:参数,而不是普通self.formattedText。这样,您就可以向NSDataDetector传递一个在自动释放池耗尽之前不会被释放的实例。