2011-10-01 27 views
8

Tôi có mã sau đây. Tôi thỉnh thoảng nhận được SIGSEGV. Tôi có một cảm giác tôi đang thiếu một cái gì đó liên quan đến quản lý bộ nhớ bằng cách sử dụng các khối. Có an toàn khi vượt qua các Url được thay thế, được tự động phát hành cho khối này không? Điều gì về việc sửa đổi biến thể instance formattedText?Điều gì gây ra một SIGSEGV bằng cách sử dụng các khối?

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

Sau khi đọc xong, tôi chắc chắn sẽ thấy nơi tôi sẽ tạo chu trình giữ lại vì bản thân sẽ được giữ lại. Tuy nhiên, không chắc chắn làm thế nào mà sẽ tạo ra vấn đề thực tế, mặc dù. – tjg184

+0

dòng dodgiest là 'if (error) {return;} nhưng tôi không chắc chắn làm thế nào mà gây ra vấn đề của bạn hoặc (mã của bạn phục hồi gracefully nếu bạn trở lại vào thời điểm này, phải không?). Việc giữ lại bản thân không nhất thiết gây ra một chu trình giữ lại, và chu trình giữ lại sẽ không gây ra SIGSEGV; – hooleyhoop

+0

Vâng, dòng đó là lạ. Tôi thậm chí không chắc nó là cần thiết. Tôi nghĩ rằng tôi đã thêm nó như là một kiểm tra sanity. Nó đã nhận được SIGSEGV trước khi chúng tôi thêm vào dòng đó. Hầu hết những câu lệnh đó nếu được thêm vào vì báo cáo sự cố chỉ trỏ tới khối chung và không phải là một dòng cụ thể. Loại gây phiền nhiễu để theo dõi vấn đề. Có an toàn để sửa đổi định dạng trong văn bản này không? – tjg184

Trả lời

2

Có vẻ như vấn đề bạn gặp phải là vấn đề liên quan đến quản lý bộ nhớ. Bạn bắt đầu bằng cách tìm kiếm thông qua chuỗi self.formattedText. Điều này có nghĩa rằng, trong khi tìm kiếm này diễn ra, trường hợp NSDataDetector của bạn có thể cần truy cập chuỗi để đọc các ký tự, v.v. Điều này hoạt động tốt và đẹp, miễn là self.formattedText không bị phân phối lại. Thông thường, ngay cả đối với các phương thức khối như thế này, trách nhiệm của người gọi là giữ lại các đối số cho đến khi kết thúc cuộc gọi hàm.

Khi bên trong khối kết hợp phù hợp, bạn thay đổi giá trị self.formattedText, giá trị cũ được tự động phát hành (giả sử đây là tài sản retain). Tôi không biết về bộ nhớ đệm mà NSDataDetector có thể làm, hoặc các vấn đề liên quan đến các nhóm tự động phát tán, v.v., nhưng tôi khá chắc chắn rằng điều này có thể gây ra vấn đề.

gợi ý của tôi là bạn vượt qua[NSString stringWithString:self.formattedText] như là đối số enumerateMatchesInString:, chứ không phải là đồng bằng self.formattedText. Bằng cách này, bạn vượt qua NSDataDetector một thể hiện sẽ không được phát hành cho đến khi hồ tự động thoát ra.

+0

Tôi chưa thử nghiệm đầy đủ điều này, nhưng tôi nghĩ câu trả lời của bạn xứng đáng. :) – tjg184

Các vấn đề liên quan