2013-08-09 27 views
8

Tôi đang làm việc với API dựa trên khối và tình cờ gặp một tình huống mà tôi đã chuyển trong tham số chặn có chữ ký không khớp với thông số đã nhập phương pháp được mong đợi. Trước sự ngạc nhiên của tôi, trình biên dịch dường như không quan tâm đến điều này và ứng dụng không gặp sự cố. Đây có phải là hành vi mong đợi không? Ví dụ:Truyền tham số chặn không khớp với chữ ký

typedef void(^MyBlock)(); 
typedef void(^MyBlockWithParam)(id param); 

- (void)doWork { 
    MyBlockWithParam block1 = ^(id param) { 
     NSLog(@"block1: %@", param); 
    }; 

    MyBlock block2 = ^{ 
     NSLog(@"block2"); 
    }; 

    [self loadData:block1]; 
    [self loadData:block2]; 
} 

- (void)loadData:(MyBlockWithParam)block { 
    block(@"foo"); 
} 
+3

Tôi nghĩ nếu bạn thay đổi người đầu tiên thành 'void (^ MyBlockType) (void)', bạn sẽ nhận được đơn khiếu nại. Các '()' trống rỗng có nghĩa là arg không xác định tôi tin. – nielsbot

+0

Vâng, điều đó làm cho trình biên dịch phàn nàn về nó sau đó. Bạn có biết nếu đó là tài liệu một số nơi (tôi đã không nhìn thấy nó nếu có)? Nếu bạn muốn đăng bình luận của bạn như là câu trả lời tôi sẽ chấp nhận nó. Cảm ơn – chinabuffet

+0

Không chắc chắn - Tôi đã nhận được thông tin này từ câu trả lời khác về một câu hỏi khác :) Hãy để tôi xem. – nielsbot

Trả lời

9

Cung cấp một đối số đặc điểm kỹ thuật sản phẩm nào như trong

typedef void(^MyBlock)(); 

có nghĩa là "không xác định" đối số . Vì vậy, hai loại tương thích như được viết. Thay đổi tuyên bố đầu tiên thành

typedef void(^MyBlock)(void); 

chỉ định rằng khối không có đối số và bạn sẽ gặp lỗi.

K & R C xác định rằng danh sách đối số trống có nghĩa là "không xác định". C khối spec nói đây là không đúng sự thật cho tờ khai loại khối (x http://clang.llvm.org/docs/BlockLanguageSpec.html#block-variable-declarations) nhưng: cả GCC và Clang thực hiện K & R hành vi như một phần mở rộng ngôn ngữ.

3

Đây là điều C. Một hàm mẫu hoặc khối với một danh sách đối số rỗng có nghĩa là "hàm (hoặc khối) nhận bất kỳ đối số nào bạn muốn". Nếu bạn muốn truyền đạt rằng khối nên không có đối số, bạn cần phải nói một cách rõ ràng nên như thế này:

typedef void(^MyBlock)(void) 

Điều này phần lớn lịch sử từ những ngày trước khi ANSI khi không có nguyên mẫu chức năng và tất cả các tờ khai chức năng (như trái ngược với các định nghĩa) trông như thế này:

some_type function(); 
4

Từ đặc điểm kỹ thuật Clang Blocks:

variadic ... đối số được hỗ trợ. [variadic.c] Một Khối không có đối số phải chỉ định khoảng trống trong danh sách đối số [voidarg.c]. Một danh sách tham số trống không đại diện, như K & R cung cấp, một danh sách đối số không xác định. Lưu ý: cả gcc và clang đều hỗ trợ kiểu dáng K & R.

Về cơ bản, đây là cú pháp cổ của cú pháp C. Trong thời gian cũ, cú pháp khai báo hàm C khá khác nhau và các dấu ngoặc đơn trống chỉ ra rằng hàm có thể được truyền qua bất kỳ số lượng đối số nào. Đối với tính tương thích ngược, các trình biên dịch thường cho phép cú pháp khai báo hàm kiểu cũ. Và vì lý do nào đó, Apple đã quyết định từ chối đồng thời cú pháp này trong tiêu chuẩn khối trong khi thực sự cho phép nó được sử dụng với các khối trong cả GCC và Clang.

Vì vậy, câu chuyện dài ngắn: Để tuyên bố rằng một khối không có đối số, bạn cần phải gõ một cách rõ ràng như void(^MyBlock)(void)

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