2011-10-01 76 views
8

我有以下代码。我偶尔会得到一个SIGSEGV。我有一种感觉,我错过了一些关于使用块的内存管理的东西。是否可以安全地通过自动发布到此块的replacementUrls?那么修改实例变量formattedText怎么样?是什么导致使用块的SIGSEGV?

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 
      } 
     }]; 
+0

经过一番阅读后,我确定看到我将在哪里创建一个保留周期,因为自我将被保留。不过,仍然不确定这将如何产生实际问题。 – tjg184

+0

最简单的一行是'if(error){return;}但是我不确定这是怎么导致你的问题(如果你现在返回的话,你的代码会优雅地恢复,对不对?)。保留自己不一定会导致保留周期,并且保留周期不会导致SIGSEGV; – hooleyhoop

+0

是的,那条线很奇怪。我甚至不确定这是否有必要。我想我把它添加为一个完整的检查。在添加该行之前,它正在获取SIGSEGV。这些if语句中的大部分都是因为崩溃报告只是指向一般块而不是特定的行而添加的。讨厌这个问题很烦人。在这里修改formattedText安全吗? – tjg184

回答

2

看来您遇到的问题与内存管理有关。您首先搜索字符串self.formattedText。这意味着,在进行此搜索时,您的NSDataDetector实例可能需要访问该字符串才能读取字符等。只要self.formattedText未被取消分配,此工作就会很好,很好。通常,即使是像这样的块方法,调用者也有责任保留参数直到函数调用结束。

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

我的建议是,你通过[NSString stringWithString:self.formattedText]enumerateMatchesInString:参数,而不是普通self.formattedText。这样,你通过NSDataDetector一个实例,它将不会被释放,直到自动释放池被耗尽。

+0

我还没有完全测试过这个,但我认为你的答案是值得的。 :) – tjg184

相关问题