Cách tốt nhất để tạo các hằng số trong Objective-C là gì


156

Tôi đang tạo một khách hàng Reddit cho mục đích học tập. Tôi cần phải có một tập tin với hằng số trong đó. Tôi đã suy nghĩ về việc nhập tệp trong Reddit-Prefix.pchtệp để cung cấp các hằng số có sẵn cho tất cả các tệp. Đó có phải là một cách tốt để làm việc? Ngoài ra, tôi đã thực hiện nghiên cứu của mình và tìm thấy một số phương pháp để tạo hằng số, nhưng tôi không biết nên sử dụng phương pháp nào:

  • #define vĩ mô
  • const
  • static const
  • extern const
  • enum

Vậy cách nào là cách ưa thích? Quy ước là gì? Tôi biết rằng "nó phụ thuộc" nhưng câu hỏi của tôi cụ thể hơn là: các trường hợp sử dụng cho mỗi giải pháp đó là gì?

Ngoài ra, nếu sử dụng extern const, tôi có cần nhập tệp không, hoặc các hằng số sẽ có sẵn trên toàn cầu mà không cần nhập tệp?

Một điều tôi có thể kết luận một cách hợp lý là đó enumlà sự lựa chọn tốt nhất khi xác định một cái gì đó giống như các miền lỗi tùy chỉnh (tôi có thực sự đúng không?). Nhưng những gì về những người khác?


stackoverflow.com/questions/11153156/ từ vui lòng truy cập liên kết này ... giải pháp của bạn nằm trong bài đăng này
Người dùng 1531343

3
@BhastaKama: Đó là một câu hỏi hẹp hơn đối chiếu hai giải pháp cụ thể.
Peter Hosey

cho - const tĩnh, #define, enum, liên kết này rất hữu ích stackoverflow.com/questions/1674032/static-const-vs-define-in-c cung cấp lời giải thích tốt về những 3 thay thế const
tài khoản 1.531.343

enumchỉ hữu ích cho các giá trị tích phân. #definevà hằng số có thể là bất kỳ loại dữ liệu.
rmaddy

const, static constextern constđều giống nhau ngoại trừ phạm vi. Vì vậy, thực sự chỉ có ba lựa chọn.
rmaddy

Câu trả lời:


385

Câu hỏi đầu tiên là phạm vi bạn muốn các hằng số của bạn có, đây thực sự là hai câu hỏi:

  • Là các hằng số cụ thể cho một lớp duy nhất, hoặc nó có ý nghĩa để có tất cả chúng trên ứng dụng?
  • Nếu chúng là đặc thù của lớp, chúng được sử dụng bởi các khách hàng của lớp, hoặc chỉ trong lớp?

Nếu chúng là cụ thể và nội bộ cho một lớp duy nhất, hãy khai báo chúng static constở đầu tệp .m, như vậy:

static NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Nếu chúng liên quan đến một lớp duy nhất nhưng phải được công khai / sử dụng bởi các lớp khác, hãy khai báo chúng như externtrong tiêu đề và định nghĩa chúng trong .m:

//.h
extern NSString *const MyThingNotificationKey;

//.m
NSString *const MyThingNotificationKey = @"MyThingNotificationKey";

Nếu chúng phải là toàn cục, hãy khai báo chúng trong một tiêu đề và xác định chúng trong một mô-đun tương ứng, đặc biệt cho các hằng số đó.

Bạn có thể trộn và kết hợp chúng cho các hằng số khác nhau với các mức độ khác nhau về mức độ toàn cầu mà bạn muốn chúng tồn tại và đối với các hằng số toàn cầu khác nhau đơn giản không thuộc về nhau, bạn có thể đặt chúng vào các mô-đun riêng biệt, mỗi mô-đun có tiêu đề riêng, nếu bạn muốn

Tại sao không #define?

Câu trả lời cũ là các macro macro không có thông tin kiểu, nhưng các trình biên dịch ngày nay khá thông minh trong việc thực hiện tất cả các loại kiểm tra chữ (các macro mở rộng thành) cũng như các biến.

Câu trả lời hiện đại là vì trình gỡ lỗi sẽ không biết về macro của bạn. Bạn không thể nói [myThing addObserver:self forKey:MyThingNotificationKey]trong lệnh gỡ lỗi nếu MyThingNotificationKeylà macro; trình gỡ lỗi chỉ có thể biết về nó nếu nó là một biến.

Tại sao không enum?

Vâng, rmaddy đã đánh bại tôi trong phần bình luận: enumchỉ có thể định nghĩa các hằng số nguyên. Những thứ như số định danh nối tiếp, mặt nạ bit, mã bốn byte, v.v.

