2009-07-02 8 views
20

मैं एक आईफोन एप्लिकेशन पर काम कर रहा हूं। मेरे पास कक्षा का ऑब्जेक्ट है जिसे कक्षा Block श्रेणी की कई ऑब्जेक्ट्स जारी करने की आवश्यकता है। प्रत्येक Block में वर्तमान में एक संपत्ति है जो कक्षा के आवृत्ति चर को बनाए रखती है।मेरे पास एक परिपत्र संदर्भ है। मैं उद्देश्य-सी में एक कमजोर संदर्भ कैसे बना सकता हूं?

@interface Block : UIImageView { 
    Row *yCoord; 
} 
@property (nonatomic,retain) Row *yCoord; 
@end 

हर इन ब्लाकों के NSMutableArray शामिल हैं।

@interface Row : NSObject { 
    NSMutableArray *blocks; 
} 
-(void)addBlock:(Block*)aBlock; 
@end 

@implementation Row 
-(void)addBlock:(Block*)aBlock { 
    [blocks addObject:aBlock]; 
    aBlock.yCoord = self; 
} 
@end 

मैं समझता हूं कि यह एक परिपत्र संदर्भ है। ऐप्पल के दस्तावेज में कहा गया है कि एक परिपत्र संदर्भ के साथ किसी ऑब्जेक्ट को डिलीकेट करने के लिए मुझे एक मजबूत संदर्भ (एक रखरखाव संपत्ति) के बजाय एक कमजोर संदर्भ की आवश्यकता है, लेकिन यह इस बात का पालन नहीं करता है कि मैं ऐसा करने के लिए वास्तव में कैसे जाता हूं। मैं एक पंक्ति के साथ-साथ पंक्ति के साथ-साथ सभी ब्लॉक को रिलीज और डिलीक करने की योजना बना रहा हूं। मैं अपने प्रत्येक ब्लॉक के भीतर अपने "पैरेंट" पंक्ति में एक कमजोर संदर्भ कैसे स्थापित करूं?

+4

वैसे, आपको अपने संपादन और विशेष रूप से एक नए SO उपयोगकर्ता के रूप में आपके संपादन और उपयुक्त टैगिंग के लिए सराहना की जाएगी। वाहवाही! मैं उन लोगों की सराहना करता हूं जो समुदाय के अच्छे के लिए कुछ चीजों को पॉलिश करने के लिए समय लेते हैं। –

+2

क्यों, धन्यवाद! यह साइट वही है जो मैं हर पहलू में खोज रहा हूं। केवल एक स्पष्ट प्रश्न पूछने के लिए समय निकालना समझ में आता है जब बहुत से लोग बाहर निकलने के लिए तैयार हैं और तुरंत जवाब देते हैं। – Tozar

उत्तर

19

संपादित करें: चूंकि पूछताछ ने स्पष्ट किया कि वह कचरा संग्रह का उपयोग नहीं कर रहा है (आईफोन वर्तमान में इसका समर्थन नहीं करता है), मेरी सलाह है कि केवल एक वस्तु को बनाए रखने के लिए चक्रों से बचें, जैसा कि आप करेंगे प्रतिनिधि। गुणों का उपयोग करते समय, इसे प्राप्त करने के लिए "बनाए रखने" के बजाय "असाइन करें" का उपयोग करें। उदाहरण के लिए:

@property (nonatomic,assign) Row *yCoord; 

मेरा उत्तर जवाब के बाकी "कमजोर संदर्भ" ऑब्जेक्टिव-सी 2.0 और जीसी के संदर्भ में से संबंधित है।


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

इस प्रकार, आप सुरक्षित रूप से कचरा संग्रहण के साथ अच्छे खेलने के लिए ऊपर जवाब संशोधित कर सकते हैं (वर्तमान में 10.5+ पर, और शायद किसी दिन iPhone पर) इस प्रकार है: (देखें related Apple docs)

@property (nonatomic,assign) __weak Row *yCoord; 

Chris Hanson (जहां आप अधिक विस्तृत जानकारी) प्राप्त कर सकते हैं के शब्दों में:।

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

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

नोट: यह नहीं सीधे कमजोर संदर्भ बनाने से संबंधित है, लेकिन वहाँ भी एक __strong विशेषता है, लेकिन चूंकि ऑब्जेक्टिव-सी वस्तु चर डिफ़ॉल्ट रूप से मजबूत संदर्भ हैं, यह आम तौर पर केवल के लिए प्रयोग किया जाता है कच्चे सी पॉइंटर्स जैसे कि structs या primitives जैसे कचरा कलेक्टर जड़ों के रूप में नहीं व्यवहार करेगा, और यदि आप उन्हें मजबूत घोषित नहीं करते हैं तो आपके नीचे से एकत्र किया जाएगा। (जबकि __weak की कमी चक्र और मेमोरी लीक बनाए रखने का कारण बन सकती, __strong की कमी स्मृति stomping में परिणाम कर सकते हैं और वास्तव में अजीब और घातक कीड़े है कि हो गैर निर्धारणात्मक और काफी मुश्किल हो सकता नीचे ट्रैक करने के लिए।)

