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.
精彩评论