ऑब्जेक्टिव-सी स्टेटिक क्लास लेवल वेरिएबल


143

मेरे पास एक क्लास फिल्म है, जिसमें से प्रत्येक एक अद्वितीय आईडी संग्रहीत करता है। C #, Java आदि में मैं एक स्थिर int currentID को परिभाषित कर सकता हूं और हर बार जब मैं आईडी सेट करता हूं तो मैं currentID बढ़ा सकता हूं और परिवर्तन क्लास स्तर पर होता है न कि ऑब्जेक्ट स्तर पर। क्या यह Objective-C में किया जा सकता है? मैंने इसके लिए एक उत्तर खोजना बहुत कठिन पाया है।

जवाबों:


158

मुद्दा विवरण :

  1. आप चाहते हैं कि आपका ClassA एक ClassB वर्ग चर हो।
  2. आप प्रोग्रामिंग भाषा के रूप में ऑब्जेक्टिव-सी का उपयोग कर रहे हैं।
  3. ऑब्जेक्टिव-सी क्लास के वैरिएबल को सपोर्ट नहीं करता जैसा कि C ++ करता है।

एक विकल्प :

ऑब्जेक्टिव-सी फीचर्स का उपयोग कर एक क्लास वेरिएबल बिहेवियर का अनुकरण करें

  1. ClassA.m के भीतर एक स्थिर वैरिएबल को डिक्लेयर / डिफाइन करें, इसलिए यह केवल classA के तरीकों (और सब कुछ जो आप classA.m के अंदर डालते हैं) के लिए सुलभ होगा।

  2. NSBbject को क्लास क्लास के एक उदाहरण के साथ सिर्फ एक बार स्टेटिक वैरिएबल को इनिशियलाइज़ करने के लिए शुरुआती तरीके से ओवरराइट करें।

  3. आप सोच रहे होंगे कि मैं NSObject के इनिशियलाइज़ मेथड को ओवरराइट क्यों करूँ। इस पद्धति के बारे में Apple प्रलेखन का उत्तर है: "रनटाइम प्रोग्राम में प्रत्येक कक्षा को कक्षा से ठीक एक समय पहले, या उस से विरासत में प्राप्त किसी भी वर्ग को प्रारंभिक संदेश भेजता है, कार्यक्रम के भीतर से इसका पहला संदेश भेजा जाता है। (इस प्रकार विधि) यदि कक्षा का उपयोग नहीं किया जाता है तो इसे कभी भी लागू नहीं किया जा सकता है।) "।

  4. किसी भी 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

संदर्भ :

  1. कक्षा चर ने उद्देश्य-सी और सी ++ दृष्टिकोण की तुलना की

3
क्या आपके पास classA.m के भीतर टाइप ClassA का स्थिर वैरिएबल हो सकता है?
गोल्टिंक्स

6
यह एक मूर्खतापूर्ण प्रश्न हो सकता है लेकिन उक्त स्मृति के विमोचन का क्या? इससे कोई फर्क नहीं पड़ता क्योंकि इसे तब तक जीना है जब तक ऐप चल रहा है?
Samiq

1
@samiq, ऑब्जेक्टिव-सी देखें: स्टैटिक वेरिएबल को क्यों बनाए रखें? । ऑब्जेक्ट के पॉइंटर को हटाया नहीं जा सकता है, लेकिन ऑब्जेक्ट ही कर सकता है। आप शायद इसे जारी नहीं करना चाहते क्योंकि आप सबसे अधिक संभावना यह चाहते हैं कि जब तक ऐप चल रहा है, तब तक आप इसे जारी रखें, लेकिन यदि आप इसे रिलीज़ करते हैं, तो आप मेमोरी को बचाएंगे, इसलिए यदि आप जानते हैं कि आपको इसकी आवश्यकता नहीं है, तो आपको चाहिए छोड़ दीजिए।
ma11hew28

5
यदि इनिशियलाइज़ () को केवल एक बार कॉल करने की गारंटी दी जाती है, तो आपको "if (classVariableName)" सशर्त की आवश्यकता क्यों है?
jb

23
@ जैमी, initializeप्रत्येक वर्ग के लिए एक बार कहा जाता है (उपवर्गों से पहले सुपरक्लास ), लेकिन अगर एक उपवर्ग ओवरराइड नहीं करता है initialize, तो अभिभावक वर्ग initializeको फिर से बुलाया जाएगा। इसलिए, यदि आप उस कोड को दो बार निष्पादित नहीं करना चाहते हैं, तो एक गार्ड की आवश्यकता है। Apple के ऑब्जेक्टिव-सी डॉक्स में क्लास ऑब्जेक्ट को इनिशियलाइज़ करना देखें ।
big_m

