2014-09-01 7 views
22

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

उदाहरण टपकाया नीचे कोड:

typealias Callback =()->() 

class CycleInducingClass : NSObject { 
    var myCallbacks = [Callback]() 

    override init() { 
     super.init() 
     myCallbacks.append(myInternalFunction) 
    } 

    func myInternalFunction() { 
     NSLog("lolol: %d", self.myCallbacks.count) 
    } 
} 

एकमात्र समाधान मैं अब तक मिल गया है के बजाय यह करने के लिए है:

myCallbacks.append({[unowned self] in self.myInternalFunction()}) 

यह सुंदर कुरूप, और त्रुटि होने का खतरा है। कोई बेहतर विचार? क्या समारोह संदर्भ खुद को कमजोर बनाने के लिए कुछ चाल है? यानी myCallbacks प्रकार myCallbacks : [WeakCallback]() या कुछ प्रकार बनाने के लिए? जहां तक ​​मैं कह सकता हूं कि मैं उपरोक्त बदसूरत क्लोजर रैपर पर सिंटैक्टिक चीनी के रूप में सुविधा सुविधा weaken भी नहीं बना सकता।

+0

myInternalFunction में पैरामीटर जोड़ने के बारे में कैसे? जिसे कमजोर घोषित किया जा सकता है ..... सुंदर नहीं है हालांकि –

+0

मैंने अपने सभी आंतरिक कार्यों को बंद करने की भी कोशिश की है, यानी 'मेरा आंतरिक कार्य = {[अज्ञात स्वयं] ...}' जो काम करता है, बल्कि यह भी है बदसूरत। – wxs

उत्तर

10

आप निश्चित रूप से इसके लिए एक फ़ंक्शन बना सकते हैं। मुझे नहीं पता कि यह नाटकीय रूप से बेहतर बनाता है, लेकिन यह कम त्रुटि-प्रवण है।

func methodPointer<T: AnyObject>(obj: T, method: (T) ->() -> Void) -> (() -> Void) { 
    return { [unowned obj] in method(obj)() } 
} 
... 
myCallbacks.append(methodPointer(self, CycleInducingClass.myInternalFunction)) 

वैकल्पिक रूप से, आप विधि संकेत के रूप में अपने कॉलबैक प्रबंधन कर सकते हैं: उस मामले में

typealias Callback = (CycleInducingClass) ->() -> Void 
... 
myCallbacks.append(CycleInducingClass.myInternalFunction) 

, आप जब आप उन्हें कहा जाता है (यदि आप ऐसा नहीं करते जो ठीक हो सकता है self पारित करने के लिए आवश्यकता होगी वास्तव में इस एक बहुत) कार्य करें:

self.myCallbacks[0](self)() 

यह सब तथ्य पर आधारित है कि हस्ताक्षर (input) -> (output) साथ प्रकार T पर एक विधि एक कार्यात्मक के बराबर है हस्ताक्षर (T) -> (input) -> (output) के साथ।

यदि आप उत्सुक हैं (मैं था), इस मामले में ओवरराइडिंग सही ढंग से काम करता है। तो यदि आप CycleInducingClass उपखंड करते हैं और myInternalFunction ओवरराइड करते हैं, तो सही संस्करण कहा जाएगा। (यह वास्तव में मुझे एक छोटे से आश्चर्य है, और मैं अभी तक वास्तव में नहीं जानता कि यह क्यों काम करता है, लेकिन यह करता है।)

संपादित करें: https://devforums.apple.com/message/1036509#1036509

+0

आह दिलचस्प, मुझे एहसास नहीं हुआ कि आप स्थिर रूप से विधियों तक पहुंचते हैं और वे आपको कक्षा की कक्षा में अपनी कक्षा के फ़ंक्शन मैपिंग उदाहरण देंगे। वह घटक है जिसे मैं याद कर रहा था। धन्यवाद! – wxs

+2

क्या होगा यदि फ़ंक्शन पैरामीटर लेता है? यह कैसे काम करेगा? – Snowman

1

लूटता जवाब मेरे लिए काम किया: यहाँ इसका जवाब है। मैं refactor था हालांकि इसलिए मैंने सोचा कि मैं इसे यहाँ मामले में साझा करेंगे यह किसी और में मदद करता है यह एक छोटे से अधिक OO होने के लिए:

public protocol WeakCallback{ 
    func invoke() 
} 

public class WeakCallbackInstance<T: AnyObject> : WeakCallback{ 
    private let callback:()->Void 
    private weak var target: T? 

    public init(target: T, action: (T)->()->Void){ 

     self.target = target 
     callback = { [weak target] in 
      action(target!)() 
     } 
    } 

    public func invoke(){ 
     callback() 
    } 
} 

class ExampleUsage{ 

    func usage(){ 
     var callbacks = [WeakCallback]() 

     let one = WeakCallbackInstance(target: DummyCallbackOne(), action:DummyCallbackOne.callbackOne) 
     let two = WeakCallbackInstance(target: DummyCallbackTwo(), action:DummyCallbackTwo.callbackTwo) 

     callbacks.append(one) 
     callbacks.append(two) 
     callbacks.first?.invoke() 
    } 
} 

class DummyCallbackOne{ 
    func callbackOne(){ 
    } 
} 

class DummyCallbackTwo{ 
    func callbackTwo(){ 
    } 
} 
-1

ब्लॉक के साथ

myCallbacks.append({ [unowned self] in self.myInternalFunction() }) 

लिपटे परम समारोह के साथ कोई परम समारोह लिपटे ब्लॉक

myCallbacks.append({ [unowned self] page in self.reloadData(page: page) }) 
0

स्विफ्ट 4 (मुझे यकीन है कि जब वाक्य रचना उपलब्ध हो गया नहीं कर रहा हूँ) में, बस self कमजोर बनाने के लिए { [weak self] (params) in } है। यह मूल रूप से [unowned self] है, Self?Self! है। कंपाइलर को self.foo के बजाय self?.foo की आवश्यकता होती है।