【问题标题】:Initialising static variable in Objective-C在 Objective-C 中初始化静态变量
【发布时间】:2012-08-28 13:26:05
【问题描述】:

在 Objective-C 类中,我只想将文本文件的内容加载到 NSString 中,以便该类的所有实例都可以使用它。

多年来,我在 Java 世界中了解到,如果不使用经过验证的惯用语,就线程安全而言很容易犯这种微妙的错误。所以我想确保我使用正确的成语。

你能告诉我一个Objective-C类的例子吗?

这是我开始的空课......

@interface TestClass : NSObject
- (NSString *)doSomething:(NSUInteger)aParam;
@end

@implementation TestClass {
}

- (id)init {
    self = [super init];
    if (self) {

    }
    return self;
}

- (NSString *)doSomething:(NSUInteger)aParam {
     // something with shared NSString loaded from text file, 
     //  depending on the value of aParam
     return @""; 
}
@end

【问题讨论】:

    标签: objective-c idioms


    【解决方案1】:

    在 Objective C 中处理静态属性的惯用方法是将它们隐藏在类方法后面(带有+ 的方法)。在类方法的实现中将您的字符串声明为static,并使用dispatch_once 进行初始化:

    + (id)stringFromFile {
        static dispatch_once_t once;
        static NSString *sharedString;
        dispatch_once(&once, ^{
            sharedString = [NSString
                stringWithContentsOfFile:@"MyFile"
                encoding:... // ...supply proper parameters here...
                error:...];
        });
        return sharedString;
    }
    

    这种设置静态对象的方式是线程安全的。 sharedString 将被初始化一次,即使该方法是从多个线程并发调用的。

    现在您可以通过调用[MyClass stringFromFile] 从任何地方访问您的字符串。

    【讨论】:

    • 这正是我正在寻找的知识渊博的答案。谢谢。
    【解决方案2】:

    创建一个实例变量供您的类实例访问,并在您指定的初始化程序中创建一个静态变量。您指定的初始化程序应创建一次字符串对象(将其保存在静态变量中)并每次将其分配给实例变量。例如:

    @implementation TestClass {
        NSString *_myString;
    }
    
    - (id)init {
        self = [super init];
        if (self == nil) return nil;
    
        static dispatch_once_t once;
        static NSString *aString = nil;
        dispatch_once(&once, ^{
            aString = ... // However you want to instantiate the string
        });
        _myString = aString;
    
        return self;
    }
    

    这使您可以像访问普通实例变量一样访问实例方法中的字符串,尽管字符串仅创建一次并且每个实例都指向单个对象。

    【讨论】:

    • 拥有最终的“_myString = aString;”是否安全?在 dispatch_once 块之外?
    • 是的。如果你把它放在dispatch_once 块中,那将是不正确的——该块的全部意义在于它只执行一次。您需要为班级的每个实例执行该分配,否则只有一个班级实例将具有非零_myStringaString 只会有一个值,并且只有在设置该值之后才会发生分配。
    【解决方案3】:
    - (NSString *)doSomething:(NSUInteger)aParam { 
    
        static NSString *foo = nil;
    
        if (!foo) {
            //load foo
        }
    
        return @"";  
    }
    

    【讨论】:

      【解决方案4】:

      【讨论】:

      • 但我描述的是单例吗?我将拥有我的类的许多实例,但我希望它们都共享对一个特定 NSString 的访问,该 NSString 在创建类的第一个实例时初始化。
      猜你喜欢
      • 2011-01-04
      • 1970-01-01
      • 2011-06-28
      • 2021-07-28
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多