31

Xcode 8 के रूप में, आप ओबज-सी में वर्ग गुणों को परिभाषित कर सकते हैं। यह स्विफ्ट के स्थिर गुणों के साथ जुड़ने के लिए जोड़ा गया है।

उद्देश्य-सी अब वर्ग गुणों का समर्थन करता है, जो स्विफ्ट प्रकार के गुणों के साथ हस्तक्षेप करता है। उन्हें इस प्रकार घोषित किया जाता है: @property (वर्ग) 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 उत्तर: (इस का उपयोग न करें, यह भयानक है)

यदि आप वास्तव में एक वैश्विक चर घोषित नहीं करना चाहते हैं, तो एक और विकल्प, शायद बहुत रूढ़िवादी :-) नहीं है, लेकिन काम करता है ... आप इस तरह से "वैरिएबल सेट" विधि की घोषणा कर सकते हैं, जिसमें एक स्थिर चर है:

+ (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]

यदि आप इस छद्म-स्थैतिक-संस्करण को शून्य पर सेट करने में सक्षम होना चाहते हैं, तो आप 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];
}

आशा करता हूँ की ये काम करेगा! सौभाग्य।


कूल, लेकिन यह वास्तव में एक वैश्विक चर नहीं है क्योंकि इसे अन्य .mफ़ाइलों से एक्सेस नहीं किया जा सकता है , और मुझे लगता है कि यह Class.mफ़ाइल के भीतर "वैश्विक" होना ठीक है ।
ma11hew28

29

अपनी .m फ़ाइल पर, आप वैरिएबल को स्थैतिक घोषित कर सकते हैं:

static ClassName *variableName = nil;

फिर आप इसे अपने +(void)initializeतरीके पर शुरू कर सकते हैं ।

कृपया ध्यान दें कि यह एक सादा सी स्थिर चर है और इस अर्थ में स्थिर नहीं है कि जावा या सी # इस पर विचार करें, लेकिन समान परिणाम प्राप्त करेंगे।


16

अपनी .m फ़ाइल में, फ़ाइल को वैश्विक चर घोषित करें:

static int currentID = 1;

फिर अपनी नियमित दिनचर्या में, यह देखें कि:

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

या यदि इसे किसी अन्य समय (जैसे आपके ओपनकोनेक्शन विधि में) बदलना है, तो इसे वहां बढ़ाएँ। याद रखें कि यह थ्रेड सुरक्षित नहीं है जैसा कि, यदि आपको कोई थ्रेडिंग समस्या हो सकती है, तो आपको सिंक्रोनाइजेशन (या बेहतर अभी तक, परमाणु ऐड का उपयोग करना) करना होगा।


11

जैसा कि पीजीबी ने कहा, "केवल" उदाहरण चर "" वर्ग चर नहीं हैं। कक्षा चर करने का उद्देश्य-सी तरीका वर्ग की .m फ़ाइल के अंदर एक स्थिर वैश्विक चर है। "स्थिर" यह सुनिश्चित करता है कि चर का उपयोग उस फ़ाइल के बाहर नहीं किया जा सकता है (अर्थात यह बाहरी नहीं हो सकता है)।


3

यहाँ एक विकल्प होगा:

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

ध्यान दें कि यह तरीका आईडी एक्सेस करने का एकमात्र तरीका होगा, इसलिए आपको इस कोड में इसे किसी तरह अपडेट करना होगा।


2

(कड़ाई से सवाल का जवाब नहीं बोल रहा है, लेकिन मेरे अनुभव में वर्ग चर की तलाश में उपयोगी होने की संभावना है)

एक वर्ग विधि अक्सर कई भूमिकाएं निभा सकती है जो एक वर्ग चर अन्य भाषाओं में होगी (उदाहरण के लिए परीक्षण के दौरान परिवर्तित कॉन्फ़िगरेशन):

@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

अब, MyClsकॉल Resource:changeSomething:के लिए स्ट्रिंग @"Something general"पर क्लास के साथ एक ऑब्जेक्ट कॉल करता है doTheThing:, लेकिन MySpecialCaseस्ट्रिंग के साथ प्राप्त की गई ऑब्जेक्ट @"Something specific"


0

आप क्लास को classA.mm के रूप में बदल सकते हैं और उसमें C ++ फीचर जोड़ सकते हैं।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.