2016-02-03 8 views
21

में IBDesignable xib लोड नहीं कर सका मैं एक xib (childXib) ने अपने कस्टम UIView तेज फाइल करने के लिए लिंक की गई फ़ाइल है के माध्यम से यह Owner है।इंटरफ़ेस बिल्डर

error: IB Designables: Failed to render instance of MyRootView: The agent threw an exception. 

:

// init for IBDesignable 
override init(frame: CGRect) { 
    super.init(frame: frame) 

    let view = loadViewFromNib() 
    view.frame = bounds 

    addSubview(view) 
} 

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

func loadViewFromNib() -> UIView { 

    let bundle = NSBundle(forClass: self.dynamicType) 
    let nib = UINib(nibName: "CommentCellView", bundle: bundle) 
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView 

    return view 
} 

मैं इस xib (childXib) एक और xib (parentXib) में, मैं निम्नलिखित त्रुटियाँ प्राप्त जोड़ना चाहते हैं जब:

यह कैसे मैं अपने कस्टम UIView प्रारंभ है जहां MyRootView फ़ाइल parentXib

से जुड़ी फ़ाइल है

जहां MyIBDesignableCustomViewFilename फ़ाइल childXib से जुड़ी है।

जब मैंने इसे Identity inspector से Custom class में Debug पर क्लिक करके डिबग, यह है कि लाइन से काम नहीं करता है:

let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView 

सभी xib फ़ाइलों Build Phases में Copy Bundle Resources में हैं।

कोई विचार क्या गलत है?

+0

अपने xib का उपयोग करता है एक subclassed UIView है? यदि ऐसा है, तो आप इसे उस वर्ग में कास्ट करने का प्रयास करना चाहेंगे। – AMayes

+0

हां वे 'UIView' – Nico

+0

के सभी उप-वर्ग हैं, फिर 'देखें view = nib.instantiateWithOwner (स्वयं, विकल्प: शून्य) [0] के रूप में! MyCustomView' – AMayes

उत्तर

0

नीचे की तरह दोनों त्रुटियों के लिए:

  1. चेक अगर .xib फ़ाइलें हैं:

    error: IB Designables: Failed to render instance of .... 
    error: IB Designables: Failed to update auto layout status: The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle ... 
    

    मैं एक छोटे से जल्दी स्वयं सत्यापन के लिए यह पता लगाने की जहां मुद्दों को संबोधित किया जाना चाहिए मदद कर सकते हैं सुझाव है एक परियोजना

  2. चेक करने के लिए सही ढंग से जोड़ा है, तो nibName ठीक से सेट है, कभी कभी टाइपो यहां होता
  3. चेक अगर दोनों आउटलेट & कार्रवाई को उचित रूप से कनेक्ट कर रहे हैं, कोड कार्यान्वयन शामिल
14

पहला चरण:

मैं तुम्हें IBDesignable और IBInspectable का परिचय दे देंगे, और आप नए सुविधा का लाभ लेने के लिए कैसे लोगों को दिखाते हैं। डेमो बनाने की तुलना में सुविधा को विस्तारित करने का कोई बेहतर तरीका नहीं है। तो हम एक साथ "इंद्रधनुष" नामक एक कस्टम इंटरफेस का निर्माण करेंगे।

IBDesignable और IBInspectable

IBDesignable और IBInspectable साथ

, डेवलपर्स इंटरफेस (या देखें) कि वास्तविक समय में इंटरफ़ेस बिल्डर में renders बनाने की अनुमति है। सामान्य रूप से, इस नई सुविधा को लागू करने के लिए, आपको केवल यूआईवीव या यूआईसींट्रोल को उप-वर्गीकरण करके दृश्य वर्ग बनाना है और फिर स्विफ्ट में @IBDesignable कीवर्ड के साथ कक्षा का नाम उपसर्ग करना है। यदि आप उद्देश्य-सी का उपयोग कर रहे हैं, तो आप इसके बजाय IB_DESIGNABLE मैक्रो का उपयोग करें।यहाँ स्विफ्ट में एक नमूना कोड है:

@IBDesignable 
class Rainbow: UIView { 
} 

