2015-04-09 11 views
9

मैं अपनी परियोजना में MKAnnotationView का उप-वर्ग बना रहा हूं। इसे सबव्यूज़ को संग्रहीत करने के लिए दो गुण होने की आवश्यकता है जिन्हें मुझे शुरुआत में कहीं भी शुरू करने की आवश्यकता है।स्विफ्ट में एमकेएनोटेशन व्यू सबक्लास के प्रारंभिकरणकर्ताओं को क्या प्रारंभ करना चाहिए?

MKAnnotationView इसके प्रलेखन, initWithAnnotation:reuseIdentifier: में डाला गया प्रारंभकर्ता है, इसलिए मुझे लगता है मैं बस उस ओवरराइड था लगा:

class PulsatingDotMarker: MKAnnotationView { 

    let innerCircle: UIView 
    let outerCircle: UIView 

    override init!(annotation: MKAnnotation!, reuseIdentifier: String!) { 
     innerCircle = ... 
     outerCircle = ... 

     super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) 
    } 

    ... 
} 

लेकिन यह एक क्रम अपवाद का कारण बनता है:

fatal error: use of unimplemented initializer 'init(frame:)' for class 'PulsatingDotMarker'

ठीक है, तो मैं अनुमान initWithAnnotation:reuseIdentifier: आंतरिक रूप से initWithFrame: पर कॉल करता है, इसलिए शायद यह है कि मुझे इसके बजाय ओवरराइड करना चाहिए। के कि कोशिश करते हैं:

class PulsatingDotMarker: MKAnnotationView { 

    let innerCircle: UIView 
    let outerCircle: UIView 

    override init(frame: CGRect) { 
     innerCircle = ... 
     outerCircle = ... 

     super.init(frame: frame) 
    } 

    ... 
} 

जब एनोटेशन दृश्य वस्तु बनाने हालांकि यह एक संकलन त्रुटि होती है:

Extra argument 'reuseIdentifier' in call

हम्म, इसलिए यदि मैं() की आवश्यकता प्रारंभकर्ता initWithFrame: लागू, यह अब डिफ़ॉल्ट प्रारंभकर्ता खो देता है initWithAnnotation:reuseIdentifier:?

शायद अगर मैंने initWithAnnotation:reuseIdentifier: का ओवरराइड जोड़ा जो केवल super पर कॉल करता है तो यह फिर से उपलब्ध होगा, क्या यह काम करेगा?

class PulsatingDotMarker: MKAnnotationView { 

    let innerCircle: UIView 
    let outerCircle: UIView 

    init!(annotation: MKAnnotation!, reuseIdentifier: String!) { 
     super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) 
    } 

    override init(frame: CGRect) { 
     innerCircle = ... 
     outerCircle = ... 

     super.init(frame: frame) 
    } 

    ... 
} 

नहीं, अभी भी नहीं अच्छा - संकलन त्रुटि:

Property 'self.innerCircle' not initialized at super.init call

ठीक है, क्या हुआ अगर मैं एक initWithFrame: था, लेकिन initWithAnnotation:reuseIdentifier: में subviews प्रारंभ? (? लेकिन फिर क्या हुआ अगर किसी को सिर्फ सीधे initWithFrame: कॉल ...)

class PulsatingDotMarker: MKAnnotationView { 

    let innerCircle: UIView 
    let outerCircle: UIView 

    init!(annotation: MKAnnotation!, reuseIdentifier: String!) { 
     innerCircle = ... 
     outerCircle = ... 

     super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) 
    } 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
    } 

    ... 
} 

नहीं आश्चर्यजनक रूप से, स्विफ्ट मुझे उस से मुझे बता द्वारा सुरक्षा करता है:

Property 'self.innerCircle' not initialized at super.init call

(initWithFrame: में इस समय)।

तो मुझे क्या करना चाहिए? मैं यहाँ और वहां दोनों सबव्यूव्यू नहीं बना सकता, है ना?

class PulsatingDotMarker: MKAnnotationView { 

    let innerCircle: UIView 
    let outerCircle: UIView 

    init!(annotation: MKAnnotation!, reuseIdentifier: String!) { 
     innerCircle = ... 
     outerCircle = ... 

     super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) 
    } 

    override init(frame: CGRect) { 
     innerCircle = ... 
     outerCircle = ... 

     super.init(frame: frame) 
    } 

    ... 
} 

गलत फिर से, यह वास्तव में काम करता है - भले ही मैं एक ही वस्तु में दो बार एक निरंतर संपत्ति बताए कर रहा हूँ (!)।

क्या किसी को पता है कि यह ठीक से कैसे किया जाना चाहिए?

