开发者

How to declare NSString constants for passing to NSNotificationCenter

I've got the following in my .h file:

#ifndef _BALANCE_NOTIFICATION
#define _BALANCE NOTIFICATION
const NSString *BalanceUpdateNotification
#endif

and the following in my .m file:

const NSString *BalanceUpdateNotification = @"BalanceUpdateNotification";

I'm using this with the following codes:

[[NSNotificationCenter defaultCenter]
    addObserver:self
    selector:@selector(updateBalance:)
    name:BalanceUpdateNotification
    object:nil];

and

[[NSNotificatoinCenter defaultCenter]
    postNotificationName:BalanceUpdateNotification
    object:self userInfo:nil];

Which works, but it gives me a warning:

Passing argument 1 of 'postNotificationName:object:userInfo' discards qualifiers from poi开发者_开发知识库nter target type

So, I can cast it to (NSString *), but I'm wondering what the proper way to do this is.


Typically you declare the variable as extern in the header. The most idiomatic way seems to be like this:

Header

#ifndef __HEADER_H__
#define __HEADER_H__

extern NSString * const BalanceUpdateNotification;

#endif

Source

#include "header.h"

NSString * const BalanceUpdateNotification = @"BalanceUpdateNotification";

extern tells the compiler that something of type NSString * const by the name of BalanceUpdateNotification exists somewhere. It could be in the source file that includes the header, but maybe not. It is not the compiler's job to ensure that it does exist, only that you are using it appropriately according to how you typed it. It is the linkers job to make sure that BalanceUpdateNotification actually has been defined somewhere, and only once.

Putting the const after the * means you can't reassign BalanceUpdateNotification to point to a different NSString.


NSStrings are immutable, so declaring a const NSString * would be redundant; just use NSString *.

If what you're trying to do is declare that the pointer itself can't change, that would be:

   NSString * const BalanceUpdateNotification = @"BalanceUpdateNotification";

See also Constants in Objective-C


I see no reason not to use a constant literal with a preprocessor directive. #import does the job of inclusion guards, so you can simply say

#define AutomaticallyResumeDownloads @"AutomaticallyResumeDownloads"

and then #import the header containing that definition wherever it's needed.


Typically, one does not make these variables constant. One would, on the other hand, declare them as externs in the header file. This is (a little bit) because when you say const NSString *string, you are telling the compiler that the memory pointed to by string will not change -- this is both not useful and not necessarily true, being that we have no control over how apple's classes manage state variables. (Although NSStrings declared at runtime are placed in the text segment, functionality could change across versions or something.) If you truly wanted to use const, which I still advise against, it should be NSString * const string, which will prevent the pointer from being altered to point to a different memory location (which it would not do otherwise);


This is the working solution to declare NSString name for observers.

static NSString *const MyCustomNotificationName = @"MyCustomNotificationName";


Apple has a recommendation in their own documentation, where among other things, the macro APPKIT_EXTERN is used instead of extern. Combined with the contents of a default header file when created in Xcode, this is a complete implementation:

Constants.h:

#import <Cocoa/Cocoa.h>

#ifndef Constants_h
#define Constants_h

APPKIT_EXTERN NSString *MyConstantName;

#endif

Constants.m:

#import "Constants.h"

NSString *MyConstantName = @"MyConstantValue";

I think the above is more or less the standard way to achieve string constants, according to Apple.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