2012-07-18 12 views
51

ObjectProperties.hऑब्जेक्टिव-सी प्रोटोकॉल आगे घोषणाएं

@protocol ObjectProperties <NSObject> 

@property (strong, nonatomic) NSString *name; 
@property (strong, nonatomic) NSDate *date; 
@property (assign, nonatomic) int64_t index; 

@end 

ClassA.h

#import <Foundation/Foundation.h> 

@protocol ObjectProperties; 

@interface ClassA : NSObject <ObjectProperties> 

- (void)specialSauce; 

@end; 

ManagedClassA.h

#import <CoreData/CoreData.h> 

@protocol ObjectProperties; 

@interface ManagedClassA : NSManagedObject <ObjectProperties> 

- (void)doSomething; 

@end; 

उपरोक्त कोड उदाहरण से, मैंने कोर डेटा ऑब्जेक्ट्स के साथ-साथ सादे ओल 'वेनिला ऑब्जेक्ट्स दोनों के साथ एक .h फ़ाइल में प्रोटोकॉल को परिभाषित किया है। यह वर्गों को अनुरूप बनाने के लिए "शोर" जैसा लगता है # प्रोटोकॉल को उनके शीर्षलेख में आयात करें; जैसा कि मैंने ऊपर दिखाया है, कार्यान्वयन फ़ाइल में प्रोटोकॉल & आयात को घोषित करने के लिए क्लीनर होगा। जब यह इस तरह से कर रही है हालांकि, Xcode एक चेतावनी फेंकता है:

Cannot find protocol definition for 'ObjectProperties'

कोड संकलित, और ज्यादातर काम करता है। मैं ज्यादातर इसलिए कहता हूं क्योंकि कोर डेटा के साथ स्केलर संपत्ति के लिए गेटर्स/सेटर्स को गतिशील रूप से बनाने की कोशिश कर रहे कुछ डेटा हैं, लेकिन मुझे लगता है कि शायद ऐसा इसलिए है क्योंकि मैंने एज एज केस मारा है।

बेशक, क्लास हेडर में प्रोटोकॉल हेडर आयात करने के लिए सबसे स्पष्ट काम है।

यदि मेरी समझ सही है (और मेरा ज्ञान हाल ही में अधिग्रहित है, और इसलिए यह पूरी तरह से संभव है कि मैं गलत हूं), अगर मैं अपने वर्ग शीर्षकों में प्रोटोकॉल आयात करता हूं और प्रोटोकॉल में बदलाव करता हूं, तो बाद में मेरी कक्षाओं को आयात करने वाली फ़ाइलों को फिर से सम्मिलित करना होगा।

इस प्रकार की समस्या को हल करने का सही तरीका क्या है?

+0

मुझे एक समान समस्या है लेकिन स्विफ्ट प्रोटोकॉल के साथ। – Alper

उत्तर

93

आप आगे एक सुपर क्लास या एक प्रोटोकॉल है कि यह के अनुरूप की घोषणा नहीं कर सकते हैं। उन मामलों में, आपको हेडर शामिल करना होगा।ऐसा इसलिए है क्योंकि (सुपरक्लास के मामले में) सुपरक्लास के आवृत्ति चर और विधियां आपकी कक्षा का हिस्सा बनती हैं; या (प्रोटोकॉल के मामले में) प्रोटोकॉल के तरीकों को स्पष्ट रूप से घोषित करने की आवश्यकता के बिना, आपकी कक्षा में घोषित विधियां बन जाती हैं। (यानी अब अन्य लोग जो आपकी कक्षा के शीर्षलेख को शामिल करते हैं, देखेंगे कि आपकी कक्षा उन तरीकों की घोषणा करती है, जैसे कि आपने उन्हें स्वयं घोषित किया है।) एकमात्र तरीका यह संभव हो सकता है कि यदि वे पहले से ही इस दायरे में परिभाषित हैं, यानी उनके शीर्षलेख आयात किए जाते हैं ।

#import <SomeClass.h> 
#import <SomeProtocol.h> // these two must be imported 

@interface MyClass : SomeClass <SomeProtocol> 
@end 

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

@class SomeClass; 
@protocol SomeProtocol; // you can forward-declare these 

@interface MyClass { 
    SomeClass *var1; 
    id<SomeProtocol> var2; 
} 
@end 
4

हाँ आप सही हैं कि सभी फ़ाइलों को पुन: संकलित करने की आवश्यकता होगी, लेकिन यह आवश्यक है। क्लास हेडर आयात करने वाली फ़ाइलें को प्रोटोकॉल से जुड़े तरीकों को जानने की आवश्यकता होती है। यदि आप उस परिभाषा को .m फ़ाइल में दूर करते हैं तो यह केवल एक फ़ाइल के लिए दृश्यमान होता है (क्योंकि .m फ़ाइलें कभी आयात नहीं होती हैं)। यह आगे की घोषणा कक्षाओं के समान नहीं है। यदि आप प्रोटोकॉल घोषित करते हैं, तो आपको इसे कहीं भी घोषित करना होगा जो आगे की घोषणा के समान क्षेत्र में दिखाई दे रहा है। मैं किसी भी उदाहरण के बारे में नहीं सोच सकता जहां यह एक ही फाइल में नहीं होता है।

एआरसी में यह एक त्रुटि है, क्योंकि एआरसी घोषित तरीकों की स्मृति प्रबंधन के बारे में पता करने की जरूरत है (वे, +1 उदाहरणों, आंतरिक संकेत वापसी करना आदि?)

2

MyClass.h में अपने वर्ग में घोषित करने से , आपको अपने सुपरक्लास के साथ-साथ MyClass.h फ़ाइल में अपनाए गए प्रोटोकॉल के लिए सभी शीर्षलेख फ़ाइलों को आयात करना होगा। उद्देश्य-सी में प्रोटोकॉल को एक प्रकार का विरासत माना जाता है।

आगे की घोषणा कक्षा के सदस्य घोषणा में आमतौर पर उपयोग की जाती है।

1

चूंकि आप प्रोटोकॉल के अनुरूप होने की घोषणा कर रहे हैं, तो आपको # प्रोटोकॉल वाले शीर्षलेख को आयात करना चाहिए।

यह एक सुपर क्लास #importing, बजाय आगे यह घोषित करने के समान ही है:

@class Foo; 

@interface Bar : Foo 
// Will get error: attempting to use the forward class 'Foo' as superclass of 'Bar' 
@end; 
संबंधित मुद्दे