दोनों वास्तव में काफी नाजुक हैं और बिल्कुल समान नहीं हैं, इस पर निर्भर करता है कि कक्षा के कौन से ग्राहक कर रहे हैं। उन्हें समान बनाना काफी आसान है - नीचे देखें - लेकिन इसे कम नाजुक बनाना कठिन है। आलसी प्रारंभिकता की कीमत (और मैं आम तौर पर इस फैशन में आलसी शुरुआत से बचने की कोशिश क्यों करता हूं, समग्र अनुप्रयोग राज्य प्रबंधन के एक हिस्से के रूप में उपप्रणाली के प्रारंभिक व्यवहार का इलाज करना पसंद करता हूं)।
# 1 के साथ, आप सेटर से परहेज कर रहे हैं और इस प्रकार, परिवर्तन को देखते हुए कुछ भी बदलाव को नहीं देख पाएगा। "देखकर", मैं विशेष रूप से कुंजी-मूल्य अवलोकन (कोको बाइंडिंग समेत) का जिक्र कर रहा हूं, जो यूआई को स्वचालित रूप से अपडेट करने के लिए केवीओ का उपयोग करता है)।
# 2 के साथ, आप परिवर्तन अधिसूचना को ट्रिगर करेंगे, यूआई को अपडेट करेंगे और अन्यथा ठीक उसी तरह जैसे कि सेटटर को बुलाया गया था।
दोनों मामलों में, यदि ऑब्जेक्ट की शुरुआत गेटटर को कॉल करती है तो आपके पास अनंत रिकर्सन की संभावना होती है। इसमें कोई भी पर्यवेक्षक परिवर्तन अधिसूचना के हिस्से के रूप में पुराने मूल्य के लिए पूछता है। ऐसा मत करो।
यदि आप किसी भी विधि का उपयोग करने जा रहे हैं, तो सावधानीपूर्वक परिणामों पर विचार करें। एक में ऐप को असंगत स्थिति में छोड़ने की क्षमता है क्योंकि किसी संपत्ति के राज्य में परिवर्तन को सूचित नहीं किया गया है और दूसरे के पास डेडलॉक की संभावना है।
पूरी तरह से इस मुद्दे से बचने के लिए बेहतर है। निचे देखो।
पर विचार करें पर (कचरा संग्रहण, मानक कोको कमांड लाइन टूल:।
#import <Foundation/Foundation.h>
@interface Foo : NSObject
{
NSString *bar;
}
@property(nonatomic, retain) NSString *bar;
@end
@implementation Foo
- (NSString *) bar
{
if (!bar) {
NSLog(@"[%@ %@] lazy setting", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
[self willChangeValueForKey: @"bar"];
bar = @"lazy value";
[self didChangeValueForKey: @"bar"];
}
return bar;
}
- (void) setBar: (NSString *) aString
{
NSLog(@"[%@ %@] setting value %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), aString);
bar = aString;
}
@end
@interface Bar:NSObject
@end
@implementation Bar
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
{
NSLog(@"[%@ %@] %@ changed\n\tchange:%@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), keyPath, change);
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Foo *foo = [Foo new];
Bar *observer = [Bar new];
CFRetain(observer);
[foo addObserver:observer forKeyPath:@"bar"
options: NSKeyValueObservingOptionPrior | NSKeyValueObservingOptionNew
context:NULL];
foo.bar;
foo.bar = @"baz";
CFRelease(observer);
[pool drain];
return 0;
}
यह लटका नहीं करता है यह निसृत:
2010-09-15 12:29:18.377 foobar[27795:903] [Foo bar] lazy setting
2010-09-15 12:29:18.396 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
notificationIsPrior = 1;
}
2010-09-15 12:29:18.397 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
new = "lazy value";
}
2010-09-15 12:29:18.400 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
notificationIsPrior = 1;
}
2010-09-15 12:29:18.400 foobar[27795:903] [Foo setBar:] setting value baz
2010-09-15 12:29:18.401 foobar[27795:903] [Bar observeValueForKeyPath:ofObject:change:context:] bar changed
change:{
kind = 1;
new = baz;
}
आप सूची में NSKeyValueObservingOptionOld
जोड़ने के लिए थे, तो अवलोकन के विकल्पों के लिए, यह बहुत लटका है।
एक टिप्पणी मैंने पहले बनाया करने के लिए वापस हो रही है; सबसे अच्छा समाधान आपके गेटर/सेटर के हिस्से के रूप में आलसी प्रारंभिक नहीं है। यह बहुत अच्छा दागदार है। आप अपने ऑब्जेक्ट ग्राफ़ स्टेटस को उच्च स्तर पर प्रबंधित करने से कहीं बेहतर हैं और इसके एक हिस्से के रूप में, एक राज्य संक्रमण है जो मूल रूप से "यो! मैं इस सबसिस्टम का उपयोग करने जा रहा हूं! खराब लड़का! " वह आलसी प्रारंभिक करता है।
यह मेरी राय में सही जवाब है। –
वास्तव में ऑब्जेक्ट को आलसी शुरू करते समय देखने के लिए कोई बदलाव नहीं है, इसलिए यह उत्तर ** ** सही नहीं है। – Sven
हू? चाहे वह आलसी शुरू हो या न हो, अप्रासंगिक है। अगर मैंने 'ऑब्जेक्ट' के केवीओ अवलोकन को स्थापित किया है और गेटटर में 'self.theObject = ...' रखा है, तो केवी अवलोकन ** ** आग लगेगा। "आलसी प्रारंभिक" सिर्फ एक पैटर्न के लिए एक नाम है; न तो संकलक और न ही रनटाइम इसके बारे में कुछ भी जानता है। – bbum