2009-10-01 11 views
5

के साथ लेखन की अनुमति क्यों देती है, मैं "मैक ओएस एक्स के लिए प्रोग्रामिंग" में "कुंजी मूल्य कोडिंग" अध्याय के माध्यम से काम कर रहा हूं। मैंने एक स्लाइडर और एक लेबल के साथ एक इंटरफेस बनाया है, दोनों फिडो, एक int से बंधे हैं। अगर मैंने फिडो के लिए संपत्ति को केवल पढ़ने के लिए सेट किया है, तो स्लाइडर को ले जाने से लेबल को इसके मान को बदलने का कारण बनता है। मैंने माना था कि मुझे इसके लिए कुछ प्रकार की त्रुटि मिल जाएगी। अगर संपत्ति केवल पढ़ने योग्य है, तो स्लाइडर अभी भी संपत्ति को कैसे लिख सकता है? मैंने सोचा कि इसमें कोई सेटर्स नहीं बनाया जाएगा, और केवीसी काम नहीं करेगा। धन्यवाद।एक रीडोनली प्रॉपर्टी अभी भी केवीसी

यहाँ कोड मैं का उपयोग कर रहा है:

#import <Cocoa/Cocoa.h> 

@interface AppController : NSObject 
{ 
    int fido; 
} 

@property (readonly, assign) int fido; 

@end 

#import "AppController.h" 

@implementation AppController 

@synthesize fido; 

- (id)init 
{ 
    [super init]; 
    [self setValue:[NSNumber numberWithInt:5] forKey:@"fido"]; 
    NSNumber *n = [self valueForKey:@"fido"]; 
    NSLog(@"fido = %@", n); 
    return self; 
} 
@end 

alt text http://idisk.me.com/nevan/Public/Pictures/Skitch/Window-20091001-174352.png

उत्तर

16

AppController.h:

@interface AppController : NSObject 
{ 
     int fido; 
} 

@property (readonly, assign) int fido; 
@end 

आयात "AppController.h"

@implementation AppController 
@synthesize fido; 
... 
@end 

इस बिंदु पर, आप घोषणा की है AppController एक -fido विधि है और आपको लगता है कि विधि संश्लेषित है। -setFido: विधि नहीं है। तो, निम्नलिखित "काम" क्यों करता है?

- (id)init 
{ 
     if (self=[super init]) { 
      [self setValue:[NSNumber numberWithInt:5] forKey:@"fido"]; 
      NSNumber *n = [self valueForKey:@"fido"]; 
      NSLog(@"fido = %@", n); 
     } 
     return self; 
} 

:

यह काम करता है क्योंकि KVC सेट या मान प्राप्त करने हेतु अनुमानी इस प्रकार है (BTW मैं अपने -init सही पैटर्न लागू करने के लिए तय हो गई)। -setValue:forKey: करने के लिए कॉल पहले -setFoo: के लिए लग रहा है। यदि नहीं मिला, तो यह आवृत्ति चर foo देखता है और इसे सीधे सेट करता है।

ध्यान दें कि यदि आप उदाहरण fido_fido चर बदलने के लिए, सेट काम करेंगे, लेकिन के रूप में यह संश्लेषित प्रणाली को बुलाती है (के बाद से मैं 64 बिट पर हूँ valueForKey 0 वापस आ जाएगी, @synthesize एक fido उदाहरण चर का संश्लेषण उलझन में, मुझे पता है।)।

यदि आप अपने ivar का नाम bar पर बदलना चाहते हैं और फिर @synthesize foo=bar; का उपयोग करें, तो कोड रनटाइम पर विफल हो जाएगा।

आप देखेंगे:

2009-10-01 08:59:58.081 dfkjdfkjfjkfd[24099:903] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<AppController 0x20000e700> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key fido.' 
*** Call stack at first throw: 
(
    0 CoreFoundation      0x00007fff85b055a4 __exceptionPreprocess + 180 
    1 libobjc.A.dylib      0x00007fff85c5a0f3 objc_exception_throw + 45 
    2 CoreFoundation      0x00007fff85b5caf9 -[NSException raise] + 9 
    3 Foundation       0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434 
(
    0 CoreFoundation      0x00007fff85b055a4 __exceptionPreprocess + 180 
    1 libobjc.A.dylib      0x00007fff85c5a0f3 objc_exception_throw + 45 
    2 CoreFoundation      0x00007fff85b5caf9 -[NSException raise] + 9 
    3 Foundation       0x00007fff814e14f5 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 434 
    4 dfkjdfkjfjkfd      0x0000000100000d96 -[AppController init] + 130 
+9

आप + (BOOL) का उपयोग भी कर सकते हैं प्रवेश Variables प्रत्यक्ष रूप से {वापसी नहीं; } इस केवीसी व्यवहार को खत्म करने के लिए – sbooth

+0

अच्छा बिंदु और अंदर आने के लिए एक अच्छी आदत। धन्यवाद! – bbum

+0

ग्रेट उत्तर, धन्यवाद। कारण मैं इस सवाल से पूछ रहा था कि अध्याय के मुख्य बिंदुओं में से एक यह है कि केवीसी सेटर्स और गेटर्स का उपयोग करता है। मुझे लगता है कि वे एकमात्र तरीका काम करते थे। इनिट शैली वह शैली है जिसका वह पुस्तक में उपयोग करता है। वह कहता है कि वह कक्षाएं जो उप-वर्ग कभी शून्य नहीं लौटती हैं, इसलिए वह सादगी के लिए चेक छोड़ देता है। –

1

केवल पढ़ने के लिए संपत्ति होने कि संकलक उत्पन्न नहीं करेगा आप उस प्रॉपर्टी के लिए सेटर का मतलब है। केवीओ/केवीसी के माध्यम से इसे लिखना अभी भी कानूनी है।

+1

यहाँ क्या हो रहा है नहीं है यही कारण है कि। – bbum

1

कंपाइलर निर्देश @property और @synthesize प्रश्न में चर को प्राप्त करने और सेट करने के तरीकों को बनाने के लिए केवल लघुरूप तरीके हैं।

निर्मित सेटर विधि का नाम setFido: है, और गेटर विधि का नाम सिर्फ fido है।

जब आप केवल पढ़ने के लिए निर्दिष्ट करते हैं, तो मुझे विश्वास है कि बस संकलक को सेटर विधि बनाने के लिए नहीं, बल्कि केवल गेटर को बताता है। यह वैरिएबल को अन्य माध्यमों से सेट करने के तरीके में किसी प्रकार का बाधा नहीं डालता है।

(आशा मैं वह सब सही मिल गया है गुड लक।!)

+0

अधिक या कम सही।विशिष्टताओं के लिए मेरा जवाब देखें। – bbum