2016-08-16 13 views
6

मेरे पास एक उद्देश्य-सी प्रोटोकॉल है जिसका उपयोग ज्यादातर उद्देश्य-सी ऑब्जेक्ट्स और एक या दो स्विफ्ट ऑब्जेक्ट्स द्वारा किया जाता है।ओबीजेसी प्रोटोकॉल पर प्रोटोकॉल एक्सटेंशन

मैं स्विफ्ट में प्रोटोकॉल का विस्तार करना चाहता हूं और 2 फ़ंक्शन जोड़ना चाहता हूं। अधिसूचना को संभालने के लिए अधिसूचना के लिए पंजीकरण करने के लिए एक और दूसरा।

अगर मैं इन

func registerForPresetLoadedNotification() { 
    NSNotificationCenter.defaultCenter().addObserver(self as AnyObject, 
                selector: #selector(presetLoaded(_:)), 
                name: kPresetLoadedNotificationName, 
                object: nil) 
} 

func presetLoaded(notification: NSNotification) { 

} 

मैं #selector जो कहते हैं Argument of '#selector' refers to a method that is not exposed to Objective-C

मैं तो presetLoaded चिह्नित करते हैं @objc के रूप में मैं एक त्रुटि जो कहते हैं @objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

मैं भी मिलता है पर एक त्रुटि प्राप्त जोड़ने प्रोटोकॉल एक्सटेंशन को @objc

के रूप में चिह्नित नहीं कर सकता जब मैं एक स्विफ्ट के रूप में उद्देश्य-सी प्रोटोकॉल बनाता हूं प्रोटोकॉल मुझे एक ही त्रुटि मिलती है।

क्या यह हासिल करने का कोई तरीका है जो प्रोटोकॉल का उपयोग करने वाले उद्देश्य-सी और स्विफ्ट कक्षाओं के लिए काम करेगा?

+0

प्रोटोकॉल को विस्तारित करने और _optional_ कार्यों के रूप में इन कार्यों को परिभाषित करने के बारे में कैसे करें उद्देश्य-सी में और स्विफ्ट में उन्हें लागू करना? सिर्फ एक विचार। – skim

+0

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

+0

मुझे यकीन नहीं है कि मैं आपको सही ढंग से समझता हूं। ऐसा लगता है कि आप जो करना चाहते हैं वह विस्तारित है (मौजूदा प्रोटोकॉल में फ़ंक्शंस जोड़ें) और ओबीजेसी में एक डिफ़ॉल्ट कार्यान्वयन प्रदान करें और स्विफ्ट में उस कार्यान्वयन के एक हिस्से को ओवरराइड करें। क्या ये सही है? – skim

उत्तर

3

दरअसल, अगर तुम सच में @objc के रूप में एक प्रोटोकॉल विस्तार के एक समारोह (या गतिशील, जो जिस तरह से बराबर है) चिह्नित नहीं कर सकते। उद्देश्य-सी रनटाइम द्वारा कक्षा के केवल विधियों को प्रेषित करने की अनुमति है।

अपने विशेष मामले में, यदि आप वास्तव में प्रोटोकॉल एक्सटेंशन के माध्यम से इसे बनाना चाहते हैं, तो मैं निम्नलिखित समाधान का प्रस्ताव दे सकता हूं (मान लें कि आपका मूल प्रोटोकॉल ObjcProtocol) है।

के हमारे अधिसूचना हैंडलर के लिए एक आवरण करते हैं:

final class InternalNotificationHandler { 
    private let source: ObjcProtocol 

    init(source: ObjcProtocol) { 
     // We require source object in case we need access some properties etc. 
     self.source = source 
    } 

    @objc func presetLoaded(notification: NSNotification) { 
     // Your notification logic here 
    } 
} 

अब हम विस्तार हमारे ObjcProtocol लागू करने के लिए आवश्यक तर्क

import Foundation 
import ObjectiveC 

internal var NotificationAssociatedObjectHandle: UInt8 = 0 

extension ObjcProtocol { 
    // This stored variable represent a "singleton" concept 
    // But since protocol extension can only have stored properties we save it via Objective-C runtime 
    private var notificationHandler: InternalNotificationHandler { 
     // Try to an get associated instance of our handler 
     guard let associatedObj = objc_getAssociatedObject(self, &NotificationAssociatedObjectHandle) 
      as? InternalNotificationHandler else { 
      // If we do not have any associated create and store it 
      let newAssociatedObj = InternalNotificationHandler(source: self) 
      objc_setAssociatedObject(self, 
            &NotificationAssociatedObjectHandle, 
            newAssociatedObj, 
            objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) 
      return newAssociatedObj 
     } 

     return associatedObj 
    } 

    func registerForPresetLoadedNotification() { 
     NSNotificationCenter.defaultCenter().addObserver(self, 
                 selector: #selector(notificationHandler.presetLoaded(_:)), 
                 name: kPresetLoadedNotificationName, 
                 object: self) 
    } 

    func unregisterForPresetLoadedNotification() { 
     // Clear notification observer and associated objects 
     NSNotificationCenter.defaultCenter().removeObserver(self, 
                  name: kPresetLoadedNotificationName, 
                  object: self) 
     objc_removeAssociatedObjects(self) 
    } 
} 

मैं जानता हूँ कि यह नहीं तो सुरुचिपूर्ण लग सकता है की जरूरत है, तो मैं वास्तव में एक कोर दृष्टिकोण बदलने पर विचार करें।

एक ध्यान दें: आप अपने प्रोटोकॉल विस्तार

extension ObjcProtocol where Self: SomeProtocolOrClass 
0

मैं एक तरह से करने के लिए यह बस सब एक साथ @objc से बचने :) पाया प्रतिबंधित करने के लिए चाहते हो सकता है कर: डी

//Adjusts UITableView content height when keyboard show/hide 
public protocol KeyboardObservable { 
    func registerForKeyboardEvents() 
    func unregisterForKeyboardEvents() 
} 

extension KeyboardObservable where Self: UITableView { 

    public func registerForKeyboardEvents() { 
     NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil) { notification in 
      self.keyboardDidShow(notification) 
     } 
     NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil) { notification in 
      self.keyboardWillHide(notification) 
     } 
    } 

    private func keyboardDidShow(_ notification: Notification) { 
     let rect = ((notification as NSNotification).userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue 
     let height = rect.height 
     var insets = UIEdgeInsetsMake(0, 0, height, 0) 
     insets.top = contentInset.top 
     contentInset = insets 
     scrollIndicatorInsets = insets 
    } 

    private func keyboardWillHide(_ notification: Notification) { 
     var insets = UIEdgeInsetsMake(0, 0, 0, 0) 
     insets.top = contentInset.top 
     UIView.animate(withDuration: 0.3) { 
      self.contentInset = insets 
      self.scrollIndicatorInsets = insets 
     } 
    } 

    public func unregisterForKeyboardEvents() { 
     NotificationCenter.default.removeObserver(self) 
    } 

} 

उदाहरण

class CreateStudentTableView: UITableView, KeyboardObservable { 

    init(frame: CGRect, style: UITableViewStyle) { 
    super.init(frame: frame, style: style) 
    registerForKeyboardEvents() 
    } 

    required init?(coder aDecoder: NSCoder) { 
    fatalError("init(coder:) has not been implemented") 
    } 

    deinit { 
    unregisterForKeyboardEvents() 
    } 
} 
संबंधित मुद्दे