1

Environment: Mac OS X 10.9, Xcode 5.0.2

I want use a constant fields for Notification name. Like this:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didUploadFinished)
                                             name:uploadNotif_uploadFileFinished
                                           object:nil];

I use a constant uploadNotif_uploadFileFinished instead @"uploadNotif_uploadFileFinished".

Constant fields instead @”string” give us, check name of the notification, during compiling. But realization of this may be different. I`am found methods using extern constant or static constant, see bellow example, but maybe exists better way to realization it?

Example to emulate “enum” of NSString, based on extern constant:
Upload.h:

#import <Foundation/Foundation.h>

@interface Upload : NSObject <NSURLConnectionDelegate>

-(void)finishUpload;

@end

// Declaretion list name of notifications for Upload Objects. Enum strings:
// ________________________________________
extern NSString* const uploadNotif_uploadFileFinished;
extern NSString* const uploadNotif_uploadError;
// ________________________________________


Upload.m:

#import "Upload.h"

@implementation Upload

-(void)finishUpload
{
    [[NSNotificationCenter defaultCenter]
    postNotificationName:uploadNotif_uploadFileFinished object:nil];
}

@end

// Initialization list name of notifications for Upload Objects. Enum strings:
// ________________________________________
NSString* const uploadNotif_uploadFileFinished = @"uploadNotif_uploadFileFinished";
NSString* const uploadNotif_uploadError = @"uploadNotif_uploadError";
// ________________________________________

This realization not very like to me because of it is not clear where declared “uploadNotif_uploadFileFinished” constant. Ideal variant may like this Upload::uploadFileFinished:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didUploadFinished)
                                             name:Upload::uploadFileFinished
                                           object:nil];

But how realize this?

Community
  • 1
  • 1
Jarikus
  • 774
  • 8
  • 18
  • You answered your own question as far as I'm concerned. Don't use `#define` for objects, you'll have unnecessary objects created all over the place. And you don't **need** Objective-C++ for this, there is nothing wrong with them being freestanding globals (this is C after all). I would recommend using `FOUNDATION_EXPORT` instead of `extern` directly, as `FOUNDATION_EXPORT` maps to `extern` or `extern 'C'` depending on which is appropriate (thoughtless migration from Objective-C to Objective-C++) – Brandon Buck Sep 05 '14 at 20:47

2 Answers2

0

I don't see any problem with your proposed solution, but if you don't like using extern NSString* const, you can use #define pre-processor statements like this in your header:

#define uploadNotif_uploadFileFinished @"uploadNotif_uploadFileFinished"
#define uploadNotif_uploadError @"uploadNotif_uploadError"

The usage is exactly the same, just import the header and you can use the constants.

Personally, I prefer defining extern NSString* const.

EDIT: Sadly Objective-C doesn't have namespaces. The broadly extended solution (even UIKit or Cocoa frameworks use it) is to use your class prefix in the constant names. This way you can declare constants which name doesn't collide with others frameworks declared names.

For example:

#define JKUploadFileFinished @"uploadNotif_uploadFileFinished"
#define JKUploadError @"uploadNotif_uploadError"
redent84
  • 18,901
  • 4
  • 62
  • 85
  • In this theme [link](http://stackoverflow.com/questions/538996/constants-in-objective-c) sayed what extern const more productive (using pointer comparison) than #define. Then for me extern const better than #define, but necessary insert name of class into name constant 'uploadNotif' + 'uploadFileFinished' that known where is this constant is declared ;( – Jarikus Jan 15 '14 at 15:53
  • Most of the `NSString*` properties are declared as `copy` to avoid mutability issues when using `NSMutableString`, so using pointer comparisons for strings is still very dangerous. – redent84 Jan 15 '14 at 17:27
  • @Jarikus Just don't worry about "efficiency". This is very unlikely to cause performance issues. –  Jan 15 '14 at 17:37
-1

You need objective-C++;

h-file:

class Upload
{
public:
static NSString* const uploadFileFinished;
static NSString* const uploadError;
};

mm-file:

NSString* const Upload::uploadFileFinished = @"uploadNotif_uploadFileFinished";
NSString* const Upload::uploadError = @"uploadNotif_uploadError";
Cy-4AH
  • 4,370
  • 2
  • 15
  • 22
  • I till see one inconvenience: constants must take out in a separate files like "ConstUploadSet.h" and “ConstUploadSet.mm” perhaps if such constant have many it no bad idea. – Jarikus Jan 15 '14 at 16:02
  • @Jarikus, you can place it in the same files with `@interface`, `@implementation`. Just give classes different names and use mm instead m. – Cy-4AH Jan 16 '14 at 07:29