2010-01-12 37 views
8

Tôi đã cố tạo một biến tĩnh để lưu trữ một từ điển hình ảnh. Thật không may, cách tốt nhất tôi có thể tìm thấy để khởi tạo nó là để kiểm tra trong mỗi chức năng sử dụng biến. Vì tôi đang tạo biến này bên trong một thể loại, tôi không thể khởi tạo nó bên trong trình khởi tạo. Có cách nào để khởi tạo navigationBarImages không?Khởi tạo biến tĩnh trong loại Mục tiêu-C

static NSMutableDictionary *navigationBarImages = NULL; 

@implementation UINavigationBar(CustomImage) 
//Overrider to draw a custom image 
- (void)drawRect:(CGRect)rect 
{ 
    if(navigationBarImages==NULL){ 
     navigationBarImages=[[NSMutableDictionary alloc] init]; 
    } 
    NSString *imageName=[navigationBarImages objectForKey:self]; 
    if (imageName==nil) { 
     [email protected]"header_bg.png"; 
    } 
    UIImage *image = [UIImage imageNamed: imageName]; 
    [image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; 
} 

//Allow the setting of an image for the navigation bar 
- (void)setImage:(UIImage*)image 
{ 
    if(navigationBarImages==NULL){ 
     navigationBarImages=[[NSMutableDictionary alloc] init]; 
    } 
    [navigationBarImages setObject:image forKey:self]; 
} 
@end 
+0

Tôi không khuyến khích khởi tạo đối tượng Obj-c bằng NULL, bạn nên khởi chạy nó bằng nil! –

+0

@DanielSanchez, trong khi tôi đồng ý, trên thực tế, nil chỉ là NULL được gán làm đối tượng. –

+0

@FireLizzard nil tương đương với NULL cho một con trỏ tới một đối tượng. nil và NULL không nên hoán đổi cho nhau. NULL được định nghĩa khác với nil. nil được định nghĩa là (id) 0. NULL không phải là. –

Trả lời

24
__attribute__((constructor)) 
static void initialize_navigationBarImages() { 
    navigationBarImages = [[NSMutableDictionary alloc] init]; 
} 

__attribute__((destructor)) 
static void destroy_navigationBarImages() { 
    [navigationBarImages release]; 
} 

Những chức năng sẽ được gọi tự động khi chương trình bắt đầu và kết thúc .

+2

Tôi thích điều này tốt hơn '+ initializer'. – neevek

+3

Tôi không hiểu ... Trường hợp này đi đâu? Được viết như thế? Và những gì được cho là sẽ xảy ra? –

1

Một tùy chọn là sử dụng C++. Thay đổi phần mở rộng của tệp thành .mm và thay thế = NULL bằng [[NSMutableDictionary alloc] init].

+0

Điều đó có hoạt động trên iPhone không? – Casebash

2

Tất cả những gì bạn cần là đặt tĩnh một lần tại một điểm đã biết trước khi nó được sử dụng. Ví dụ, bạn có thể thiết lập một đại biểu NSApplication và có nó làm công việc trong -applicationDidFinishLaunching:

+0

Tôi không thể truy cập nó trong một tệp khác - biến tĩnh chỉ được khai báo trong phạm vi của một lớp – Casebash

+2

Chỉ cần xác định một hàm thiết lập độc lập. –

+1

Không. Điều đó sẽ không hoạt động. * Một cái gì đó * đã gọi chức năng thiết lập. – bbum

10

Hãy xem xét cách tiếp cận này,

static NSMutableDictionary *navigationBarImages() 
{ 
    static NSMutableDictionary *dict = NULL; 
    if(dict == NULL) 
    { 
     dict = [[NSMutableDictionary alloc] init]; 
    } 
    return [[dict retain] autorelease]; 
} 

sau đó bất cứ khi nào bạn woulde sử dụng navigationBarImages, thay thế nó với navigationBarImages(), như thế này:

thay đổi

NSString *imageName=[navigationBarImages objectForKey:self]; 

để

NSString *imageName=[navigationBarImages() objectForKey:self]; 

Nếu overhead chức năng cuộc gọi phiền bạn, có thể sử dụng một biến tạm thời để đón sự trở lại của navigationBarImages(),

NSMutableDictionary *dict = navigationBarImages(); 
[dict doSomething]; 
[dict doSomething]; 

Các nhược điểm là khi bạn gọi navigationBarImages(), các Ví dụ của NSMutableDictionary đã được tạo ra, sau đó nó sẽ không bao giờ có cơ hội để dealloc cho đến khi kết thúc chương trình.

+2

Cuộc đời này là điển hình cho các biến tĩnh mặc dù, vì vậy Tôi sẽ không thực sự coi đó là một hạn chế. –

+1

Điều này sẽ không hoàn toàn giống như luồng an toàn khi sử dụng 'dispatch_once' để khởi tạo từ điển.Mã sẽ tốt hơn để sử dụng: 'static dispatch_once_t một lần; static NSMutableDictionary * dict = nil; dispatch_once (& once,^{dict = [[NSMutableDictionary alloc] init];}); return dict; ' – Streeter

0

Bạn có thể thêm +initialize vào tệp .m trong danh mục của mình - bạn chỉ cần đảm bảo rằng bạn không đập một triển khai hiện tại hoặc bạn sẽ nhận được sự chiến thắng chung. (Rõ ràng, bạn có thể chắc chắn về điều này nếu bạn viết mã, nhưng với mã của bên thứ ba, điều này có lẽ không phải là phương pháp tốt nhất.)

+1

... và bạn sẽ chắc chắn như thế nào? Ý tưởng tồi. – benzado

+0

Bạn chắc chắn có thể chắc chắn nếu bạn đã viết các lớp học, hoặc bạn có thể sử dụng phương pháp introspection thời gian chạy hoặc phương pháp tương tự. Tôi thường chỉ sử dụng + khởi tạo trong nguồn của riêng tôi, tôi đã chỉ đưa nó ra khỏi đó như là một tùy chọn. Thông thường, nó * là * tùy chọn tốt nhất, không chỉ với các danh mục. –

+0

Nếu bạn đã viết lớp, bạn không cần phải đặt + khởi tạo trong một danh mục. Nếu bạn không viết nó, bạn không thể tin tưởng rằng bạn sẽ không dẫm lên nó trong một phiên bản tương lai của thư viện. Đặt + khởi tạo trong một danh mục có nhiều rủi ro hơn giá trị của nó. – benzado

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