+1

मुझे यह स्पष्ट करने दें कि यह एक आईफोन एप्लिकेशन के लिए है। मुझे विश्वास नहीं है कि आईफोन एक जीसी का उपयोग करता है। – Tozar

+1

तो पंक्ति * yCoord घोषित करने की बजाय; @@property (nonatomic, retain) के साथ \t पंक्ति * yCoord; क्या मैं करता हूं: __weak पंक्ति * yCoord; लेकिन फिर मैं संपत्ति कैसे घोषित करूं? – Tozar

+0

आप @property और __weak मिश्रण कर सकते हैं: @property (nonatomic, retain) __weak पंक्ति * yCoord; – Tim

4

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

आम तौर पर, कोको में, Block वस्तुओं (उन्हें NSMutableArray में शामिल करके) को बनाए रखने होगा, लेकिन Block बनाए रखने नहीं होगा, प्रत्येक बस इसे एक इवर में संग्रहीत करेंगे (एक "आवंटित" संपत्ति के साथ)।

जब तक के रूप में प्रत्येक Block जारी करने के लिए सावधान है इससे पहले कि यह पुनः आवंटित की जाती है (यानी, अपने dealloc NSMutableArray जो जब तक कोई और उन्हें किसी भी संकेत दिए गए है ब्लाकों जारी करेंगे रिलीज चाहिए) तो सब कुछ के रूप में पुनः आवंटित की जाती हो जाएगा उचित।

तुम भी सरणी से entiries हटाने से पहले ब्लाकों से पंक्ति संदर्भ के शून्यीकरण की एहतियात ले जा सकते हैं, कुछ की तरह:

- (void) dealloc { 
    for (Block* b in _blocks) { 
     b.row = nil; 
    } 
    [_blocks release]; 
    [super dealloc]; 
} 

जहां _blocks इवर ब्लॉक संपत्ति द्वारा संदर्भित है।

+0

क्या _b NSMutableArray ivar self.blocks द्वारा लौटाया गया है? यदि ऐसा है, तो मुझे लगता है कि आप इसका मतलब है [_b रिलीज] इसके बजाय। इसके अलावा, कक्षा के अंदर self.blocks का उपयोग करने की आवश्यकता नहीं है जिसमें रेफरेंस हैं - बस (ब्लॉक * बी में _b) के लिए उपयोग करें। यदि _b को "_blocks" या यहां तक ​​कि "ब्लॉक" नाम दिया गया हो तो यह कम भ्रमित हो सकता है। (मुझे एहसास है कि कुछ लोग अंडरस्कोर पसंद करते हैं, लेकिन मैं इसका कभी भी उपयोग नहीं करता हूं।) –

+0

फिक्स्ड, धन्यवाद क्विन –

8

बस के बजाय आवंटित बनाए रखने, कोई और अधिक वृत्तीय संदर्भ के लिए इसे बदल।

@interface Block : UIImageView { 
    Row *yCoord; 
} 
@property (nonatomic,assign) Row *yCoord; 
@end 
3

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

सौभाग्य से, यह अक्सर पदानुक्रम की एक समस्या है, और कमजोर संदर्भ युक्त वस्तु केवल वस्तु इसके लिए संदर्भित किया-पर आपत्ति के जीवनकाल को संदर्भित करता है के बारे में परवाह है। सुपीरियर < -> अधीनस्थ संबंध के साथ यह सामान्य स्थिति है।

मुझे लगता है कि यह करने के लिए ओ पी की टिप्पणी नक्शे, पंक्ति = सुपीरियर, ब्लॉक = अधीनस्थ साथ में मामला।

इस मामले में, मैं अधीनस्थ से सुपीरियर को संदर्भित करने के एक हैंडल का प्रयोग करेंगे:

// Superior.h 

@class Superior; 

@interface SuperiorHandle : NSObject { 
    @private 
     Superior* superior_; 
} 

// note the deliberate avoidance of "nonatomic" 
@property (readonly) Superior *superior; 

@end 

@interface Superior : NSObject { 
    @private 
     SuperiorHandle *handle_; 
     // add one or more references to Subordinate instances 
} 

// note the deliberate avoidance of "nonatomic" 
@property (readonly) SuperiorHandle *handle; 

@end 


// Superior.m 

#import "Superior.h" 

@implementation SuperiorHandle 

@synthesize 
    superior = superior_; 