Xcode के पुराने संस्करणों में, आप उपयोगकर्ता परिभाषित क्रम एक वस्तु (जैसे layer.cornerRadius) इंटरफ़ेस बिल्डर में के गुणों को बदलने के लिए जिम्मेदार बताते हैं संपादित कर सकते हैं। समस्या यह है कि आपको गुणों के सटीक नाम में कुंजी रखना है। IBInspectable एक कदम आगे लेता है। जब आप IBInspectable साथ दृश्य वर्ग के एक प्रॉपर्टी उपसर्ग, संपत्ति इंटरफ़ेस बिल्डर से अवगत कराया जाएगा इस तरह है कि आप एक बहुत सरल तरीके से अपने मूल्य बदल सकते हैं:

enter image description here

फिर आप अपने अनुप्रयोग विकसित कर रहे हैं, तो स्विफ्ट में, आपको बस अपनी चुनी हुई संपत्ति को कीवर्ड @IBInspectable के साथ उपसर्ग करना है। यहां एक नमूना कोड का टुकड़ा है:

@IBInspectable var firstColor: UIColor = UIColor.blackColor() 
{ 
    // Update your UI when value changes 
} 



@IBInspectable var firstColor: UIColor = UIColor.blackColor() 
{ 
    // Update your UI when value changes 
} 

अपने Xcode प्रोजेक्ट

बिल्डिंग चलिए Xcode में एक नई परियोजना बनाने और एक टेम्पलेट के रूप एकल दृश्य आवेदन चुनें द्वारा आरंभ करने के लिए, और यह नाम RainbowDemo। हम प्रोग्रामिंग भाषा के रूप में इस परियोजना में स्विफ्ट का उपयोग करेंगे, इसलिए प्रोजेक्ट बनाने के दौरान इसे चुनना न भूलें।

एक बार समाप्त हो जाने के बाद, प्रोजेक्ट नेविगेटर में Main.storyboard का चयन करें और ऑब्जेक्ट लाइब्रेरी से व्यू कंट्रोलर पर एक ऑब्जेक्ट खींचें। इसका रंग # 38334 सी (या जो भी रंग आप चाहते हैं) में बदलें और इसके आकार को 600 से 434 तक सेट करें। फिर इसे मुख्य दृश्य के केंद्र में रखें। दृश्य दृश्य के समान रंग में मुख्य दृश्य का रंग बदलने के लिए मत भूलना। युक्ति: यदि आप अपने कोड के लिए आरजीबी रंग मानों को बदलना चाहते हैं, तो बस अपना रंग पैलेट खोलें और आरजीबी मूल्यों को बदलने के लिए स्लाइडर टैब पर स्विच करें।

भ्रमित हो रहा है? कोई चिंता नहीं। प्रोजेक्ट डेमो के माध्यम से जाने के बाद आप समझेंगे कि मेरा क्या मतलब है।

एक्सकोड 6 के साथ, आपको सभी प्रकार के आईओएस उपकरणों का समर्थन करने के लिए दृश्य के लिए ऑटो लेआउट बाधाओं को कॉन्फ़िगर करना होगा। ऑटो लेआउट एक्सकोड के नवीनतम संस्करण में बहुत शक्तिशाली है। सरल बाधाओं के लिए, आप ऑटो लेआउट मेनू के मुद्दे विकल्प पर क्लिक कर सकते हैं और "अनुपलब्ध विवाद जोड़ें" चुन सकते हैं, और एक्सकोड दृश्य के लिए लेआउट बाधाओं को स्वचालित रूप से कॉन्फ़िगर कर देगा।

enter image description here

कस्टम दृश्य क्लास बनाना

अब जब कि तुम स्टोरीबोर्ड में दृश्य बना लिया है, यह हमारे कस्टम दृश्य वर्ग बनाने के लिए समय है। हम वर्ग निर्माण के लिए स्विफ्ट क्लास टेम्पलेट का उपयोग करेंगे। इसे "इंद्रधनुष" नाम दें।

enter image description here

Then insert the following code in the class: 

import UIKit 

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

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

जैसा कि पहले उल्लेख किया है, दृश्य वर्ग UIView का एक उपवर्ग है। लाइव प्रतिपादन में हमारी कस्टम कक्षा का उपयोग करने के लिए, हमें ऊपर दिखाए गए दोनों प्रारंभकर्ताओं को ओवरराइड करने की आवश्यकता है। अगला सहायक संपादक का चयन करके दृश्य विभाजित:

enter image description here

इसके बाद,, सहायक संपादक में मुख्य स्टोरीबोर्ड चुनें, ताकि आप देख सकते हैं कि आप वास्तविक समय में निर्माण कर रहे हैं।