Đối với những mục đích đó, enumlà tuyệt vời và bạn hoàn toàn nên sử dụng nó. (Thậm chí tốt hơn, sử dụng các macro NS_ENUMNS_OPTIONS .) Đối với những thứ khác, bạn phải sử dụng một cái gì đó khác; enumkhông làm gì ngoài số nguyên.

Và những câu hỏi khác

Tôi đã suy nghĩ về việc nhập tệp trong tệp Reddit-Prefix.pch để cung cấp các hằng số có sẵn cho tất cả các tệp. Đó có phải là một cách tốt để làm việc?

Có lẽ vô hại, nhưng có lẽ quá mức. Nhập (các) tiêu đề hằng của bạn, nơi bạn cần chúng.

Các trường hợp sử dụng cho mỗi giải pháp đó là gì?

  • #define: Khá hạn chế. Tôi thực sự không chắc chắn có lý do chính đáng để sử dụng điều này cho các hằng số nữa.
  • const: Tốt nhất cho hằng số địa phương. Ngoài ra, bạn phải sử dụng điều này cho một cái bạn đã khai báo trong một tiêu đề và hiện đang xác định.
  • static const: Tốt nhất cho các hằng số dành riêng cho tệp (hoặc lớp cụ thể).
  • extern const: Bạn phải sử dụng điều này khi xuất một hằng trong tiêu đề.

Ngoài ra, nếu sử dụng extern const, tôi có cần nhập tệp không, hoặc các hằng số sẽ có sẵn trên toàn cầu mà không cần nhập tệp?

Bạn cần nhập tệp, trong mỗi tệp mà bạn sử dụng hoặc trong tiêu đề tiền tố.


3
Tại sao không sử dụng hoàn toàn static NSString *consttrong .htập tin?
Iulian Onofrei

3
@IulianOnofrei: Bạn có thể, nếu đó là trong một ứng dụng chứ không phải khung. Nếu bạn làm như vậy static NSString *const foo = @"foo";, thì tiêu đề của bạn sẽ xác định chuỗi đó là gì và nó phải giống nhau ở mọi nơi nếu bạn thay đổi chuỗi và các bên khác nhau sử dụng các phiên bản khác nhau của tiêu đề với một chuỗi khác nhau, thì các chuỗi sẽ không khớp khi chạy thời gian. Trong một khung, bạn chỉ muốn cung cấp quyền truy cập vào biểu tượng và để khung đó là nguồn duy nhất của giá trị thực của biểu tượng đó, vì vậy mọi người đều nhận được cùng một chuỗi từ một nơi. Đó là những gì externcó được bạn.
Peter Hosey

Lưu ý bổ sung về #defines: chúng không được đảm bảo có cùng một địa chỉ trong bộ nhớ (tùy thuộc vào cách chúng được khai báo, chúng có thể phân bổ một thể hiện mới mỗi khi chúng được sử dụng), vì vậy việc sử dụng myObject == MyDefinesẽ không luôn hoạt động như mong đợi, nhưng myObject == MyStaticConstsẽ
Ben Leggiero

Liệu nó có ý nghĩa về chính tả như static NSString *constthay vì static NSString const*?? Có gì khác biệt?!
kokos8998

@ kokos8998 có làm nên sự khác biệt không? Có nó làm. static NSString const *giống như static const NSString *và có nghĩa là "con trỏ (có thể thay đổi) thành NSString không đổi" - điều này hơi vô dụng ở đây vì NSString đã không thay đổi. Những gì bạn muốn chỉ static NSString * const- đó là "con trỏ liên tục đến NSString"
David

8

FOUNDATION_EXPORT

Cân nhắc sử dụng FOUNDATION_EXPORTđể tương thích nhiều hơn một chút so với externkhi nó được xác định trong nền tảng và biên dịch thành các định dạng tương thích cho C, C ++ và Win32.

Như được định nghĩa trong NSObjCR nb.h

#if defined(__cplusplus)
#define FOUNDATION_EXTERN extern "C"
#else
#define FOUNDATION_EXTERN extern
#endif

#if TARGET_OS_WIN32

    #if defined(NSBUILDINGFOUNDATION)
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllexport)
    #else
        #define FOUNDATION_EXPORT FOUNDATION_EXTERN __declspec(dllimport)
    #endif

    #define FOUNDATION_IMPORT FOUNDATION_EXTERN __declspec(dllimport)

#else
    #define FOUNDATION_EXPORT  FOUNDATION_EXTERN
    #define FOUNDATION_IMPORT FOUNDATION_EXTERN
#endif
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.