- (id)initWithSuperior:(Superior *)superior { 
    if ((self = [super init])) { 
     superior_ = superior; // weak reference 
    } 
} 

- (void)invalidate { 
    @synchronized (self) { 
     superior_ = nil; 
    } 
} 

- (Superior *)superior { 
    @synchronized (self) { 
     // retain and autorelease is required to prevent dealloc before we're ready, thanks to AndroidDev for pointing out this mistake 
     return [[superior_ retain] autorelease]; 
    } 
} 

@end 

@implementation Superior 

@synthesize 
    handle = handle_; 

- (id)init { 
    if ((self = [super init])) { 
     handle_ = [[SuperiorHandle alloc] initWithSuperior:self]; 
    } 
    return self; 
} 

- (void)dealloc { 
    [handle_ invalidate]; 
    [handle_ release]; 

    [super dealloc]; 
} 

@end 


// Subordinate.h 

@class Superior; 
@class SuperiorHandle; 

@interface Subordinate : NSObject { 
    @private 
     SuperiorHandle *superior_handle_; 
} 

@property (readonly) Superior *superior; 

@end 


// Subordinate.m 

#import "Subordinate.h" 

#import "Superior.h" 

@implementation Subordinate 

// no synthesize this time, superior's implementation is special 

- (id)initWithSuperior:(Superior *)superior { 
    if ((self = [super init])) { 
     superior_handle_ = [superior.handle retain]; 
    } 
    return self; 
} 

- (void)dealloc { 
    [superior_handle_ release]; 

    [super dealloc]; 
} 

- (Superior *)superior { 
    @synchronized (superior_handle_) { 
     return superior_handle_.superior; 
    } 
} 

@end 

कुछ लाभ:

  1. यह धागा सुरक्षित। Subordinate में निहित कमजोर संदर्भ एक अमान्य सूचक बनने का कोई तरीका नहीं है। यह शून्य हो सकता है लेकिन यह ठीक है।
  2. केवल ऑब्जेक्ट्स को एम्बेडेड कमजोर संदर्भ के बारे में जानने की आवश्यकता है। अन्य सभी वस्तुएं अधीनस्थ का इलाज कर सकती हैं जैसे कि इसमें सुपीरियर का नियमित संदर्भ है।
+0

यह डिज़ाइन काम करेगा, लेकिन आप SuperiorHandle क्लास में @ सिंथेसाइज़ बेहतर का उपयोग नहीं कर सकते। @ सिंथेसाइज प्रत्येक फ़ील्ड के लिए एक अलग लॉक बनाएगा (एक स्पिन लॉक सटीक होना चाहिए)। आपको 'अमान्य' में उपयोग किए जाने वाले उसी लॉक को लॉक करने की आवश्यकता है जो आप 'better_' चर को वापस करते समय करते हैं। तो आपको अपने आप को बेहतर ढंग से कार्यान्वित करने और @ सिंक्रनाइज़ (स्वयं) वापस लौटने की आवश्यकता है {returnValue = _superior} वापसी वापसी वैल्यू; –

+0

दरअसल, शायद यह 'सुपीरियर' डिज़ाइन काम नहीं करेगा। क्या होगा यदि आप 'सुपीरियर' के लिए मान प्राप्त करने के लिए 'श्रेष्ठ' विधि को कॉल करते हैं, और फिर कोई अन्य थ्रेड हैंडल को अमान्य करता है? आप अभी भी थ्रेड में मुक्त स्मृति के लिए एक सूचक के साथ छोड़े गए हैं कि आपने अभी 'श्रेष्ठ' मान प्राप्त किया है। बेशक, आप मानते हैं कि इनमें से कोई भी धागा सुरक्षित नहीं है (लेकिन अगर ऐसा होता है, तो आप ' @ सिंक्रनाइज़ कॉल की आवश्यकता नहीं है)। दुर्भाग्य से मुझे नहीं लगता कि यह बिल्कुल काम करेगा। इसके लिए आपको वास्तव में एक जीसी वातावरण की आवश्यकता है, या इसे वापस करने से पहले आपको बेहतर मूल्य को बनाए रखना होगा। –

+0

पुन: स्पिन लॉक। मुझे इस व्यवहार से अवगत नहीं था, क्या आपके पास इसके लिए दस्तावेज है? मैंने हिलगैस की पुस्तक में क्या पढ़ा है, और दस्तावेज क्या है [यहां] (http://stackoverflow.com/questions/588866/atomic-vs-nonatomic-properties) इंगित करता है कि "परमाणु संश्लेषित" द्वारा उत्पन्न लॉक @ सिंक्रनाइज़ (स्वयं) जैसा कि मैं मैन्युअल रूप से अमान्य() में करता हूं। – Brane

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