2011-07-20 5 views
5

के बाद एक दृश्य नियंत्रक के कार्यान्वयन से एक टुकड़ा है:समझौता ऑब्जेक्टिव-सी गुंजाइश मुद्दा

- (void)myOtherAwesomeMethod 
{ 
    [self myAwesomeMethod]; // Compile ERROR here: Receiver type for instance message does not declare a method with selector 
} 

- (void)myAwesomeMethod 
{ 
    NSLog(@"%@", @"Calling my awesome method..."); 
} 

- (void)viewDidLoad 
{ 
    [self myAwesomeMethod]; 

    [self myOtherAwesomeMethod]; 
} 

मैं myAwesomeMethod विधि मेरी हेडर फाइल में घोषित की जरूरत नहीं है, लेकिन क्यों कि मैं viewDidLoad में myAwesomeMethod कॉल कर सकते हैं यह है, लेकिन myOtherAwesomeMethod में नहीं?

मुझे पता है कि इस त्रुटि का समाधान मेरी हेडर फ़ाइल में विधि घोषित करना है, लेकिन मैं समझना चाहता हूं कि यह क्यों हो रहा है।

+0

आप कहां कह रहे हैं '-myOtherAwesomeMethod'? – vikingosegundo

+1

मेरा मानना ​​है कि यह केवल चेतावनी है, त्रुटि नहीं? – tia

+0

इसके अलावा आप केवल स्ट्रिंग को NSLog कर सकते हैं, इसे प्रारूपित करने की आवश्यकता नहीं है। –

उत्तर

11

सी में, नियम है: आपको इसका उपयोग करने से पहले इसे घोषित करना होगा।

फ़ाइलों को ऊपर से संकलित किया गया है। तो यहां आपके कोड में क्या हो रहा है:

  1. कंपाइलर आपकी कक्षा के लिए @interface घोषणा पढ़ता है। चूंकि आप कहते हैं कि हेडर फ़ाइल में न तो विधि घोषित की गई है, न ही अभी तक प्रतीक तालिका में हैं।

    आपका प्रतीक तालिका में शामिल है: अभी तक

  2. कुछ भी नहीं संकलक पढ़ता myAwesomeMethod के लिए विधि परिभाषा। आपने इसे अभी तक घोषित नहीं किया है, इसलिए यह प्रतीक तालिका में जोड़ा जाता है। विधि के शरीर में NSLog पर कॉल है, जिसे ऐप्पल द्वारा प्रदान किए गए शीर्षलेख में बहुत पहले घोषित किया गया था।

    आपका प्रतीक तालिका में शामिल हैं: myAwesomeMethod

  3. संकलक पढ़ता viewDidLoad के लिए विधि परिभाषा; यह वास्तव में एक सुपरक्लास की हेडर फ़ाइल में घोषित किया गया था। विधि के शरीर में myAwesomeMethod पर कॉल है, जो पाया गया था! इसमें myOtherAwesomeMethod पर कॉल भी शामिल है। कभी नहीं सुना!

    अब, यह कोई त्रुटि नहीं है, क्योंकि यह अभी भी कॉल करने के लिए कोड उत्पन्न कर सकता है। यह तर्क प्रकारों का अनुमान लगा सकता है कि आप इसका उपयोग कैसे करते हैं (इस मामले में, कोई तर्क नहीं)। यह रिटर्न प्रकार के बारे में सुनिश्चित नहीं हो सकता है, हालांकि (सिर्फ इसलिए कि आप रिटर्न वैल्यू का उपयोग नहीं करते हैं इसका मतलब यह नहीं है कि कोई नहीं था)। तो यह धारणा पर आता है कि कॉल id देता है और एक चेतावनी उत्पन्न करता है।

    आपका प्रतीक तालिका में शामिल हैं: myAwesomeMethod

  4. अंत में, संकलक myOtherAwesomeMethod के लिए विधि परिभाषा पढ़ता है। यह प्रतीक तालिका में जोड़ा जाता है। यह शरीर को संकलित करता है, जिसमें तालिका में myAwesomeMethod पर कॉल होता है। अंत भला तो सब भला।

    फ़ाइल के अंत में, अपने प्रतीक तालिका में शामिल हैं: myAwesomeMethod, myOtherAwesomeMethod

आप जावा की तरह एक भाषा से आ रहे हैं, यह, मूर्ख लग सकता है लेकिन यह है कि क्योंकि जावा सी की तुलना में अलग काम करता है जावा में, स्रोत कोड संकलित और एक चरण में जुड़ा हुआ है; आप किसी वर्ग को संकलित नहीं कर सकते जो किसी अन्य वर्ग को स्रोत कोड या कक्षा फ़ाइलों के बिना संदर्भित करता है। यह एक परेशानी हो सकती है, लेकिन दूसरी ओर, आपको परिभाषाओं के अलावा घोषणाओं की आवश्यकता नहीं है।

सी में, संकलन और लिंकिंग विभिन्न चरणों हैं।कंपाइलर केवल ऑब्जेक्ट कोड उत्पन्न करता है जो प्रतीकों को संदर्भित करता है जिन्हें कहीं और परिभाषित किया जा सकता है; यह सुनिश्चित करने के लिए घोषणाओं का उपयोग करता है कि यह सही कोड उत्पन्न करता है। लिंकर उन सभी प्रतीकों से मेल खाने के लिए जिम्मेदार है जो अन्य पुस्तकालयों, स्थिर या गतिशील में परिभाषाओं के साथ हैं।

उद्देश्य-सी में, लिंकर वास्तव में उद्देश्य-सी संदेशों के बारे में नहीं जानता/परवाह नहीं करता है, क्योंकि संकलन समय/लिंक-टाइम पर जानने का कोई तरीका नहीं है कि कोई ऑब्जेक्ट किसी संदेश का जवाब दे सकता है या नहीं। तो यह रनटाइम पर हिरण पास करता है, जो एक अपवाद फेंकता है अगर आप इसे विधि परिभाषा के बिना दूर ले जाते हैं।

+0

धन्यवाद @benzado, मुझे पता चला कि आदेश अपराधी है। मुझे इसे कहीं भी घोषित करने की ज़रूरत नहीं है, लेकिन इसे परिभाषित करने से पहले विधि परिभाषा को आने की आवश्यकता है। मैं भयानक स्पष्टीकरण के लिए वैसे भी आपका जवाब स्वीकार कर रहा हूं। – pixelfreak

0

मैं मानता हूं कि मुझे यकीन नहीं है कि यह दृश्य में क्यों काम करता है।

ध्यान दें कि त्रुटि कहती है कि "विधि को अस्वीकार नहीं किया गया"। यह एक संकेत है कि यह एक घोषणा की तलाश में है (आमतौर पर एक शीर्षलेख में) .. यानी एक समारोह प्रोटोटाइप।

हालांकि, ऐसा कुछ भी नहीं है जो कहता है कि घोषणा एक शीर्षलेख में होनी चाहिए। यदि आप फ़ाइल के बाहर से उस विधि को कॉल नहीं करने जा रहे हैं तो आप इसे कार्यान्वयन फ़ाइल के शीर्ष पर रख सकते हैं।

संबंधित मुद्दे