कार्यान्वयन IBDesignable नियंत्रित करता है

पहला कदम को लाइव प्रतिपादन के लिए एक नियंत्रण से designable के रूप में कस्टम दृश्य सेट करने के लिए सक्षम करने के लिए है: पहचान निरीक्षक के तहत "रेनबो" को देखने के वर्ग के नाम को बदलने के लिए याद रखें @IBDesignable साथ वर्ग के नाम लगाकर:

@IBDesignable 
class Rainbow: UIView { 
    ... 
} 

यह थोड़े सरल रूप में आप देख सकते हैं। लेकिन यह सरल कीवर्ड आपके विकास को अधिक आसान बना देगा। इसके बाद, हम मंडलियों के रंगों को सेट करने के लिए कुछ गुण जोड़ देंगे। इंद्रधनुष वर्ग में कोड की इन पंक्तियों के सम्मिलित करें:

@IBInspectable var firstColor: UIColor = UIColor(red: (37.0/255.0), green: (252.0/255), blue: (244.0/255.0), alpha: 1.0) 
@IBInspectable var secondColor: UIColor = UIColor(red: (171.0/255.0), green: (250.0/255), blue: (81.0/255.0), alpha: 1.0) 
@IBInspectable var thirdColor: UIColor = UIColor(red: (238.0/255.0), green: (32.0/255) 

यहाँ, हम एक डिफ़ॉल्ट रंग के साथ प्रत्येक संपत्ति परिभाषित कर लेते हैं, और देखने के लिए हर बार एक उपयोगकर्ता अपने मूल्य में परिवर्तन पुनः बनाने का यह बताओ। सबसे महत्वपूर्ण बात यह है कि हम प्रत्येक संपत्ति को @IBInspectable कीवर्ड से उपसर्ग करते हैं। यदि आप दृश्य के निरीक्षण योग्य गुणों पर जाते हैं, तो आपको इन गुणों को दृष्टि से देखना चाहिए:

कूल, है ना? गुणों को IBInspectable के रूप में इंगित करके, आप रंग पिकर का उपयोग करके उन्हें दृष्टि से संपादित कर सकते हैं।

ठीक है चलो इंद्रधनुष वर्ग के मुख्य तरीकों को लागू करने के लिए आगे बढ़ें, जिसका उपयोग स्क्रीन पर एक सर्कल खींचने के लिए किया जाता है। कक्षा में निम्न विधि सम्मिलित करें:

func addOval(lineWidth: CGFloat, path: CGPathRef, strokeStart: CGFloat, strokeEnd: CGFloat, strokeColor: UIColor, fillColor: UIColor, shadowRadius: CGFloat, shadowOpacity: Float, shadowOffsset: CGSize) { 

    let arc = CAShapeLayer() 
    arc.lineWidth = lineWidth 
    arc.path = path 
    arc.strokeStart = strokeStart 
    arc.strokeEnd = strokeEnd 
    arc.strokeColor = strokeColor.CGColor 
    arc.fillColor = fillColor.CGColor 
    arc.shadowColor = UIColor.blackColor().CGColor 
    arc.shadowRadius = shadowRadius 
    arc.shadowOpacity = shadowOpacity 
    arc.shadowOffset = shadowOffsset 
    layer.addSublayer(arc) 
} 

enter image description here

कोड स्वच्छ और पठनीय बनाने के लिए हम फोन करने वाले द्वारा प्रदान की मानकों के अनुसार एक भरा है या आधा सर्कल ड्राइंग के लिए एक आम तरीका पैदा करते हैं। CAShapeLayer क्लास का उपयोग करके सर्कल या एक चाप खींचने के लिए यह बहुत सरल है। आप स्ट्रोक स्टार्ट और स्ट्रोक एंड गुणों का उपयोग करके स्टोक की शुरुआत और अंत को नियंत्रित कर सकते हैं। 0.0 और 1.0 के बीच stokeEnd के मान को बदलकर, आप एक पूर्ण या आंशिक सर्कल खींच सकते हैं। बाकी गुणों का उपयोग स्ट्रोक, छाया रंग इत्यादि के रंग को सेट करने के लिए किया जाता है। आप कैशपलेयर में उपलब्ध सभी गुणों के विवरण के लिए आधिकारिक दस्तावेज़ीकरण देख सकते हैं।

इसके बाद, सम्मिलित इंद्रधनुष वर्ग में निम्न विधियों:

override func drawRect(rect: CGRect) { 
    // Add ARCs 
    self.addCirle(80, capRadius: 20, color: self.firstColor) 
    self.addCirle(150, capRadius: 20, color: self.secondColor) 
    self.addCirle(215, capRadius: 20, color: self.thirdColor) 
} 

func addCirle(arcRadius: CGFloat, capRadius: CGFloat, color: UIColor) { 
    let X = CGRectGetMidX(self.bounds) 
    let Y = CGRectGetMidY(self.bounds) 

    // Bottom Oval 
    let pathBottom = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath 
    self.addOval(20.0, path: pathBottom, strokeStart: 0, strokeEnd: 0.5, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero) 

    // Middle Cap 
    let pathMiddle = UIBezierPath(ovalInRect: CGRectMake((X - (capRadius/2)) - (arcRadius/2), (Y - (capRadius/2)), capRadius, capRadius)).CGPath 
    self.addOval(0.0, path: pathMiddle, strokeStart: 0, strokeEnd: 1.0, strokeColor: color, fillColor: color, shadowRadius: 5.0, shadowOpacity: 0.5, shadowOffsset: CGSizeZero) 

    // Top Oval 
    let pathTop = UIBezierPath(ovalInRect: CGRectMake((X - (arcRadius/2)), (Y - (arcRadius/2)), arcRadius, arcRadius)).CGPath 
    self.addOval(20.0, path: pathTop, strokeStart: 0.5, strokeEnd: 1.0, strokeColor: color, fillColor: UIColor.clearColor(), shadowRadius: 0, shadowOpacity: 0, shadowOffsset: CGSizeZero) 

} 

drawRect विधि के डिफ़ॉल्ट कार्यान्वयन कुछ नहीं करता है। दृश्य में मंडलियों को आकर्षित करने के लिए, हम अपने स्वयं के ड्राइंग कोड को लागू करने के लिए विधि को ओवरराइड करते हैं। addCircle विधि तीन पैरामीटर में लेती है: आर्कक्रियाडस, कैपराइडियस और रंग। arcRadius सर्कल का त्रिज्या है, जबकि capRadius गोलाकार टोपी का त्रिज्या है।

addCircle विधि आर्क्स आकर्षित करने के लिए UIBezierPath का उपयोग करता है और यह इस तरह काम करता है:

First it draws a half circle at the bottom 
Next it draws a full small circle at the edge of the arc. 
Finally, it draws the other half of the circle 

drawRect विधि में, हम addCircle विधि अलग त्रिज्या और रंग के साथ तीन बार कहते हैं। यह आंकड़ा बताता है कि मंडल कैसे खींचे जाते हैं: enter image description here

युक्ति: यदि आपको UIBezierPath के बारे में अधिक जानकारी चाहिए, तो आप ऐप्पल के आधिकारिक दस्तावेज़ीकरण को देख सकते हैं।

IBInspectable गुण के साथ

, अब आप कोड में गोता बिना इंटरफ़ेस बिल्डर में सही प्रत्येक चक्र का रंग बदलने के लिए स्वतंत्र हैं:

जाहिर है, आप आगे एक IBInspectable संपत्ति के रूप में arcRadius दिखा सकता है। मैं इसे आपके लिए एक अभ्यास के रूप में छोड़ दूंगा।

enter image description here

enter image description here

के लिए यहाँ उदाहरण कोड क्लिक

: https://github.com/appcoda/Rainbow-IBDesignable-Demo

+0

मैन, यह बिल्कुल पागल है, एक जवाब के लिए प्रयास की मात्रा! @prince का बहुत सम्मान है। –

+12

आईबी डिज़ाइन करने योग्य के लिए ग्रेट लिखित, लेकिन XIB फ़ाइलों के लिए उपयोगकर्ता के अनुरोध को संबोधित करने में विफल रहा। – mobilemonkey

+0

@mobilemonkey सहमत हुए। मुझे नहीं लगता कि यह जवाब बक्षीस के योग्य है। – Sid

4

मैं एक ही समस्या हो रही थी और मैं इसे ठीक करने में कामयाब रहे।

स्विफ्ट 3

let bundle = Bundle(for: MyView.self) 
let view = UINib(nibName: "MyView", bundle: bundle).instantiate(withOwner: self) as! MyView 

महत्वपूर्ण बिट बंडल

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