स्विफ्ट में फ़ंक्शन पैरामीटर के रूप में प्रोटोकॉल के अनुरूप वर्ग


91

ऑब्जेक्टिव-सी में, एक प्रोटोकॉल पैरामीटर विधि के रूप में एक वर्ग को निर्दिष्ट करना संभव है। उदाहरण के लिए, मेरे पास एक ऐसा तरीका हो सकता है जो केवल उसी की अनुमति देता UIViewControllerहै UITableViewDataSource:

- (void)foo:(UIViewController<UITableViewDataSource> *)vc;

मुझे स्विफ्ट में ऐसा करने का तरीका नहीं मिल रहा है (शायद यह अभी तक संभव नहीं है)। आप कई प्रोटोकॉल का उपयोग करके निर्दिष्ट कर सकते हैं func foo(obj: protocol<P1, P2>), लेकिन आपको कैसे आवश्यकता है कि वस्तु एक विशेष वर्ग की भी है?


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

जवाबों:


132

आप fooएक सामान्य कार्य के रूप में परिभाषित कर सकते हैं और एक वर्ग और एक प्रोटोकॉल दोनों की आवश्यकता के लिए प्रकार की बाधाओं का उपयोग कर सकते हैं ।

स्विफ्ट 4

func foo<T: UIViewController & UITableViewDataSource>(vc: T) {
    .....
}

स्विफ्ट 3 (स्विफ्ट 4 के लिए भी काम करता है)

func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { 
    ....
}

स्विफ्ट 2

func foo<T: UIViewController where T: UITableViewDataSource>(vc: T) {
    // access UIViewController property
    let view = vc.view
    // call UITableViewDataSource method
    let sections = vc.numberOfSectionsInTableView?(tableView)
}

3
मुझे लगता है कि यह थोड़ा दुर्भाग्यपूर्ण है कि इसकी आवश्यकता है। उम्मीद है कि भविष्य में इसके लिए एक क्लीनर सिंटैक्स होगा, जैसे protocol<>प्रदान करता है (लेकिन protocol<>इसमें गैर-प्रोटोकॉल प्रकार नहीं हो सकते हैं)।
jtbandes

यह मुझे बहुत दुखी करता है।
DCMaxxx 20

जिज्ञासा से बाहर, क्या आप स्पष्ट रूप से नहीं खोल सकते numberOfSectionsInTableViewक्योंकि यह एक आवश्यक कार्य है UITableViewDataSource?
rb612

numberOfSectionsInTableView:है वैकल्पिक-आप के बारे में सोच हो सकती है tableView:numberOfRowsInSection:
नैट कुक

11
स्विफ्ट 3 में यह एक वरीयता के साथ Xcode 8 बीटा 6 के रूप में पदावनत प्रतीत होता है:func foo<T: UIViewController>(vc:T) where T:UITableViewDataSource { ... }
LOP_Luke

29

स्विफ्ट 4 में आप इसे नए और साइन के साथ प्राप्त कर सकते हैं:

let vc: UIViewController & UITableViewDataSource

17

स्विफ्ट बुक डॉक्यूमेंटेशन से पता चलता है कि आप एक क्लॉज़ के साथ प्रकार की बाधाओं का उपयोग करते हैं:

func someFunction<C1: SomeClass where C1:SomeProtocol>(inParam: C1) {}

यह गारंटी देता है कि "InParam" एक शर्त के साथ "SomeClass" प्रकार का है जो कि "SomeProtocol" का भी पालन करता है। आपके पास एकाधिक को निर्दिष्ट करने की शक्ति भी है जहां अल्पविराम द्वारा सीमांकित किया जाता है:

func itemsMatch<C1: SomeProtocol, C2: SomeProtocol where C1.ItemType == C2.ItemType,    C1.ItemType: SomeOtherProtocol>(foo: C1, bar: C2) -> Bool { return true }

1
प्रलेखन के लिंक को देखकर अच्छा लगा होगा।
राज

4

स्विफ्ट 3 के साथ, आप निम्न कार्य कर सकते हैं:

func foo(_ dataSource: UITableViewDataSource) {
    self.tableView.dataSource = dataSource
}

func foo(_ delegateAndDataSource: UITableViewDelegate & UITableViewDataSource) { 
    //Whatever
}

1
यह केवल तेज 3. में प्रोटोकॉल, नहीं प्रोटोकॉल और वर्ग पर लागू होता है
आर्टेम Goryaev

2

इस तरह से क्या ?:

protocol MyProtocol {
    func getTableViewDataSource() -> UITableViewDataSource
    func getViewController() -> UIViewController
}

class MyVC : UIViewController, UITableViewDataSource, MyProtocol {

    // ...

    func getTableViewDataSource() -> UITableViewDataSource {
        return self
    }

    func getViewController() -> UIViewController {
        return self
    }
}

func foo(_ vc:MyProtocol) {
    vc.getTableViewDataSource() // working with UITableViewDataSource stuff
    vc.getViewController() // working with UIViewController stuff
}

2

स्विफ्ट 5:

func foo(vc: UIViewController & UITableViewDataSource) {
    ...
}

तो अनिवार्य रूप से ऊपर Jeroen का जवाब है।


0

सितंबर 2015 में नोट : यह स्विफ्ट के शुरुआती दिनों में एक अवलोकन था।

यह असंभव मालूम पड़ता है। ऐप्पल के पास उनके कुछ एपीआई में भी यह गुस्सा है। यहाँ iOS 8 में एक नए पेश वर्ग से एक उदाहरण है (बीटा 5 के रूप में):

UIInputViewControllerकी textDocumentProxyसंपत्ति:

उद्देश्य-सी में परिभाषित निम्नानुसार है:

@property(nonatomic, readonly) NSObject<UITextDocumentProxy> *textDocumentProxy;

और स्विफ्ट में:

var textDocumentProxy: NSObject! { get }

Apple के दस्तावेज़ से लिंक करें: https://developer.apple.com/library/prerelease/iOS/documentation/UIKit/Reference/UIInputViewController_Class/index.html#//apple -ref/occ/ instp /UIInputViewController/ textDocumentProxyProxmentProxy


1
ऐसा लगता है कि स्वतः उत्पन्न: स्विफ्ट प्रोटोकॉल को ऑब्जेक्ट के रूप में चारों ओर से पारित किया जा सकता है। सैद्धांतिक रूप से वे सिर्फ टाइप कर सकते हैंvar textDocumentProxy: UITextDocumentProxy! { get }
atlex2

@ atlex2 आपने UITextDocumentProxy प्रोटोकॉल प्रकार के पक्ष में NSObject वर्ग प्रकार खो दिया है।
टाइटेनियमडेकॉय

@titaniumdecoy नहीं आप गलत हैं; अगर आप UITextDocumentProxy को सबसे प्रोटोकॉल की तरह घोषित करते हैं तो आप अभी भी NSObject नहीं हैं:@protocol MyAwesomeCallbacks <NSObject>
CommaToast

@CommaToast स्विफ्ट में नहीं है, जो यह सवाल है।
टाइटेनियमडेकॉय

@titaniumdecoy हाँ, आप मूल रूप से सही थे। मैं भ्रमित था! क्षमा करें, आप गलत थे। उल्टा आप अभी भी NSObjectProtocol ... इस उदाहरण में करते हैं ... लेकिन मुझे पता है कि यह एक ही बात नहीं है।
कोमाटैस्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.