2011-10-01 73 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

相關問題