12

आमतौर पर हमारे पास प्रोजेक्ट में UIBarButtonItem का एक पूर्वनिर्धारित सेट है जिसका उपयोग प्रोजेक्ट में किया जा सकता है और एक साइड मेनू खोलने के लिए बाएं मेनू बटन जैसे कई बार, इसका उपयोग विभिन्न UIViewController एस में भी एक करीबी बटन में किया जा सकता है जो प्रस्तुत दृश्य नियंत्रक को खारिज कर देता है।परियोजना के किसी भी UIViewController को बार बटन आइटम जोड़ने के लिए जेनेरिक ग्लोबल सुरुचिपूर्ण तरीका

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

enum BarButtonItemType { 
    case menu, close, notification 
} 

enum BarButtonItemPosition{ 
    case right, left 
} 

extension UIViewController { 

    func add(barButtons:[BarButtonItemType], position: BarButtonItemPosition) { 

     let barButtonItems = barButtons.map { rightBarButtonType -> UIBarButtonItem in 
      switch rightBarButtonType { 
      case .menu: 
       return UIBarButtonItem(image: UIImage(named:"menu"), 
        style: .plain, 
        target: self, 
        action: #selector(presentLeftMenu(_:))) 
      case .notification: 
       return UIBarButtonItem(image: UIImage(named:"notification"), 
       style: .plain, 
       target: self, 
       action: #selector(showNotification(_:))) 
      case .close: 
       return UIBarButtonItem(image: UIImage(named:"close"), 
        style: .plain, 
        target: self, 
        action: #selector(dismissController(_:))) 
      } 
     } 

     switch position { 
     case .right: 
      self.navigationItem.rightBarButtonItems = barButtonItems 
     case .left: 
      self.navigationItem.leftBarButtonItems = barButtonItems 
     } 
    } 

    // MARK: Actions 
    @objc fileprivate func presentLeftMenu(_ sender:AnyObject) { 
     self.parent?.presentLeftMenuViewController(sender) 
    } 

    @objc fileprivate func dismissController(_ sender:AnyObject) { 
     self.dismiss(animated: true, completion: nil) 
    } 

    @objc fileprivate func showNotification(_ sender:AnyObject) { 
     let notificationViewController = UINavigationController(rootViewController:NotificationViewController()) 
     self.present(notificationViewController, animated: true, completion: nil) 
    } 
} 

और उसके बाद:

override func viewDidLoad() { 
    super.viewDidLoad() 
    self.add(barButtons: [.close], position: .right) 
    self.add(barButtons: [.menu], position: .left) 
} 

मेरे दृष्टिकोण की सीमाएं हैं:

  • मेरी एक दृष्टिकोण के साथ आते हैं, लेकिन यह सही किया जा रहा से दूर है

    एक्सटेंशन को यह जानने की आवश्यकता है कि नए व्यू कंट्रोलर को तुरंत कैसे चालू किया जाए (उदाहरण के लिए अधिसूचना का मामला) और क्या होगा नियंत्रक मानकों के साथ inited किया जाना चाहिए

  • यह मानता है कि आप केवल एक UIViewController

  • सुरुचिपूर्ण नहीं प्रस्तुत करना चाहते हैं।

मुझे यकीन है कि ओरिएंटेड प्रोग्रामिंग स्विफ्ट भाषा और प्रोटोकॉल के साथ बेहतर तरीका है कि अधिक लचीलेपन के साथ इच्छित परिणाम प्राप्त कर सकते हैं, कोई विचार है कि वहाँ रहा हूँ?

उत्तर

1

ऐसा लगता है कि आप डिफॉल्ट बार बटन कॉन्फ़िगरेशन के बाद हैं लेकिन विशिष्ट (UIViewController के उप-वर्ग के लिए) बार बटन क्रिया कार्यान्वयन। आपने 1 का उल्लेख किया है। "एक्सटेंशन को नए दृश्य नियंत्रक को तुरंत चालू करने के बारे में जानने की आवश्यकता है" और आपका दूसरा बिंदु 2. "यह मानता है कि आप केवल एक UIViewController प्रस्तुत करना चाहते हैं", यह एक अच्छा संकेत है कि आपके एक्सटेंशन को उस सबक को उप-वर्ग में सौंपना चाहिए जानता है कि उन कार्यों के साथ क्या करना है। यहां मैंने नमूना कार्यान्वयन किया है:

enum BarButtonItemPosition { 
    case right, left 
} 

enum BarButtonItemType { 
    case menu(BarButtonItemPosition) 
    case close(BarButtonItemPosition) 
    case notification(BarButtonItemPosition) 
} 

/// Has default implementation on UIViewControllers that conform to BarButtonActions. 
protocol BarButtonItemConfiguration: class { 

    func addBarButtonItem(ofType type: BarButtonItemType) 
} 

/// Hate that we're forced to expose button targets to objc runtime :(
/// but I don't know any other way for the time being, maybe in Swift 6 :) 
@objc protocol BarButtonActions { 
    @objc func presentLeftMenu(_ sender:AnyObject) 
    @objc func dismissController(_ sender:AnyObject) 
    @objc func showNotification(_ sender:AnyObject) 
} 

extension BarButtonItemConfiguration where Self: UIViewController, Self: BarButtonActions { 

    func addBarButtonItem(ofType type: BarButtonItemType) { 

     func newButton(imageName: String, position: BarButtonItemPosition, action: Selector?) { 
      let button = UIBarButtonItem(image: UIImage(named: imageName), style: .plain, target: self, action: action) 
      switch position { 
      case .left: self.navigationItem.leftBarButtonItem = button 
      case .right: self.navigationItem.rightBarButtonItem = button 
      } 
     } 

     switch type { 
     case .menu(let p): newButton(imageName: "", position: p, action: #selector(Self.presentLeftMenu(_:))) 
     case .notification(let p): newButton(imageName: "", position: p, action: #selector(Self.showNotification(_:))) 
     case .close(let p): newButton(imageName: "", position: p, action: #selector(Self.dismissController(_:))) 
     } 
    } 
} 

/// Conform to this in subclasses of UIViewController and implement BarButtonActions (its impl. differs from vc to vc). 
protocol BarButtonConfigarable: BarButtonItemConfiguration, BarButtonActions {} 

/// example 
class SampleVC: UIViewController, BarButtonConfigarable { 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     addBarButtonItem(ofType: .menu(.right)) 
     addBarButtonItem(ofType: .menu(.left)) 
    } 

    @objc func presentLeftMenu(_ sender:AnyObject) { 
     // TODO: 
    } 
    @objc func dismissController(_ sender:AnyObject) { 
     // TODO: 
    } 
    @objc func showNotification(_ sender:AnyObject) { 
     // TODO: 
    } 
} 
संबंधित मुद्दे

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