swift vxi कंपाइलर त्रुटि: उद्देश्य-सी चयनकर्ता के साथ विधि एक ही उद्देश्य-सी चयनकर्ता के साथ पिछले घोषणा के साथ संघर्ष करता है




swift vxi (5)

उद्देश्य-सी विधि ओवरलोडिंग का समर्थन नहीं करता है, आपको एक अलग विधि नाम का उपयोग करना होगा। जब आपने UIViewController को विरासत में मिला तो आपने एनएसओब्जेक्ट को विरासत में मिला और कक्षा को ओब्जे-सी के लिए इंटरऑपबल बनाया। दूसरी ओर स्विफ्ट ओवरलोडिंग का समर्थन करता है, यही कारण है कि जब आप विरासत को हटाते हैं तो यह काम करता है।

मैं स्विफ्ट सीखना शुरू कर रहा हूं, और YouTube पर बहुत अच्छे स्टैनफोर्ड यूनिवर्सिटी वीडियो व्याख्यान का पालन कर रहा हूं। यदि आप रुचि रखते हैं या यह मदद करता है तो यहां एक लिंक दिया गया है (हालांकि मेरी समस्या को समझने की आवश्यकता नहीं है):

स्विफ्ट के साथ आईओएस 8 ऐप का विकास - 2. अधिक एक्सकोड और स्विफ्ट, एमवीसी

व्याख्यान का पालन करते समय मुझे एक बिंदु पर पहुंचा जहां (जहां तक ​​मैं कह सकता था) मेरा कोड वीडियो में कोड के समान था लेकिन मेरे सिस्टम पर मुझे एक कंपाइलर त्रुटि मिली। बहुत सारे परीक्षण और त्रुटि के बाद मैंने अपने कोड को दो उदाहरणों में कम करने में कामयाब रहा है, जिनमें से एक त्रुटि उत्पन्न करता है, दूसरा या जो नहीं करता है, लेकिन मुझे नहीं पता कि वास्तव में त्रुटि क्या है या इसे कैसे हल किया जा रहा है।

कोड जो त्रुटि बनाता है वह है:

import UIKit

class BugViewController: UIViewController
{
    func perform(operation: (Double) -> Double) {
    }

    func perform(operation: (Double, Double) -> Double) {
    }
}

यह निम्न संकलक त्रुटि बनाता है:

ऑब्जेक्टिव-सी चयनकर्ता 'प्रदर्शन' के साथ विधि 'प्रदर्शन', उसी उद्देश्य-सी चयनकर्ता के साथ पिछले घोषणा के साथ संघर्ष

UIViewController के उप-वर्गीकरण को आसानी से हटाकर कोड संकलित करता है:

import UIKit

class BugViewController
{
    func perform(operation: (Double) -> Double) {
    }

    func perform(operation: (Double, Double) -> Double) {
    }
}

कुछ अन्य जानकारी जो प्रासंगिक हो सकती है या नहीं भी हो सकती हैं:

  • मैंने हाल ही में योसामेट में अपग्रेड किया है।
  • जब मैंने एक्सकोड स्थापित किया, तो मैंने बीटा संस्करण (संस्करण 6.3 (6 डी 543q)) के साथ समाप्त किया क्योंकि (अगर मुझे सही याद है) यह वह संस्करण था जिसे मुझे ओएस एक्स के अपने संस्करण पर चलाने के लिए आवश्यक था।

मैं आधा उम्मीद कर रहा हूं कि यह कंपाइलर में एक बग है क्योंकि अन्यथा इससे मुझे कोई समझ नहीं आती है। किसी भी मदद बहुत आभारी रूप से प्राप्त!


समस्या UIViewController एक @objc वर्ग है। UIViewController से विरासत में होने पर, BugViewController भी @objc क्लास है।

इसका मतलब है कि इसे उद्देश्य-सी चयनकर्ताओं (विधि का नाम) के नियमों के अनुरूप होना चाहिए। विधियों func perform(operation: (Double) -> Double) और func perform(operation: (Double, Double) -> Double) दोनों एक ही चयनकर्ता @selector(perform:) चयनकर्ता @selector(perform:) । इसकी अनुमति नहीं है।

इसे हल करने के लिए, विभिन्न नामों का उपयोग करें: जैसे func perform1(operation: (Double) -> Double) और func perform2(operation: (Double, Double) -> Double)

