【问题标题】:Best way to emulate “enum” const list of NSString?模拟 NSString 的“枚举”常量列表的最佳方法?
【发布时间】:2014-01-15 15:10:25
【问题描述】:

环境:Mac OS X 10.9、Xcode 5.0.2

我想为通知名称使用一个常量字段。像这样:

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

我使用常量uploadNotif_uploadFileFinished 代替@"uploadNotif_uploadFileFinished"

常量字段代替@“string” 给我们,在编译期间检查通知的名称。 但是实现这可能会有所不同。我是found 使用外部常量或静态常量的方法,请参见下面的示例,但也许存在更好的实现方式?

基于外部常量模拟 NSString 的“枚举”的示例:
上传.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;
// ________________________________________


上传.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";
// ________________________________________

我不太喜欢这种实现,因为不清楚在哪里声明了“uploadNotif_uploadFileFinished”常量。理想的变种可能会这样Upload::uploadFileFinished

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

但是如何实现呢?

【问题讨论】:

  • 就我而言,您回答了自己的问题。不要将#define 用于对象,您将在各处创建不必要的对象。而且你不需要需要 Objective-C++,它们是独立的全局变量并没有错(毕竟这是C)。我建议直接使用FOUNDATION_EXPORT 而不是extern,因为FOUNDATION_EXPORT 映射到externextern 'C',这取决于哪个是合适的(从Objective-C 到Objective-C++ 的无思想迁移)

标签: objective-c cocoa initialization constants


【解决方案1】:

我认为您提出的解决方案没有任何问题,但如果您不喜欢使用 extern NSString* const,您可以在标题中使用像这样的 #define 预处理器语句:

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

用法完全一样,只需要导入header就可以使用常量了。

就个人而言,我更喜欢定义extern NSString* const

编辑: 遗憾的是,Objective-C 没有命名空间。广泛扩展的解决方案(甚至 UIKit 或 Cocoa 框架都使用它)是在常量名称中使用您的类前缀。这样,您可以声明名称不会与其他框架声明的名称冲突的常量。

例如:

#define JKUploadFileFinished @"uploadNotif_uploadFileFinished"
#define JKUploadError @"uploadNotif_uploadError"

【讨论】:

  • 在这个主题中link 说 extern const 比 #define 更有效率(使用指针比较)。然后对我来说 extern const 比#define 更好,但是必须将类的名称插入到名称常量“uploadNotif”+“uploadFileFinished”中,知道该常量在哪里声明;(
  • 大部分NSString*属性被声明为copy以避免在使用NSMutableString时出现可变性问题,所以对字符串使用指针比较还是很危险的。
  • @Jarikus 只是不要担心“效率”。这不太可能导致性能问题。
【解决方案2】:

你需要 Objective-C++;

h-文件:

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

mm 文件:

NSString* const Upload::uploadFileFinished = @"uploadNotif_uploadFileFinished";
NSString* const Upload::uploadError = @"uploadNotif_uploadError";

【讨论】:

  • 我看到了一个不便之处:常量必须放在单独的文件中,例如“ConstUploadSet.h”和“ConstUploadSet.mm”,如果这样的常量有很多也不错。
  • @Jarikus,您可以将其与@interface@implementation 放在同一个文件中。只需给类起不同的名称并使用 mm 代替 m。
猜你喜欢
  • 2012-10-21
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
相关资源
最近更新 更多