2012-04-23 26 views
5

Tôi muốn sử dụng biến __block để nhận giá trị trong khối. Nhưng khi ra khỏi khối, biến __block có vẻ là không. Tại sao điều này sẽ xảy ra?Biến "__block" dẫn đến giá trị nil khi đi ra khỏi khối

NSString *fileName = [Tools MD5Encode:url]; 
    __block NSString *filePath = nil; 
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSString *aFileName = obj; 
     if ([aFileName isEqualToString:fileName]) { 
      NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
      filePath = path; 
      NSLog(@"filePath1 %@", filePath); 
      *stop = YES; 
     } 
    }]; 
    //NSLog(@"filePath2 %@", filePath); 
    //filePath seems to be nil 
    return filePath; 

Khi tôi thay đổi mã thành [path copy], nó hoạt động. Nhưng tôi không biết đây có phải là một ý hay hay không. Mọi quyết định?

NSString *fileName = [Tools MD5Encode:url]; 
    __block NSString *filePath = nil; 
    [fileList enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     NSString *aFileName = obj; 
     if ([aFileName isEqualToString:fileName]) { 
      NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
      filePath = [path copy]; 
      NSLog(@"filePath1 %@", filePath); 
      *stop = YES; 
     } 
    }]; 
    //NSLog(@"filePath2 %@", filePath); 
    return [filePath autorelease]; 
+1

Đó là những tình huống như thế này khiến tôi vui mừng khi nhóm của tôi quyết định nắm lấy ARC. –

Trả lời

1

Có thể sử dụng bản sao hoặc giữ lại trên đường dẫn. Lý do cho vấn đề của bạn là các đối tượng NSString là thành viên của các đối tượng tiện lợi cùng với các đối tượng khác như NSArray mà bạn không thực sự phải phát hành và đã được hệ thống tự động phát hành trước ngày ARC. Cá nhân, tôi không thích rằng họ đã làm điều đó gây ra nó chỉ gây ra sự nhầm lẫn như thế này. Bởi vì khối hoàn thành việc thực thi hệ thống, hãy tự động phát hiện đối tượng chuỗi mà bạn đã cấp phát gây ra sự rò rỉ.

5

http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html

Cụ thể:

Nếu không có ARC, __block cũng có tác dụng phụ của việc không giữ lại nội dung của nó khi nó được chụp bởi một khối. Các khối sẽ tự động giữ lại và giải phóng bất kỳ con trỏ đối tượng nào mà chúng nắm bắt, nhưng các con trỏ __block là đặc biệt và hoạt động như một con trỏ yếu. Nó trở thành một mô hình phổ biến để dựa vào hành vi này bằng cách sử dụng __block để tránh giữ lại chu kỳ.

Trong ARC, __block hiện giữ lại nội dung của nó giống như các con trỏ đối tượng đã chụp khác. Mã sử ​​dụng __block để tránh các chu kỳ lưu giữ sẽ không hoạt động nữa. Thay vào đó, hãy sử dụng __weak như mô tả ở trên.

Vì vậy, bạn cần phải sao chép.

+0

Tôi không tin rằng "đường dẫn NSString * = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent: aFileName] là một đối tượng được phân bổ theo ngăn xếp" là chính xác. Như tôi đã hiểu, chỉ riêng đối tượng khối (không phải bất kỳ đối tượng nào được tạo bởi mã trong khối) là một đối tượng ngăn xếp. http://www.friday.com/bbum/2009/08/29/blocks-tips-tricks/ –

+0

Bạn nói đúng ... cảm ơn vì đã sửa tôi. Tôi sẽ chỉnh sửa bài đăng của mình. –

1

Việc sử dụng các khối thậm chí có vấn đề ở đây không?

Dường như với tôi rằng chuỗi mã này:

NSString *filePath = nil; 
NSString *path = [VERSIONS_INFO_DATA_DIRECTORY stringByAppendingPathComponent:aFileName]; 
filePath = path; 
return [filePath autorelease]; 

là quá phóng filePath (vì bạn không sở hữu kết quả của -stringByAppendingPathComponent:, bạn không nên (auto) phát hành nó)

+0

tốt, tôi đã sao chép mã sai. Khi tôi sử dụng "filePath = path", nên trả về filePath. Sau đó, vấn đề đã đến. Tôi đã sửa nó ngay bây giờ. – Wayne

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