10

ठीक से स्व-रिलीज करने वाली वस्तुओं को परिवर्तित करना ठीक है, इसलिए ऐप्पल ने हमें एआरसी लाया, जो कि महान है। एआरसी में अपना आवेदन दोबारा करने के बाद लगभग सबकुछ ठीक काम करता है और अब विकास और रखरखाव करना बहुत आसान है।एआरसी

एक ऐसी समस्या है जिसे मैं अभी भी समझ नहीं पा रहा हूं।

मेरा नौकरी प्रबंधन कार्यक्रम प्रस्तावों, आदेशों और उनके स्वयं के विंडोज़ पर विभिन्न विवरणों की जानकारी दिखाता है। तो मैं एक विशेष वर्ग जहां WindowControllers आवंटित हो जाता है और initWithWindowNibName के साथ शुरू और फिर खिड़की showWindow साथ दिखाया गया है है:

DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:@"ThePorposalWindow"]; 
[proposalWindowController showWindow:nil]; 

एआरसी से पहले WindowController का उदाहरण documentation में दिखाया गया है की तरह रिलीज किया:

- (void)windowWillClose:(NSNotification *)notification 
{ 
    [self autorelease]; 
} 

लेकिन अब एआरसी के साथ यह अब संभव नहीं है और इससे भी बदतर हो जाता है, मेरी विशेष कक्षा में जहां विंडोकंट्रोलर आवंटित और शुरू किया गया है, वही विंडो नियंत्रक एआरसी द्वारा जारी किया जाता है क्योंकि विंडो नियंत्रक के लिए कोई सूचक नहीं है।

मेरा विचार एक mutuable सरणी में windowController कॉपी करने के लिए किया गया था:

[proposalWindowArray addObject:proposalWindowController]; 
[[proposalWindowArray lastObject] showWindow:nil]; 

और windowControllers प्रतिनिधि विधि windowWillClose मैं अपने विशेष वर्ग के लिए एक सूचना पोस्ट में:

- (void)windowWillClose:(NSNotification *)notification 
{ 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ProposalWindowWillClose" object:[[self window] windowController] userInfo:nil]; 
} 

मेरी विशेष वर्ग में मैं अधिसूचना सुनता हूं और ऑब्जेक्ट को सरणी से हटा देता हूं:

- (void) proposalWindowWasClosed: (NSNotification *) notification 
{ 
    [proposalWindowArray removeObjectIdenticalTo:[notification object]]; 
} 

यह काम करता है, लेकिन मुझे अभी भी विश्वास नहीं है कि यह सही तरीका है।

क्या किसी को भी एक ही समस्या है या इसे बेहतर बनाने के लिए एक युक्ति है?

+0

आपका नया तरीका मूल रूप से सही है। एआरसी के साथ, कंपाइलर को बनाए रखने/रिलीज कॉल को सही तरीके से ट्रैक करने में सक्षम होने के लिए आपको ऑब्जेक्ट्स के स्पष्ट संदर्भों को रखने की आवश्यकता है। असल में, मुझे लगता है कि आपको सामान्य रूप से कॉलबैक विधियों में 'रिलीज' को कॉल करने जैसी चाल से बचना चाहिए, चाहे आप एआरसी का उपयोग कर रहे हों या नहीं। –

+1

@RobKeniger: इसके बजाय आप क्या सुझाव देते हैं? कल्पना कीजिए कि हम ऐप प्रतिनिधि में हैं जो आगे/विंडो नियंत्रकों को देखने के लिए क्रियाएं प्राप्त करते हैं और आमतौर पर कई अलग-अलग नियंत्रक शामिल होते हैं। प्रत्येक के लिए एक संपत्ति बनाना अनावश्यक गन्दा लगता है। –

उत्तर

10

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

उस ने कहा, कभी-कभी आत्म-स्वामित्व कम से कम सुविधाजनक होता है, और दुनिया के सबसे खराब नहीं। तो स्वयं का केवल अंतर यह है कि आपको रिसाव और ओवर-रिलीज से मेल खाने के बजाय स्पष्ट रूप से ऐसा करने की आवश्यकता है (जो आपका पुराना कोड कर रहा था)।

एक निजी strong संपत्ति बनाएं। इसे self असाइन करें। इससे एक बरकरार लूप बन जाएगा जो आपको तब तक रखेगा जब तक कि आप संपत्ति को nil पर सेट न करें।

+0

तो आपका उत्तर आपकी कक्षा में विंडो नियंत्रक उप-वर्गों की एक सरणी रखना है जो प्रतिनिधि के रूप में कार्य करता है और खिड़की नियंत्रक की खिड़की WillClose विधि में कहा जाता है? –

+3

सिस्टम के आधार पर, मेरे पास अक्सर केंद्रीय 'विंडोमेनगर' सिंगलटन होता है और इसे 'NSWindowWillCloseNotification' देखने देता है, लेकिन कभी-कभी मैं प्रतिनिधिमंडल का उपयोग करता हूं जैसा कि आप कहते हैं। इस पर निर्भर करता है कि इसे कैसे एकीकृत किया जाना चाहिए। WindowManager आमतौर पर सिस्टम में सभी विंडो नियंत्रक का मालिक है। यही वह डिज़ाइन है जिसे मैं आमतौर पर ढूंढता हूं जब तक मैं कर रहा हूं। –

+0

रोब: इस विषय पर बहुत अधिक शोध करने के बाद (आईट्यून्स यू में पाए गए पॉल हेगार्टी से "आईपैड और आईफोन ऐप डेवलपमेंट" पाठ्यक्रम के माध्यम से काम कर रहे हैं, जिसे मैं अत्यधिक अनुकरण कर सकता हूं) मैं आपका अंतिम उत्तर स्वीकार करता हूं। मैंने इसे अभी किया है ('NSWindowWillCloseNotification' देख रहा है) और यह सबसे सुरुचिपूर्ण और उचित तरीका प्रतीत होता है। तो सभी को धन्यवाद। – archibaldtuttle

