खोज…


परिचय

आमतौर पर, UIControl या UIButton का उपयोग करते समय, हम एक बटन या नियंत्रण पर एक घटना के रूप में selector को जोड़ते हैं, जब बटन या नियंत्रण पर कोई घटना होती है, जैसे कि उपयोगकर्ता बटन दबाने या नियंत्रण को छूता है।

उदाहरण के लिए, हम निम्नलिखित करेंगे:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
        button.addTarget(self, action: #selector(self.onButtonPress(_:)), for: .touchUpInside)
        self.view.addSubview(button)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    func onButtonPress(_ button: UIButton!) {
        print("PRESSED")
    }
}

जब selector बात आती है, तो संकलक को केवल यह जानना होगा कि यह मौजूद है .. यह एक protocol माध्यम से किया जा सकता है और इसे लागू नहीं किया जा सकता है।

उदाहरण के लिए, निम्नलिखित आपके एप्लिकेशन को क्रैश कर देगा:

import UIKit

@objc
protocol ButtonEvent {
    @objc optional func onButtonPress(_ button: UIButton)
}

class ViewController: UIViewController, ButtonEvent {
    @IBOutlet weak var button: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
        button.addTarget(self, action: #selector(ButtonEvent.onButtonPress(_:)), for: .touchUpInside)
        self.view.addSubview(button)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

ऐसा इसलिए है क्योंकि आपका एप्लिकेशन onButtonPress फ़ंक्शन को लागू नहीं करता है।

अब क्या होगा अगर आप बटन के आरंभीकरण के साथ यह सब कर सकते हैं? क्या होगा यदि आपको कॉलबैक निर्दिष्ट नहीं करना है और इसके बजाय ऐसे ब्लॉक निर्दिष्ट कर सकते हैं जिन्हें किसी भी समय जोड़ा और हटाया जा सकता है? चयनकर्ताओं को लागू करने की चिंता क्यों?


समाधान

import Foundation
import UIKit

protocol RemovableTarget {
    func enable();
    func disable();
}

extension UIControl {
    func addEventHandler(event: UIControlEvents, runnable: (control: UIControl) -> Void) -> RemovableTarget {
        
        class Target : RemovableTarget {
            private var event: UIControlEvents
            private weak var control: UIControl?
            private var runnable: (control: UIControl) -> Void
            
            private init(event: UIControlEvents, control: UIControl, runnable: (control: UIControl) -> Void) {
                self.event = event
                self.control = control
                self.runnable = runnable
            }
            
            @objc
            private func run(_ control: UIControl) {
                runnable(control: control)
            }
            
            private func enable() {
                control?.addTarget(self, action: #selector(Target.run(_:)), for: event)
                objc_setAssociatedObject(self, unsafeAddress(of: self), self, .OBJC_ASSOCIATION_RETAIN)
            }
            
            private func disable() {
                control?.removeTarget(self, action: #selector(Target.run(_:)), for: self.event)
                objc_setAssociatedObject(self, unsafeAddress(of: self), nil, .OBJC_ASSOCIATION_ASSIGN)
            }
        }
        
        let target = Target(event: event, control: self, runnable: runnable)
        target.enable()
        return target
    }
}

ऊपर UIControl पर एक सरल विस्तार है। यह एक आंतरिक निजी वर्ग को जोड़ता है जिसमें कॉलबैक func run(_ control: UIControl) होता है जिसे घटनाओं की कार्रवाई के रूप में उपयोग किया जाता है।

अगला हम लक्ष्य को जोड़ने और हटाने के लिए object association का उपयोग करते हैं क्योंकि यह UIControl द्वारा बनाए नहीं रखा जाएगा।

ईवेंट हैंडलर फ़ंक्शन किसी Protocol को Target वर्ग के आंतरिक कामकाज को छिपाने के लिए देता है, लेकिन आपको किसी भी समय लक्ष्य को enable और disable करने की अनुमति देता है।


उपयोग उदाहरण:

import Foundation
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        

        //Create a button.
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 44))
        
        //Add an event action block/listener -- Handles Button Press.
        let target = button.addEventHandler(event: .touchUpInside) { (control) in
            print("Pressed")
        }
        

        self.view.addSubview(button)
        
        //Example of enabling/disabling the listener/event-action-block.
        DispatchQueue.main.after(when: DispatchTime.now() + 5) {
            target.disable() //Disable the listener.
            
            DispatchQueue.main.after(when: DispatchTime.now() + 5) {
                target.enable() //Enable the listener.
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow