मैं आपके सवालों का जवाब देंगे नीचे, लेकिन शायद सबसे अच्छा तरीका यह सामान जानने के लिए कुछ उपयोगकर्ता के अनुकूल ऐसे cocoadevcentral पर अधिक the Learn Objective-C tutorial के रूप में भाषा के लिए नए लोगों के लिए करना नोट, पढ़ने के लिए है।
एक उदाहरण
मैं एक उदाहरण (मैं उदाहरण के द्वारा सीखने प्यार) के साथ आपके सवालों के जवाब में मदद करना चाहते हैं। आइए मान लें कि आप एक शिक्षक को एक प्रोग्राम लिख रहे हैं जो छात्रों को एक विशेष हां/कोई सवाल नहीं पूछता है, और यह ट्रैक करता है कि कितने लोग इसे सही करते हैं और कितने छात्रों ने पूछा है।
@interface Question : NSObject {
NSString* questionStr;
int numTimesAsked;
int numCorrectAnswers;
}
@property (nonatomic, retain) NSString* questionStr;
@property (nonatomic, readonly) int numTimesAsked;
@property (nonatomic) int numCorrectAnswers;
@property (nonatomic) int numWrongAnswers;
- addAnswerWithTruthValue: (BOOL) isCorrect;
@end
ब्रेसिज़ के अंदर तीन चर उदाहरण चर हैं, और आपके वर्ग के प्रत्येक उदाहरण वे चर से प्रत्येक के लिए अपने स्वयं के मान होगा:
यहाँ इस वर्ग के लिए एक संभव इंटरफेस है। ब्रेसिज़ के बाहर सबकुछ लेकिन @end
से पहले एक विधि की घोषणा है (@property
घोषणाओं सहित)।
(साइड नोट:। कई वस्तुओं के लिए, यह retain
गुण हैं, जब से तुम वस्तु को कॉपी करने की भूमि के ऊपर से बचने के लिए और सुनिश्चित करें कि आप प्रयोग कर रहे हैं, जबकि यह जारी नहीं किया है बनाना चाहते उपयोगी है यह कानूनी है करने के लिए retain
इस उदाहरण में एक NSString
, लेकिन it is often considered good practice to use copy
instead of retain
एक NSString*
के बाद से वास्तव में एक NSMutableString
वस्तु है, जो बाद में बदल सकता है जब आपके कोड यह एक ही रहने की उम्मीद को इंगित कर सकते हैं।)
क्या @property
करता
जब आप एक @property
का ऐलान करते हैं तो आपको दो बातें कर रहे हैं:
- वर्ग के इंटरफ़ेस में एक सेटर और गेटर विधि की घोषणा, और
- संकेत कैसे सेटर और गेटर व्यवहार।
@property (nonatomic, retain) NSString* questionStr;
मूल रूप से इस रूप में ही है:
- (NSString*) questionStr; // getter
- (void) setQuestionStr: (NSString) newQuestionStr; // setter
शीर्षक में
पहले एक के लिए, यह है कि इस लाइन को पता है काफी है। आप सचमुच उन दो तरीकों की घोषणा कर रहे हैं; आप उन्हें सीधे कॉल कर सकते हैं, या डॉट नोटेशन का उपयोग उनको कॉल करने के लिए शॉर्टकट के रूप में कर सकते हैं।
मूल रूप से "मूल रूप से" भाग "मूल रूप से" भाग nonatomic
और retain
जैसे कीवर्ड द्वारा दी गई अतिरिक्त जानकारी है।
nonatomic
कीवर्ड इंगित करता है कि वे आवश्यक रूप से थ्रेड-सुरक्षित नहीं हैं।सामान्य retain
कीवर्ड इंगित करता है कि ऑब्जेक्ट सेट किए गए किसी भी मान को बनाए रखता है, और पिछले मानों को रिलीज़ करता है जैसे उन्हें जाने दिया जाता है।
उदाहरण के लिए:
// The correct answer to both questions is objectively YES.
Question* myQuestion = [[Question alloc] init];
NSString* question1 = [[NSString alloc] initWithString:@"Is pizza tasty?"];
// question1 has retain count of 1, from the call to alloc
myQuestion.questionStr = question1;
// question1 now has a retain count of 2
NSString* question2 = [[NSString alloc] initWithString:@"Free iPhone?"];
myQuestion.questionStr = question2;
// question1 has a retain count of 1, and question2 has retain count of 2
तो questionStr
के लिए @property
घोषणा assign
बजाय किया गया था, तो सभी myQuestion.questionStr =
बयान किए गए परिवर्तन सभी पर बनाए रखने के लिए मायने रखता है के लिए बनाया नहीं होता।
आप read a little more about properties here कर सकते हैं।
क्या IBOutlet
और IBAction
कर ये मूल रूप से कोई-op शब्द जो एक तरह से इंटरफ़ेस बिल्डर जो हेडर फाइल के टुकड़े पर ध्यान देना बताने के लिए के रूप में केवल अभिनय कर रहे हैं। IBOutlet
संकलक एक खाली स्ट्रिंग बन जाता है जब संकलक इसे देखता है, और IBAction
void
वापसी मान बन जाता है। हमें इंटरफ़ेस बिल्डर के साथ काम करने की आवश्यकता है, हालांकि, वे महत्वपूर्ण हैं - बस संकलक के लिए नहीं।
सी structs पर त्वरित टिप्पणी और बनाम डॉट नोटेशन
तीर वैसे, एक ऑब्जेक्टिव-सी वस्तु का डेटा हिस्सा बहुत एक सी struct के समान है। आप एक सी struct करने के लिए एक सूचक है, तो आप इस तरह, struct के एक विशिष्ट भाग का उल्लेख करने के लिए तीर अंकन ->
उपयोग कर सकते हैं:
struct MyStructType {
int i;
BOOL b;
};
struct MyStructType* myStruct;
myStruct->i = 3;
myStruct->b = TRUE; // or YES in Objective-C.
यह वही वाक्य रचना ऑब्जेक्टिव-सी में एक ही तरह से काम करता है:
Question* question = [[Question alloc] init];
question->questionStr = @"Is this a long answer?"; // YES
लेकिन जब आप ऐसा करते हैं, तो नहीं डॉट नोटेशन के विपरीत, दृश्यों के पीछे विधि कॉल हो रहा है। डॉट नोटेशन के साथ, आप सेटर कॉल कर रहे हैं (या अगर कोई = है बाद में मनुष्य), और इन दो पंक्तियों में एक ही कर रहे हैं:
question.questionStr = @"Chocolate?";
[question setQuestionStr:@"Chocolate?"];
यह अक्सर एक अच्छा विचार के पक्ष में तीर अंकन से बचने के लिए है डॉट नोटेशन, चूंकि डॉट नोटेशन आपको वैध स्थिति को लागू करने देता है - उदाहरण के लिए, आपके क्लाइंट को पॉइंटर्स हमेशा बनाए रखा जाता है। आप अपने इंस्टेंस वैरिएबल को @private
के रूप में घोषित करके तीर नोटेशन का उपयोग करने से दूसरों को भी अस्वीकार कर सकते हैं; यदि आप इसके लिए @property
घोषित करते हैं, तो वे अभी भी गेटटर और सेटर का उपयोग कर सकते हैं।
@synthesize
क्या करता है अब, जब आप चारों ओर करने के लिए वास्तव में अपने वर्ग को लागू करने के लिए, @synthesize
का कहना है की तरह कुछ "यकीन है कि मनुष्य और सेटर इस संपत्ति के लिए लागू किया हो सकते हैं।" यह कहता है "इन दोनों को मेरे लिए लागू करें," क्योंकि संकलक पहले आपके स्वयं के कार्यान्वयन की जांच करने के लिए विनम्र है, और केवल आपके द्वारा छोड़े गए टुकड़ों को भरें। आपको @synthesize
का उपयोग करने की ज़रूरत नहीं है, भले ही आप @property
का उपयोग वज़ू से करें - आप हमेशा अपने सेटर्स और गेटर्स के लिए अपने कार्यान्वयन प्रदान कर सकते हैं, अगर आप उस तरह की चीज में हैं।
आप शायद कि ऊपर Question
इंटरफ़ेस में देखा वहाँ एक संपत्ति जो एक उदाहरण चर (numWrongAnswers
) है, जो ठीक है क्योंकि आप बस तरीकों घोषणा कर रहे है नहीं है। यहाँ उदाहरण के कोड में, आप देख सकते हैं कि यह कैसे वास्तव में काम करता है:
@implementation Question
@synthesize questionStr, numTimesAsked, numCorrectAnswers;
- (void) setNumCorrectAnswers: (int) newCorrectAnswers {
// We assume the # increases, and represents new answers.
int numNew = newCorrectAnswers - numCorrectAnswers;
numTimesAsked += numNew;
numCorrectAnswers = newCorrectAnswers;
}
- (int) numWrongAnswers {
return numTimesAsked - numCorrectAnswers;
}
- (void) setNumWrongAnswers: (int) newWrongAnswers {
int numNew = newWrongAnswers - self.numWrongAnswers;
numTimesAsked += numNew;
}
- (void) addAnswerWithTruthValue: (BOOL) isCorrect {
if (isCorrect) {
self.numCorrectAnswers++;
} else {
self.numWrongAnswers++;
}
}
@end
एक बात है कि यहाँ क्या हो रहा है हम एक उदाहरण चर numWrongAnswers
कहा जाता है, जो अनावश्यक जानकारी हो सकता है अगर हम इसे कक्षा में संग्रहीत faking रहे हैं। चूंकि हम जानते हैं कि numWrongAnswers
+ numCorrectAnswers
= numTimesAsked
हर समय, हमें केवल इन तीन डेटा बिंदुओं में से किसी एक को स्टोर करने की आवश्यकता है, और हम हमेशा उन दो मूल्यों का उपयोग करके दूसरे के संदर्भ में सोच सकते हैं जिन्हें हम जानते हैं। यहां बिंदु यह समझना है कि @property
घोषणा वास्तव में केवल एक सेटटर और गेटर विधि घोषित करने के बारे में है, जो आम तौर पर एक वास्तविक आवृत्ति चर के अनुरूप होती है - लेकिन हमेशा नहीं। @synthesize
डिफ़ॉल्ट रूप से कीवर्ड एक वास्तविक आवृत्ति चर के अनुरूप है, ताकि संकलक के लिए आपके लिए कार्यान्वयन भरना आसान हो।
कारण अलग .h
और .m
फ़ाइलों
वैसे है, एक फ़ाइल (.h
हेडर फाइल) और एक अन्य (.m
या तरीकों फ़ाइल) में उनके कार्यान्वयन को परिभाषित करने में घोषित करने के तरीकों के पूरे मुद्दे कोड को कम करने में मदद करने के लिए है। उदाहरण के लिए, यदि आप अपनी प्रोजेक्ट में केवल .m
फ़ाइल अपडेट करते हैं, तो आपको अन्य .m
फ़ाइलों को पुन: संकलित करने की आवश्यकता नहीं है, क्योंकि उनका ऑब्जेक्ट कोड वही रहेगा - यह समय बचाता है। एक अन्य लाभ यह है कि आप एक लाइब्रेरी का उपयोग कर सकते हैं जिसमें केवल हेडर फाइलें और प्री-कंपाइल ऑब्जेक्ट कोड, या यहां तक कि डायनामिक लाइब्रेरीज़ भी शामिल हैं जहां आपको हेडर फ़ाइल की आवश्यकता होती है ताकि संकलक को पता चल सके कि कौन से तरीके मौजूद हैं, लेकिन उन विधियों में भी लिंक नहीं है आपके निष्पादन योग्य फ़ाइल के साथ। जब आप पहली बार कोडिंग शुरू करते हैं तो इन फायदों की सराहना करना मुश्किल होता है, लेकिन केवल थोड़ी देर बाद लॉजिकल ब्रेकडाउन और कार्यान्वयन का समावेशन उपयोगी हो जाता है।
मुझे उम्मीद है कि यह सहायक है!
का उपयोग करके केवल गुणों का उपयोग किया जाता है, एक समग्र प्रभावशाली पोस्ट की कुछ रचनात्मक आलोचना: (1) एनएसएसटींग गुणों को वास्तव में बनाए रखने के रूप में चिह्नित किया जाना चाहिए, (2) मुझे लगता है कि आप क्यों चाहते हैं .m और .h फ़ाइलों की आवश्यकता नहीं है इस संदर्भ में क्या चल रहा है इसके साथ रहना बेहतर है। मुझे पसंद आया कि आपने आईबीओलेट और आईबीएक्शन के उद्देश्य के बारे में बात की थी। –
असल में, एनएसएसटींग गुणों को कॉपी के रूप में चिह्नित किया जाना चाहिए। – bbum
ओह, मेरा यही मतलब था - उदाहरण कोड पहले से ही इसे बनाए रखने के रूप में है ...मेरी गलती को सुधारने के लिए धन्यवाद! –