(नोट: वर्ग भी एक आवश्यक initWithCoder: प्रारंभकर्ता कि सिर्फ पहला उदाहरण से fatalError कॉल शामिल है, लेकिन वस्तु एक स्टोरीबोर्ड से कभी नहीं बनाई गई है।)

+0

क्या होगा अगर subviews घोषित किया गया है 'var innerCircle: UIView!' के रूप में? यह "आवश्यक init (xxx)" त्रुटियों से बच सकता है। – Anna

+0

यह वही है जो मैंने किया है, लेकिन यह एक हैक की तरह लगता है - एक संपत्ति को शून्य और परिवर्तनीय के रूप में चिह्नित करता है, भले ही यह कंपाइलर को खुश करने के लिए नॉन-नल और स्थिर होना चाहिए ... –

+0

मैंने इसी तरह की समस्याओं पर कुछ समय बिताया, और एक टेस्ट प्रोजेक्ट बनाया जहां मुझे लगता है कि मैं इस कारण को काम करने में कामयाब रहा हूं (उद्देश्य सी क्लास '[स्वयं initWith ...]' विधि को अपने सार्वजनिक 'init' विधि में कॉल कर रहा है), लेकिन दुर्भाग्य से अभी तक कोई समाधान नहीं है - http://stackoverflow.com/questions/31161143/non-designated-initialiser-inheritance-from-objective-c-classes – Rupert

उत्तर

2

मेरे ऐप के लिए, समाधान मैं चुना घोषित करने के लिए है एक वैकल्पिक के रूप में सबव्यूशन और इसे initFrame में तत्काल करें ...

var innerCircle: UIView?

यहां मेरा कोड है ...

class EventAnnotationView: MKPinAnnotationView 
{  
    static var REUSE_ID = "EventAnnotationView" 

var imageView: UIImageView? 

override init(frame: CGRect) 
{ 
    super.init(frame: frame) 

    // Create subview for custom images 
    imageView = UIImageView(frame: CGRectMake(0, 0, 22, 22)) 

    ... 

} 

override init(annotation: MKAnnotation!, reuseIdentifier: String!) 
{ 
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier) 
} 

required init(coder aDecoder: NSCoder) 
{ 
    super.init(coder: aDecoder) 
} 
} 

एक हैक से कम लगता है :), लेकिन सबव्यूव एक वैकल्पिक है क्योंकि अधिक कोड/काम की आवश्यकता है।

उम्मीद है कि इससे मदद मिलती है।

8

दुर्भाग्य से MKAnnotationView आपको init(frame: CGRect) लागू करने के लिए मजबूर करता है जिसका अर्थ है कि आपको उस विधि में अपने सभी इंस्टेंस चर को भी प्रारंभ करना होगा।

This article यह थोड़ा बताते अधिक

चर कि केवल ये मान वे चर वैकल्पिक बनाने के लिए और init(frame: CGRect) में नहीं के बराबर करने के लिए उन्हें स्थापित करने के लिए में पारित साथ initialised जा सकता है।

इसका कारण यह है कि मुझे संदेह है कि एमकेएनोटेशन व्यू अपने उद्देश्य-सी इनिट विधि में self.initWithFrame: rect पर कॉल कर रहा है। ऐसा इसलिए है कि यदि उप-वर्ग initWithFrame:(CGRect) rect को ओवरराइड करता है तो इसे कॉल किया जाएगा। हालांकि, यह तेजी से एक समस्या का कारण बनता है क्योंकि यदि आप एक कस्टम नामित प्रारंभिक घोषणाकर्ता घोषित करते हैं तो आप सुपरक्लास के प्रारंभकर्ताओं का वारिस नहीं करते हैं। इसलिए आपको अपने उप-वर्ग में init(frame: CGRect) को लागू करना होगा।

मुझे UITableVeiwController के साथ एक ही समस्या है। इसका हेडर एक ही पैटर्न का पालन करना चाहता है। i.e दो faliable नामित प्रारंभिक।

यह मुझे बहुत दुखी करता है। पर आप क्या कर सकते हैं।

0

स्विफ्ट 3 में वास्तव में कुछ तोड़ दिया गया है, क्योंकि नामित प्रारंभकर्ता को वास्तव में रन टाइम पर आईओएस द्वारा नहीं बुलाया जा रहा है।

मैंने पाया अन्य उत्तर में सुझाव संकलित नहीं है (XCode 8.1 पर परीक्षण किया गया जीएम/आईओएस 10.1), लेकिन भर के विभिन्न हैकिंग के बाद मैंने पाया इस संयोजन काम करता है:

override init(annotation: MKAnnotation?, reuseIdentifier: String?) { 
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier); 

    /* Your actual init code */ 
} 

convenience init(frame: CGRect) { 
    self.init(annotation: nil, reuseIdentifier: nil); 
} 
संबंधित मुद्दे