Objective-C静态类级变量

Objective-C静态类级变量,objective-c,variables,static,Objective C,Variables,Static,我有一个类胶片,每个类胶片存储一个唯一的ID。在C#、Java等语言中,我可以定义一个静态int currentID,每次设置ID时,我都可以增加currentID,更改发生在类级别而不是对象级别。这可以在Objective-C中实现吗?我发现很难找到答案。在.m文件中,可以将变量声明为静态变量: static ClassName *variableName = nil; 然后可以在+(void)initialize方法上初始化它 请注意,这是一个普通的C静态变量,在java或C中,它不是静态

我有一个类胶片,每个类胶片存储一个唯一的ID。在C#、Java等语言中,我可以定义一个静态int currentID,每次设置ID时,我都可以增加currentID,更改发生在类级别而不是对象级别。这可以在Objective-C中实现吗?我发现很难找到答案。

在.m文件中,可以将变量声明为静态变量:

static ClassName *variableName = nil;
然后可以在
+(void)initialize
方法上初始化它


请注意,这是一个普通的C静态变量,在java或C中,它不是静态的,但会产生类似的结果。

< P>正如PGB所说,没有“类变量”,只有“实例变量”。Objy-C做类变量的方法是类的M文件中的静态全局变量。“静态”可确保变量不能在该文件之外使用(即不能在外部使用)。

在.m文件中,声明一个文件全局变量:

static int currentID = 1;
然后在init例程中,引用:

- (id) init
{
    self = [super init];
    if (self != nil) {
        _myID = currentID++; // not thread safe
    }
    return self;
}

或者,如果它需要在其他时间更改(例如在openConnection方法中),则在那里增加它。请记住,它不是线程安全的,如果可能存在任何线程问题,则需要进行同步(或者更好地使用原子添加)。

问题描述

  • 您希望ClassA有一个ClassB类变量
  • 您正在使用Objective-C作为编程语言
  • Objto-C不支持C++变量的类变量。 一个备选方案

    使用Objective-C功能模拟类变量行为

  • 在classA.m中声明/定义一个静态变量,这样它将只对classA方法(以及放在classA.m中的所有内容)可访问

  • 覆盖NSObject initialize class方法,以使用ClassB实例初始化静态变量一次

  • 您可能会想,为什么要覆盖NSObject initialize方法。关于此方法的Apple文档给出了答案:“在类或从其继承的任何类从程序内部发送第一条消息之前,运行时向程序中的每个类发送一次initialize(初始化)。(因此,如果不使用该类,则可能永远不会调用该方法)。”

  • 可以在任何ClassA类/实例方法中随意使用静态变量

  • 代码示例

    档案:classA.m

    static ClassB *classVariableName = nil;
    
    @implementation ClassA
    
    ...
     
    +(void) initialize
    {
        if (! classVariableName)
            classVariableName = [[ClassB alloc] init];
    }
    
    +(void) classMethodName
    {
        [classVariableName doSomething]; 
    }
    
    -(void) instanceMethodName
    {
        [classVariableName doSomething]; 
    }
    
    ...
    
    @end
    
    参考资料


  • 从Xcode 8开始,您可以在Obj-C中定义类属性。这是为了与Swift的静态属性进行互操作而添加的

    Objective-C现在支持与Swift类型属性互操作的类属性。它们被声明为:@property(class)NSString*someStringProperty;。它们从未被合成过。(23891898)

    这里有一个例子

    @interface YourClass : NSObject
    
    @property (class, nonatomic, assign) NSInteger currentId;
    
    @end
    
    @implementation YourClass
    
    static NSInteger _currentId = 0;
    
    + (NSInteger)currentId {
        return _currentId;
    }
    
    + (void)setCurrentId:(NSInteger)newValue {
        _currentId = newValue;
    }
    
    @end
    
    然后您可以像这样访问它:

    YourClass.currentId = 1;
    val = YourClass.currentId;
    
    这里有一个非常有趣的例子,我用它作为参考来编辑这个旧答案


    2011回答:(不要用这个,太可怕了)

    如果你真的不想声明一个全局变量,还有另外一个选项,可能不是很正统:-),但它是有效的。。。您可以像这样声明一个“get&set”方法,其中包含一个静态变量:

    + (NSString*)testHolder:(NSString*)_test {
        static NSString *test;
    
        if(_test != nil) {
            if(test != nil)
                [test release];
            test = [_test retain];
        }
    
        // if(test == nil)
        //     test = @"Initialize the var here if you need to";
    
        return test;
    }
    
    因此,如果需要获取值,只需调用:

    NSString *testVal = [MyClass testHolder:nil]
    
    然后,当您要设置它时:

    [MyClass testHolder:testVal]
    
    如果您希望能够将此伪静态变量设置为nil,则可以将
    testHolder
    声明为:

    + (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
        static NSString *test;
    
        if(shouldSet) {
            if(test != nil)
                [test release];
            test = [_test retain];
        }
    
        return test;
    }
    
    还有两种简便的方法:

    + (NSString*)test {
        return [MyClass testHolderSet:NO newValue:nil];
    }
    
    + (void)setTest:(NSString*)_test {
        [MyClass testHolderSet:YES newValue:_test];
    }
    

    希望有帮助!祝你好运。

    这里有一个选项:

    +(int)getId{
        static int id;
        //Do anything you need to update the ID here
        return id;
    }
    

    注意,此方法将是唯一访问ID的方法,因此必须在该代码中以某种方式更新它。

    < P> u可以将类重命名为CLSA.mm,并在其中添加C++特征。

    < P>(严格地说不是问题的答案,但在我的经验中,当寻找类变量时可能有用)

    类方法通常可以扮演类变量在其他语言中可能扮演的许多角色(例如,测试期间更改的配置):


    现在,类
    MyCls
    的对象调用
    Resource:changeSomething:
    字符串
    @“Something general”
    调用
    doTheThing:
    ,但从
    MySpecialCase
    派生的对象调用字符串
    @“Something specific”

    另一种可能性是有一个小的
    NSNumber
    子类singleton。

    你能在ClassA.m中有一个ClassA类型的静态变量吗?这可能是一个愚蠢的问题,但是释放所说的内存呢?没关系,因为它必须像应用程序运行的时间一样长?@samiq,看看。无法删除指向对象的指针,但可以删除对象本身。你可能不想释放它,因为你很可能希望它在应用程序运行期间一直存在,但是如果你释放它,你会节省内存,因此如果你知道你不再需要它,那么你应该释放它。如果initialize()保证只调用一次,为什么你需要条件“if(!classVariableName)”?@jamie,
    initialize
    为每个类(子类之前的超类)调用一次,但如果子类未重写
    initialize
    ,则父类
    initialize
    将再次调用。因此,如果您不希望代码执行两次,就需要一个保护。在Apple的Objective-C文档中可以看到。很酷,但它不是一个真正的全局变量,因为它不能从其他
    .m
    文件中访问,我认为它在
    Class.m
    文件中是“全局”的是好的。
    @interface MyCls: NSObject
    + (NSString*)theNameThing;
    - (void)doTheThing;
    @end
    @implementation
    + (NSString*)theNameThing { return @"Something general"; }
    - (void)doTheThing {
      [SomeResource changeSomething:[self.class theNameThing]];
    }
    @end
    
    @interface MySpecialCase: MyCls
    @end
    @implementation
    + (NSString*)theNameThing { return @"Something specific"; }
    @end