2009-12-08 42 views
11

Tôi đã xác định giao thức mà tất cả các trình cắm của tôi phải triển khai. Tôi cũng muốn các trình cắm thêm sử dụng một số chuỗi nhất định, như MyPluginErrorDomain. Với số nguyên này khá dễ dàng đạt được trong một enum, nhưng tôi không thể tìm ra cách để làm tương tự với các chuỗi. Thông thường, trong các lớp học tôi sẽ xác địnhCách tốt nhất để xác định hằng số chuỗi trong giao thức khách quan-c là gì?

extern NSString * const MyPluginErrorDomain; 

trong file .h và trong file .m:

NSString * const MyPluginErrorDomain = @"MyPluginErrorDomain"; 

nhưng điều đó không làm việc rất tốt trong một giao thức, bởi vì sau đó mỗi plug- trong sẽ phải cung cấp thực hiện riêng của mình mà đánh bại mục đích có một hằng số.

sau đó tôi đã cố gắng

#define MYPLUGIN_ERROR_DOMAIN @"MyPluginErrorDomain" 

nhưng các lớp học thực hiện trong các plug-in dường như không thể nhìn thấy cáC#define. Ai biết được một giải pháp tốt?

+0

xóa thẻ C, C++ - đây là câu hỏi C mục tiêu – zaharpopov

+0

Ghi chú cho C++, cũng xem nhận xét của tôi về câu trả lời thú vị của Neil Butterworth. Tôi vẫn đang băn khoăn liệu có phải là giải pháp C không, tôi không thể là người đầu tiên trong lịch sử của C, người muốn đạt được điều này. –

+0

Vì đây là C Hằng số C này không cần phải được loại bỏ – iCaramba

Trả lời

10

Bạn có thể khai báo chúng trong tiêu đề bằng giao thức (nhưng bên ngoài giao diện giao thức), sau đó xác định chúng trong tệp triển khai cho giao thức (rõ ràng nó sẽ không có phần @implementation - chỉ định nghĩa NSString).

Hoặc có cặp .h/.m riêng biệt chỉ dành cho các hằng số chuỗi (tiêu đề giao thức có thể nhập tiêu đề chuỗi hằng số).

3

Trong C++, tôi sẽ khai báo trong một tiêu đề như thế này:

const char * const MYPLUGIN_ERROR_DOMAIN = "MyPluginErrorDomain"; 
const char * const MYPLUGIN_FOO_DOMAIN = "MyPluginFooDomain"; 

Lưu ý rằng khi con trỏ đang const, họ sẽ có địa phương cho các đơn vị dịch header đượC#included trong, và do đó sẽ không cần sử dụng extern để ngăn chặn nhiều lỗi định nghĩa.

+0

Là * địa phương cho các đơn vị dịch * hợp lệ cho tất cả các định nghĩa con trỏ const? –

+1

Điều này đúng với tất cả các định nghĩa const - con trỏ chỉ là một trường hợp. Lưu ý rằng con trỏ chính nó phải là const, vì vậy const char * p = "foo"; sẽ không làm. –

+0

Đối với những người, như tôi, thấy điều này đáng ngạc nhiên: "Tên có phạm vi không gian tên có liên kết nội bộ nếu nó là tên của .. đối tượng hoặc tham chiếu được khai báo rõ ràng const và không khai báo rõ ràng bên ngoài .." [3.5/3 ] –

9

Bạn giữ nét .h:

extern NSString * const MyPluginErrorDomain; 

nhưng đặt phần này vào một tập tin .m riêng biệt được nối trong khuôn khổ của bạn:

NSString * const MyPluginErrorDomain = @"MyPluginErrorDomain"; 

Vì vậy, plug-in có thể vẫn thực hiện nhưng khi biên dịch chúng liên kết hoặc biên dịch trong tệp .m khác của bạn, vì vậy chúng sẽ thấy giá trị của MyPluginErrorDomain.

2

Bạn nên thực hiện nó như chuỗi extern như trong ví dụ của bạn:

extern NSString * const MyPluginErrorDomain;

hoặc cung cấp chức năng bên ngoài trả về dữ liệu lưu trữ tĩnh. Ví dụ:

/* h */ 

extern NSString * MyPluginErrorDomain(); 

/* m */ 

NSString * MyPluginErrorDomain() { 
    static NSString * const s = @"MyPluginErrorDomain"; 
    return s; 
} 

Lý do là chuỗi và khóa thường được sử dụng và so sánh với giá trị con trỏ hoặc giá trị băm, thay vì so sánh chuỗi thực (isEqualToString :).

Ở cấp độ thực hiện, có một sự khác biệt lớn giữa:

Trong mã, đó có nghĩa là khi chuỗi so được quy định tại nhiều mã nhị phân:

Say 'MyPluginErrorDomain' và 'chìa khóa' có giống hệt nhau giá trị chuỗi, nhưng được định nghĩa trong các tệp nhị phân khác nhau (ví dụ: trong máy chủ plugin, một trong plugin).

/////// Pointer comparison (NSString) 
BOOL a = [MyPluginErrorDomain isEqualToString:key]; 
BOOL b = MyPluginErrorDomain == key; 

// c may be false because a may be true, in that they represent the same character sequence, but do not point to the same object 
BOOL c = a == b; 


/////// Hash use (NSString) 
// This is true 
BOOL d = [MyPluginErrorDomain hash] == [key hash]; 

// This is indicative if true 
BOOL e = [MyPluginErrorDomain hash] == [someOtherStringKey hash]; 

// because 
BOOL f = [MyPluginErrorDomain isEqualToString:someOtherStringKey]; 

// g may be false (though the hash code is 'generally' correct) 
BOOL g = e == f; 

Do đó, cần cung cấp khóa trong nhiều trường hợp. Nó có vẻ giống như một điểm tầm thường, nhưng rất khó để chẩn đoán một số vấn đề liên quan đến sự khác biệt.

Mã băm và so sánh con trỏ được sử dụng xuyên suốt Foundation và các công nghệ objc khác trong bộ nhớ từ điển, mã hóa khóa ... Nếu từ điển của bạn đi thẳng ra xml, đó là một điều, nhưng thời gian chạy là khác và có một vài thông báo trong chi tiết triển khai và thời gian chạy.

+0

'chuỗi extern' sẽ không hoạt động vì bạn không cần phải liên kết đến nhị phân để giao tiếp với nó thông qua một giao thức' --' * tin nhắn từ xa * –

+0

@gf Không có gì lạ khi một plugin liên kết đến một thư viện cụ thể vào giao diện plugin. – justin

+0

* "Không phổ biến" * không phải là * "luôn luôn" * - nhắn tin từ xa cũng là * "phổ biến" * với Cocoa. –

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