0

हैक के बिना, किसी ऑब्जेक्ट को किसी अन्य ऑब्जेक्ट में इसके मजबूत संदर्भ के अलावा किसी ऑब्जेक्ट को बनाए रखने के लिए कोई शानदार तरीका नहीं है। उदाहरण के लिए, आप एक स्थिर NSMutableArray/NSMutableSet रख सकते हैं, वहां अपना कंट्रोलर जोड़ें, और इसे windowsWillClose: में हटा दें। अधिसूचना पोस्ट करने से यह छोटा होगा। इसे पुन: प्रयोज्य बनाने के लिए, WindowControllerRegistry सिंगलटन को सरणी के साथ बनाएं, जहां आप इस तरह के नियंत्रक जोड़ते हैं, और जो स्वचालित रूप से NSWindowWillCloseNotification सुनेंगे और उन्हें अपने सरणी से हटा देंगे जिससे स्वामित्व जारी किया जा सकेगा।

एक त्वरित समाधान के रूप में आप non-ARC file से retain/autorelease कॉल प्रदर्शन कर सकता है:

my_retain(self); 
my_autorelease(self); 

// ArcDisabled.mm 
void my_retain(id obj) { [obj retain]; } 
void my_autorelease(id obj) { [obj autorelease]; } 
+0

धन्यवाद हम्सटरजिन, जो शायद काम करेगा। लेकिन मैं थोड़ा और सुरुचिपूर्ण समाधान की तलाश में हूं। बनाए रखने और रिहाई के बिना समाधान होना चाहिए। अन्यथा मुझे एआरसी में स्विच करने की ज़रूरत नहीं थी। – archibaldtuttle

+0

एआरसी एक कंपाइलर फ़ंक्शन को बनाए/रिलीज़ करता है। उन्हें इस तरह से कॉल करना एआरसी के तहत अनिर्धारित संकलक व्यवहार है, और कुछ भी कर सकता है। यह रिसाव, काम, दुर्घटना, कभी-कभी या हमेशा हो सकता है। कल्पना से, यह आ सकता है और अपने कुत्ते को लात मार सकता है। कंपाइलर में ऑप्टिमाइज़ेशन होते हैं जो अनावश्यक बनाए रखने और रिलीज़ होने के बाद रिलीज़ होते हैं। एआरसी कभी-कभी "झुकता" रखता है और रिहा करता है। कंपाइलर अनुकूलित करने के तरीके के आधार पर आपका दृष्टिकोण सिस्टम को असंतुलित कर सकता है। अपरिभाषित व्यवहार पर अधिक: http://blog.regehr.org/archives/213 एआरसी अनुकूलन पर अधिक: http://bit.ly/friday-qa-2011-09-30 –

+0

@RobNapier चाल गंदे है और नहीं चाहिए इस्तेमाल किया जाए, लेकिन आपको ऐसा क्यों लगता है कि यह अपरिभाषित व्यवहार है? एआरसी गतिशील प्रेषण रद्द नहीं करता है। – hamstergene

0

मुझे लगता है कि अपने वैकल्पिक दृष्टिकोण सही होना चाहिए, लेकिन मुझे नहीं लगता कि आप दूसरी सूचना की आवश्यकता है। आप ऐसा करने में सक्षम होना चाहिए:

- (void)windowWillClose:(NSNotification *)notification 
{ 
    [proposalWindowArray removeObjectIdenticalTo:self]; 
} 

मान लिया जाये कि "proposalWindowArray" एक स्थिर NSMutableArray है।

+0

दुर्भाग्यवश प्रस्तावविंडोएरे मेरे विशेष श्रेणी के विवरण की एक निजी संपत्ति है विन्डो कंट्रोलर जो खिड़की के आवंटन और प्रारंभिक प्रबंधन का प्रबंधन करता है जैसे प्रस्तावविंडो नियंत्रक। इसलिए विस्तार की निजी संपत्ति तक पहुंच प्राप्त करने का कोई तरीका नहीं है विन्डो कंट्रोलर प्रस्ताव से बाहर WindowController। – archibaldtuttle

0

जब मैंने एआरसी में स्विच किया तो मुझे यह वही समस्या थी। आपका समाधान काम करता है, लेकिन आप इसे बहुत जटिल बना रहे हैं। जब आप बंद हो जाते हैं तो खिड़की रिलीज होने से पहले आप जो भी कर रहे थे, वह अनिवार्य रूप से कर सकते हैं, लेकिन एआरसी संगत तरीके से।

समाधान केवल वर्ग के भीतर अपनी कक्षा की संपत्ति बनाना है।

@property (strong) DetailWindowController  *theWindowController; 

फिर जब आप ऊपर अपने कोड के साथ खिड़की बनाने के लिए, तो जैसे एक पंक्ति जोड़ें:: अपनी उदाहरण के लिए, DetailWindowController में, आपको निम्न संपत्ति जोड़ना होगा फिर अंत में

DetailWindowController *proposalWindowController = [[DetailWindowController alloc] initWithWindowNibName:@"ThePorposalWindow"]; 
[preferenceController setTheWindowController:proposalWindowController]; 
[proposalWindowController showWindow:nil]; 

, के लिए एआरसी खिड़की जारी है जैसे आप autorelease पूर्व एआरसी के साथ किया था जब यह बंद कर दिया है DetailWindowController कक्षा में, के लिए, बस कार्य करें:

- (void)windowWillClose:(NSNotification *)notification 
{ 
    // Let ARC tear this down and clean it up 
    [self setTheWindowController:nil]; 
}