मुझे लगता है कि इसे संभालने का सबसे अच्छा तरीका है अपने perform() विधियों को और वर्णनात्मक नाम देना। इन तरीकों से क्या करते हैं? वे व्यू कंट्रोलर की स्थिति कैसे बदलते हैं? विधि नामकरण की शैली के लिए एक महसूस करने के लिए अन्य UIViewController विधियों को देखें, या पढ़िए विधि नाम अभिव्यक्तिपूर्ण होना चाहिए और कक्षा के भीतर अद्वितीय होना चाहिए


जैसा कि पहले ही इसका उत्तर दिया जा चुका है, ओबीजेसी विधि ओवरलोडिंग (उसी नाम के साथ दो विधियों) का समर्थन नहीं करता है और एक्सकोड 7 के तहत स्विफ्ट 2 में इस तरह की समस्याओं को हल करने के लिए दो विकल्प हैं। एक विकल्प विशेषता का उपयोग कर विधि का नाम बदलना है: @objc(newNameMethod:)

func methodOne(par1, par2) {...}

@objc(methodTwo:)
func methodOne(par1) {...}

Xcode 7+ में इस समस्या को हल करने का एक और विकल्प किसी भी विधि, सबस्क्रिप्ट या प्रारंभिक उपयोगकर्ता को @nonobjc विशेषता लागू कर रहा है

func methodOne() {...}

@nonobjc
func methodOne() {...}

मैं खुद स्टैंड स्टैंडफोर्ड कोर्स भी ले रहा हूं और मैं यहां भी लंबे समय तक फंस गया हूं, लेकिन कुछ खोज के बाद, मुझे यहां से कुछ मिला: एक्सकोड रिलीज नोट्स और इसमें कुछ नीचे बताया गया है:

स्विफ्ट 1.2 @objc विधियों और प्रारंभकर्ताओं के प्रकार-आधारित ओवरलोडिंग की जांच करने के बारे में सख्त है, कुछ उद्देश्य-सी द्वारा समर्थित नहीं है।

// Has the Objective-C selector "performOperation:".
func performOperation(op: NSOperation) { /* do something */ }
// Also has the selector "performOperation:".
func performOperation(fn: () -> Void) {
    self.performOperation(NSBlockOperation(block: fn))
}

स्विफ्ट से आने पर यह कोड काम करेगा, लेकिन उद्देश्य-सी से आक्रमण किए जाने पर आसानी से क्रैश हो सकता है। इस समस्या को हल करने के लिए, स्विस कंपाइलर को उद्देश्य-सी रनटाइम में खोलने से रोकने के लिए उद्देश्य-सी द्वारा समर्थित एक प्रकार का उपयोग करें:

  • यदि यह समझ में आता है, तो सदस्य को @objc की अक्षमता अक्षम करने के लिए निजी के रूप में चिह्नित करें।
  • अन्यथा, एक डिफ़ॉल्ट मान के साथ एक डमी पैरामीटर का उपयोग करें, उदाहरण के लिए: _ nonobjc: () = ()। (19826275)

निजी उप-वर्गों में उद्देश्य-सी के संपर्क में आने वाली विधियों के ओवरराइड को @objc होने का अनुमान नहीं है, जिससे स्विफ्ट कंपाइलर क्रैश हो जाता है। किसी भी ओवरराइडिंग विधियों में स्पष्ट रूप से @objc विशेषता जोड़ें। (19935352)

एसडीके से प्रतीकों को उपलब्ध नहीं है जब एक परियोजना या कार्यक्षेत्र में त्वरित रूप से उपयोग करें जो स्विफ्ट का उपयोग करता है। (20349540)

मैंने जो किया वह ओवरराइड विधि के सामने बस "निजी" जोड़ रहा था:

    private func performOperation(operation: Double -> Double) {
    if operandStack.count >= 1 {
        displayValue = operation(operandStack.removeLast())
        enter()
    }
}

मुझे एक ही ओब्जे-सी हस्ताक्षर के साथ दो विधियां होने के कारण एक ही त्रुटि मिली:

static func prepareForUpSyncing(obj : NSManagedObject!) -> Bool
static func prepareForUpSyncing(objs : [NSManagedObject]!) -> Bool

रनटाइम पर अवांछित परिणामों की संभावना के कारण मैं उनमें से एक को @nonobjc के रूप में चिह्नित नहीं करना चाहता था। (अगर कोई संभावना नहीं है तो कोई मुझे सही कर सकता है)

दूसरी विधि में स्विफ्ट के बाह्य पैरामीटर नाम सुविधा (मैंने बाहरी नाम के समान बाहरी नाम बनाया) का उपयोग करके इसे हल किया, जो प्रभावी ढंग से ओबीजे-सी विधि हस्ताक्षर को बदलता है:

static func prepareForUpSyncing(objs objs : [NSManagedObject]!) -> Bool {




swift