2010-10-07 25 views
11

Có vẻ như từ thử nghiệm rằng biểu thức thu thập chỉ được đánh giá một lần. Hãy xem xét ví dụ sau:Mục tiêu c "cho mỗi" (liệt kê nhanh) - đánh giá bộ sưu tập?

static NSArray *a; 

- (NSArray *)fcn 
{ 
    if (a == nil) 
     a = [NSArray arrayWithObjects:@"one", @"two", @"three", nil]; 
    NSLog(@"called"); 
    return a; 
} 

... 

for (NSString *s in [self fcn]) 
    NSLog(@"%@", s); 

Đầu ra là:

2010-10-07 07:37:31.419 WidePhotoViewer Lite[23694:207] called 
2010-10-07 07:37:31.420 WidePhotoViewer Lite[23694:207] one 
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] two 
2010-10-07 07:37:31.425 WidePhotoViewer Lite[23694:207] three 

chỉ ra rằng [tự fcn] được gọi là chỉ một lần.

Có ai có thể xác nhận rằng đây là hành vi được chỉ định (trái ngược với quan sát đơn thuần) không?

Những gì tôi có trong tâm trí đang làm một cái gì đó như thế này:

for (UIView *v in [innerView subviews]) { 

thay vì điều này:

NSArray *vs = [innerView subviews]; 
for (UIView *v in vs) { 

Suy nghĩ?

+0

Nhờ những điều đó, đặc biệt. Shmurk, người đã cố gắng trả lời ... điều này thực sự làm sáng tỏ vấn đề. (Kiểm tra một thực hiện để làm rõ một đặc điểm kỹ thuật là nguy hiểm. Dù sao, tôi đã làm điều đó trong việc chuẩn bị câu hỏi.) –

Trả lời

13

Loại vòng lặp này được gọi là "liệt kê nhanh" (xem đối tượng NSFastEnumeration). Tài liệu của Apple nói rằng trong "đối với obj trong biểu thức", biểu thức mang lại một đối tượng phù hợp với giao thức NSFastEnumeration, vì vậy tôi đoán đó là hành vi đúng: hàm được gọi một lần, một trình lặp được tạo một lần và được sử dụng trong vòng lặp.

0

Đây là một phần của hành vi liệt kê nhanh. Đối với một số kiến ​​thức chuyên sâu về việc triển khai liệt kê nhanh kiểm tra bài đăng trên blog này trên NSBlog: Implementing Fast Enumeration.

3

Ý thức chung sẽ quyết định theo cách đó. Nhưng vì nó không được ghi trực tiếp vào tài liệu liệt kê nhanh, tại sao bạn không có một cái nhìn tại các giao thức riêng của mình:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSFastEnumeration_protocol/Reference/NSFastEnumeration.html

giao thức này không được cung cấp các phương pháp như nextObject, hoặc objectAtIndex, hoặc một cái gì đó như điều đó, nhưng thay vào đó yêu cầu một mảng C của các đối tượng, sau đó được lặp lại.

Mặc dù có những chỉ dẫn mạnh mẽ, không có tài liệu nào đảm bảo cho bạn rằng biểu thức chỉ được đánh giá một lần.

7

Trong thực tế, collection chỉ được đánh giá một lần, bạn có thể kiểm tra nguồn gốc của clang, ví dụ. Khi tài liệu không nói đủ chính xác, bạn cần phải tin tưởng việc triển khai.

Có, tôi nghĩ Apple nên làm rõ tài liệu. Vui lòng gửi một lỗi, Marc!

Một cách đơn giản để thực hiện việc này là đọc phần lề của tài liệu chính thức, có thể tìm thấy here. Đó là tuyên bố rằng

điều tra viên có một trình bảo vệ đột biến để nếu bạn cố gắng sửa đổi bộ sưu tập trong quá trình liệt kê, ngoại lệ được nêu ra. Kể từ khi đột biến của đối tượng trong quá trình lặp lại bị cấm, bạn có thể thực hiện nhiều liệt kê đồng thời.

vì vậy, bộ sưu tập mà bạn lặp lại không thể thay đổi.Nó không nói liệu nó đánh giá collection trong

for(id obj in collection) { ... } 

một hoặc hai lần, đối tượng kết quả không thể thay đổi.

+0

+1 chỉ để cho thấy một lỗi-nộp! – Wevah

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