2016-08-14 9 views
8

यहाँ बनाए रखने के अपने कस्टम दृश्य हैस्विफ्ट चक्र स्पष्टीकरण

class ViewControllerB: UIViewController { 

    var customView: CustomVIew! 

    deinit { 
     print("B deinit") 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let customView = CustomVIew() 
     customView.onTapViewHandler = { [unowned self] in 
      self.didTapBlue() 
     } 
     customView.frame = CGRect(x: 50, y: 250, width: 200, height: 100) 
     customView.backgroundColor = UIColor.blueColor() 
     view.addSubview(customView) 

     self.customView = customView 

    } 

    func didTapBlue() { 

    } 
} 

जब नियंत्रक नेविगेशन ढेर से पॉप है, सब कुछ ठीक है:

B deinit 
custom view deinit 

लेकिन जब मैं इस कोड को प्रतिस्थापित करता हूं:

customView.onTapViewHandler = { [unowned self] in 
    self.didTapBlue() 
} 
इस के साथ

:

customView.onTapViewHandler = didTapBlue 

तो, कुछ भी कंसोल पर छपा है। कस्टम व्यू और व्यू कंट्रोलर जारी नहीं किए जाते हैं, क्यों?

customView.onTapViewHandler = didTapBlueself का संदर्भ कैप्चर क्यों करता है?

+0

आप जानते हैं कि यह पहले से क्यों नहीं है? आपका शीर्षक कहता है कि यह सर्कल बनाए रखता है ... इसे प्रिंट करके संदर्भ गणना की जांच करें: प्रिंट (CFGetRetainCount (ऑब्जेक्ट)) – Surely

+0

@ निश्चित रूप से आप 'CFGetRetainCount' को 'बनाए रखने' के आसपास काम करने के लिए सुझाव देते हैं। लेकिन एक कारण है कि 'बनाए रखना' बहिष्कृत किया गया है: यह एक अच्छा समाधान नहीं है। – Abizern

+0

यह सिर्फ एक जांच विधि है। मेरा मतलब है कि आप संदर्भों की मात्रा को मुद्रित कर सकते हैं जो नियंत्रक को संदर्भित किया गया है ताकि आप जान सकें कि "customView" दृश्य नियंत्रक के लिए एक मजबूत संदर्भ है या नहीं। यदि यह है, तो एक बरकरार चक्र है। क्योंकि इसमें एक सतत चक्र है, इसलिए दो ऑब्जेक्ट स्वचालित रूप से नष्ट नहीं हो सकते हैं। – Surely

उत्तर

4

यदि आप बंद करने के लिए [unowned self] कैप्चर सूची जोड़ते हैं, तो दृश्य में self का एक कमजोर संदर्भ है, और self दृश्य के लिए एक मजबूत संदर्भ रखता है।

चूंकि दृश्य नियंत्रक पॉप-अप होने पर self, self के लिए कोई मजबूत संदर्भ नहीं है, तो self को हटाया जा सकता है। self के बाद deinitialized है, अब दृश्य के लिए कुछ भी मजबूत संदर्भ नहीं है, इसलिए यह भी deinitialized है।

यदि आप कैप्चर सूची को हटाते हैं, तो self दृश्य के लिए एक मजबूत संदर्भ रखता है और दृश्य self पर एक मजबूत संदर्भ रखता है। इसका मतलब है कि self को पुन: प्रारंभ करने के लिए, दृश्य को पहले परिभाषित किया जाना चाहिए (जो मजबूत संदर्भ को तोड़ देगा)। लेकिन दृश्य को परिभाषित करने के लिए, व्यू कंट्रोलर को दृश्य के मजबूत संदर्भ को तोड़ने के लिए सबसे पहले deinitialized किया जाना चाहिए। लेकिन जब तक आप दृश्य नियंत्रक को परिभाषित नहीं करते हैं, तब तक आप दृश्य के मजबूत संदर्भ को तोड़ नहीं सकते। जब तक आप दृश्य को परिभाषित नहीं करते हैं, तब तक आप व्यू कंट्रोलर के मजबूत संदर्भ को तोड़ नहीं सकते।

देखें? हम यहाँ एक अनंत लूप में मिल गया है! तो न तो दृश्य और न ही दृश्य नियंत्रक को रद्द कर दिया जाएगा!

4

स्विफ्ट फ़ंक्शन बंद करने का एक प्रकार है। तो बंद होने की तरह (उद्देश्य सी में ब्लॉक) कार्य करता है संदर्भों को पकड़ सकते हैं।

जब customView.onTapViewHandler = didTapBlueself यानी ViewControllerB संदर्भ के संदर्भ को निष्पादित करता है तो इस मामले में संदर्भ कॉल द्वारा कब्जा कर लिया जाएगा।

वही समय ViewControllerB का दृश्य CustomVIew पर मजबूत संदर्भ रखता है ताकि यह चक्र बनाए रख सके।

unowned का उपयोग कर के बारे में, Apple document का कहना है:

कमजोर और बिना स्वामित्व वाले संदर्भ उस पर एक मजबूत पकड़ रखने के बिना अन्य उदाहरण का उल्लेख करने के लिए एक संदर्भ चक्र में एक उदाहरण सक्षम करें। उदाहरण एक मजबूत संदर्भ चक्र के बिना एक दूसरे को संदर्भित कर सकते हैं।

इसका मतलब है कि कोई परिपत्र संदर्भ नहीं है और चक्र बनाए रखा है।

+0

धन्यवाद। मुझे समझ में नहीं आता कि क्यों 'customView.onTapViewHandler = didTapBlue' निष्पादन' स्वयं 'संदर्भ को कैप्चर करेगा, क्या आप मुझे बता सकते हैं? –

+0

'didTapBlue'' self.didTapBlue' है। तो 'customView' को' didTapBlue' के संदर्भ में रखना चाहिए, केवल तब ही वह फ़ंक्शन निष्पादित कर सकता है। जैसा कि आप जानते हैं, ऑब्जेक्ट के संदर्भ के बिना didTapBlue जीवित नहीं रह सकता है। तो बंद, ब्लॉक और विधियां उदाहरण – renjithr

+0

ओह के लिए एक मजबूत संदर्भ जोड़ते हैं! समझा। बहुत बहुत धन्यवाद!^- ^ –