2010-07-22 36 views
11

Tôi đang sử dụng một tập hợp các tệp Constant.m, mỗi tệp một mục tiêu, để xác định những điều cụ thể cho từng mục tiêu. Ví dụ:Làm thế nào tôi có thể sử dụng một NSArray như một hằng số toàn cầu?

// Constants.h 
extern NSString * const kDatabaseFileName; 
//Constants.m 
NSString * const kDatabaseFileName = @"target_one.sqlite"; 

Tôi cũng muốn xác định một NSArray cho mỗi mục tiêu của tôi:

NSArray * const kLabelNames = [[NSArray alloc] initWithObjects: 
    @"nameLabel", @"addressLabel", nil]; 

Nhưng điều này mang lại "lỗi: yếu tố khởi tạo phải là không đổi". Sử dụng 'arrayWithObjects` cũng không hoạt động. Đây có phải là vì các chuỗi trong mảng của tôi không phải là hằng số?

Tôi làm cách nào để thiết lập một mảng dưới dạng hằng số chung? Cảm ơn.

+0

có thể trùng lặp của [Làm cách nào để khai báo mảng dưới dạng hằng số trong Mục tiêu-c?] (Http://stackoverflow.com/questions/2436463/how-do-i-declare-an-array- as-a-constant-in-objective-c) –

Trả lời

6

Nếu bạn muốn một tập hợp các hằng số bao gồm các loại NS, hãy xem xét đặt tất cả chúng trong một singleton.

Bạn có thể có một tệp tiêu đề duy nhất và nhiều tệp triển khai (một tệp cho mỗi mục tiêu). Miễn là tất cả thực hiện các lớp khai báo trong tập tin tiêu đề bạn nên được tốt.

2

Bạn nên tạo một lớp chứa các hằng số trong các phương thức lớp. Sau đó, bạn có thể thêm lớp vào bất kỳ mục tiêu nào và gọi các phương thức để lấy các hằng số trong các đối tượng như mảng. Thay đổi lớp hoặc thực hiện lớp để thay đổi sự trả về của các hằng số.

Nếu bạn sử dụng rất nhiều, bạn có thể tạo giao thức xác định tên phương thức. Sau đó hoán đổi lớp thực hiện giao thức trong mỗi mục tiêu sao cho cùng một mã trả về các giá trị khác nhau khi cần.

28

Trong mục tiêu-C, các đối tượng chỉ có thể được cấp phát trong heap, do đó không có cách nào để tạo NSArray trong bộ nhớ tĩnh. Tuy nhiên, bạn có thể tạo một mảng C của các con trỏ tới hằng NSString như vậy ...

NSString * const kLabelNames[] = { 
    @"Foo", @"Bar", @"Baz" 
}; 

... và sau đó bạn có thể viết các phương thức lớp như thế này ...

+ (NSArray *)labelNames 
{ 
    static NSArray *names; 
    if (names == nil) { 
     names = [[NSArray alloc] initWithObjects:kLabelNames count:3]; 
    } 
    return names; 
} 

Sửa

Lưu ý rằng với việc giới thiệu các công nghệ mới như ARC, Grand Central Dispatch và cú pháp mới cho mảng, bây giờ có cách đơn giản hơn để thực hiện điều gì đó tương tự. Lưu ý rằng ví dụ dưới đây cũng cung cấp an toàn luồng lớn hơn, mặc dù ví dụ ban đầu có thể đã kết hợp khối @synchronized hoặc một trong một số cơ chế khác để đạt được kết quả tương tự.

+ (NSArray *)labelNames 
{ 
    static NSArray *names; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     names = @[@"Foo", @"Bar", @"Baz"]; 
    }); 

    return names; 
} 

Tuy nhiên ví dụ trên không hoàn toàn giải quyết câu hỏi gốc. Nếu một mảng liên tục toàn cầu đang thực sự cần thiết, ví dụ trước có thể được viết lại dọc theo các đường tương tự như câu trả lời ban đầu, trong khi vẫn tận dụng GCD:

NSString * const kLabelNames[] = { 
    @"Foo", @"Bar", @"Baz" 
}; 

+ (NSArray *)labelNames 
{ 
    static NSArray *names; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     names = [NSArray arrayWithObjects:kLabelNames count:3]; 
    }); 

    return names; 
} 
+0

Trong trường hợp bạn muốn thay thế số đó: 3 bằng giá trị động thì bạn có thể sử dụng cách C cũ tốt để có kích thước của mảng. '' 'count: sizeof (kLabelNames)/sizeof (kLabelNames [0])' '' –

1

Nếu bạn muốn tránh làm một kiểm tra NULL trên mỗi sử dụng, bạn có thể phân lớp phương thức khởi tạo NSObject +. Điều đó sẽ được gọi một lần, lần đầu tiên lớp của bạn được khởi tạo (và một lần nữa trên mỗi lớp con, nếu bất kỳ lớp con nào được khởi tạo), và là một nơi rất tốt để thực hiện kiểu khởi tạo này.

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html%23//apple_ref/occ/clm/NSObject/initialize

+1

Nếu bạn đọc kỹ tài liệu được liên kết, bạn sẽ thấy 'initialize' có thể (và thường là) được gọi nhiều lần:" Thời gian chạy gửi 'initialize' cho mỗi lớp trong một chương trình chính xác một lần ngay trước lớp, * hoặc bất kỳ lớp nào thừa kế từ nó *, được gửi thông điệp đầu tiên của nó từ bên trong chương trình." [nhấn mạnh thêm] – jlehr

+0

Chỉ cần xem nhận xét của bạn và cập nhật câu trả lời của tôi. – StilesCrisis

5

Dưới đây là một cách tiếp cận đơn giản hơn nhiều:

Declare NSString với các yếu tố dấu phẩy tách ra (hoặc bất kỳ dấu phân cách bạn muốn)

NSString *const kLabelNames = @"Foo,Bar,Baz"; 

Sau đó chuyển sang NSArray bất cứ khi nào bạn cần nó:

NSArray *namesArray = [kLabelNames componentsSeparatedByString:@","]; 
4

Sử dụng macro:

#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"]) 
Các vấn đề liên quan