I have a xib
(childXib
) file linked to its custom UIView
swift file through it's Owner
.
我有一个xib (childXib)文件通过它的所有者链接到它的自定义UIView swift文件。
This is how I initialize my custom UIView
:
这就是我初始化自定义UIView的方法:
// 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
}
When I want to add this xib
(childXib
) in another xib
(parentXib
), I get the following errors:
当我想在另一个xib (parentXib)中添加这个xib (childXib)时,会得到以下错误:
error: IB Designables: Failed to render instance of MyRootView: The agent threw an exception.
Where MyRootView
is the file linked to parentXib
MyRootView的文件链接到parentXib在哪里
error: IB Designables: Failed to update auto layout status: The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle: 'NSBundle </Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Overlays> (loaded)' with name 'MyIBDesignableCustomViewFilename'
Where MyIBDesignableCustomViewFilename
is the file linked to childXib
.
其中MyIBDesignableCustomViewFilename是与childXib链接的文件。
When I debug it by clicking on Debug
in Custom class
from the Identity inspector
, it doesn't work from that line:
当我通过单击Identity inspector自定义类中的debug来调试它时,它在这行不起作用:
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
All the xib
files are in Copy Bundle Resources
in Build Phases
.
所有xib文件都在构建阶段的复制包资源中。
Any idea what's wrong?
知道有什么问题吗?
3 个解决方案
#1
15
First Step:
第一步:
I will give you an introduction to IBDesignable and IBInspectable, and show you guys how to take advantage of the new feature. There is no better way to elaborate a feature than creating a demo. So we will build a custom interface called “Rainbow” together.
我将向您介绍IBDesignable和IBInspectable,并向您展示如何利用这个新特性。没有比创建一个demo更好的方式来阐述特性了。因此,我们将一起构建一个名为“Rainbow”的自定义接口。
IBDesignable and IBInspectable
IBDesignable和IBInspectable
With IBDesignable and IBInspectable, developers are allowed to create interface (or view) that renders in Interface Builder in real time. In general, to apply this new feature, all you need to do is create a visual class by subclassing UIView or UIControl and then prefix the class name with @IBDesignable keyword in Swift. If you are using Objective-C, you use IB_DESIGNABLE macro instead. Here is a sample code in Swift:
使用IBDesignable和IBInspectable,开发人员可以创建接口(或视图),在接口构建器中实时呈现。通常,要应用这个新特性,只需通过子类化UIView或UIControl创建一个可视类,然后在Swift中使用@IBDesignable关键字对类名进行前缀。如果使用Objective-C,则使用IB_DESIGNABLE宏。以下是Swift代码示例:
@IBDesignable
class Rainbow: UIView {
}
In older versions of Xcode, you can edit the user-defined runtime attributes to change properties of an object (e.g. layer.cornerRadius) in Interface Builder. The problem is you have to key in the exact name of the properties. IBInspectable takes a step forward. When you prefix a property of the visual class with IBInspectable, the property will be exposed to the Interface Builder such that you can change its value in a much straightforward way:
在旧版本的Xcode中,您可以编辑用户定义的运行时属性来更改接口构建器中的对象的属性(例如,layer. radius - radius)。问题是你必须键入属性的确切名称。IBInspectable更进一步。当您在visual类的属性前面加上IBInspectable的前缀时,该属性将公开给接口构建器,以便您可以以一种非常简单的方式更改其值:
Again if you are developing your app in Swift, what you have to do is just prefix your chosen property with the keyword @IBInspectable. Here is a sample code snippet:
同样,如果您正在使用Swift开发应用程序,您需要做的就是在您选择的属性前面加上关键字@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
}
Building Your Xcode Project
建立你的Xcode项目
Let’s get started by creating a new project in Xcode and choose Single View Application as a template, and name it RainbowDemo. We will use Swift in this project as the programming language, so don’t forget to choose it when creating the project.
让我们从在Xcode中创建一个新项目开始,选择单个视图应用程序作为模板,并将其命名为RainbowDemo。我们将在这个项目中使用Swift作为编程语言,所以在创建项目时不要忘记选择它。
Once finished, select the Main.storyboard in the Project Navigator and drag a View object from the Object Library to the View Controller. Change its color to #38334C (or whatever color you want) as well as set its size to 600 by 434. Then put it in the center of the main view. Don’t forget to change the color of the main view to the same color of the view object. Tip: If you want to change the RGB Color values for your code, just open up your Color Palette and switch to the Sliders tab to alter the RGB values.
完成后,选择Main。在项目导航器中,将视图对象从对象库拖到视图控制器。将它的颜色更改为#38334C(或任何您想要的颜色),并将它的大小设置为600 * 434。然后把它放在主视图的中心。不要忘记将主视图的颜色更改为视图对象的相同颜色。提示:如果您想更改代码的RGB颜色值,只需打开颜色面板并切换到Sliders选项卡来更改RGB值。
Getting confused? No worries. You will understand what I mean after going through the project demo.
感到困惑吗?不用担心。通过项目演示,您将理解我的意思。
With Xcode 6, you have to configure auto layout constraints for the view in order to support all types of iOS devices. Auto Layout is pretty powerful in the latest version of Xcode. For simple constraints, you can just click the Issues option of the Auto Layout menu and choose “Add Missing Contraints”, and Xcode will automatically configure the layout constraints for the view.
使用Xcode 6,您必须为视图配置自动布局约束,以便支持所有类型的iOS设备。在最新版本的Xcode中,自动布局非常强大。对于简单的约束,您可以单击Auto Layout菜单的Issues选项,选择“添加缺失的约束”,Xcode将自动为视图配置布局约束。
Creating Custom View Class
创建自定义视图类
Now that you’ve created the view in storyboard, it’s time to create our custom view class. We’ll use the Swift class template for the class creation. Name it “Rainbow”.
既然您已经在故事板中创建了视图,现在是创建自定义视图类的时候了。我们将使用Swift类模板创建类。命名为“彩虹”。
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)
}
}
As mentioned before, the visual class is a subclass of UIView. In order to use our custom class in live rendering, we need to override both initializers as shown above. Next split the view by selecting the assistant editor:
正如前面提到的,visual类是UIView的一个子类。为了在实时呈现中使用我们的自定义类,我们需要覆盖上面所示的两个初始化器。接下来通过选择助理编辑器来分割视图:
Once done, select the main storyboard in the assistant editor, so you can see what you are building in real time. Remember to change the class name of the view to “Rainbow” under the Identity inspector:
一旦完成,在助理编辑器中选择主故事板,这样您就可以实时看到正在构建的内容。请记住在标识符检查器下将视图的类名更改为“Rainbow”:
Implementing IBDesignable Controls
实现IBDesignable控制
The first step to enable a control for live rendering is to set the custom view as Designable by prefixing the class name with @IBDesignable:
启用实时呈现控件的第一步是将自定义视图设置为可设计的,方法是在类名前面加上@IBDesignable:
@IBDesignable
class Rainbow: UIView {
...
}
It’s kinda simple as you can see. But this simple keyword would make your development much easier. Next, we will add a few properties for setting the colors of the circles. Insert these lines of code in the Rainbow class:
这就像你看到的一样简单。但是这个简单的关键字将使您的开发更加容易。接下来,我们将添加一些属性来设置圆圈的颜色。在Rainbow类中插入这些代码行:
@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)
Here, we predefine each property with a default colour, and tell it to redraw the view each time a user changes its value. Most importantly, we prefix each property with the @IBInspectable keyword. If you go to the Attributes inspectable of the view, you should find these properties visually:
在这里,我们用默认颜色预先定义每个属性,并告诉它在用户每次更改其值时重新绘制视图。最重要的是,我们用@IBInspectable关键字对每个属性进行前缀。如果您查看视图的属性检查表,您应该在视觉上找到这些属性:
Cool, right? By indicating the properties as IBInspectable, you can edit them visually using color picker.
很酷,对吧?通过将属性表示为IBInspectable,您可以使用颜色选择器来可视化地编辑它们。
Okay let’s move to implement the main methods of the Rainbow class, which is used to draw a circle on the screen. Insert the following method in the class:
好,让我们来实现彩虹类的主要方法,它用于在屏幕上画一个圆圈。在类中插入以下方法:
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)
}
To make the code clean and readable, we create a common method for drawing a full or half circle according to the parameters provided by the caller. It’s pretty straightforward to draw a circle or an arc using CAShapeLayer class. You can control the start and end of the stoke using the strokeStart and strokeEnd properties. By varying the value of stokeEnd between 0.0 and 1.0, you can draw a full or partial circle. The rest of the properties are just used to set the color of a stroke, shadow color, etc. You can check out the official documentation for details of all the properties available in CAShapeLayer.
为了使代码清晰易读,我们根据调用者提供的参数创建一个绘制完整或半圆的通用方法。使用CAShapeLayer类来画一个圆或弧是非常简单的。您可以使用strokeStart和strokeEnd属性控制stoke的起始和结束。通过在0.0和1.0之间改变stokeEnd的值,您可以绘制一个完整的或部分的圆。其余的属性只是用来设置描边、阴影颜色等的颜色。您可以查看官方文档,了解在CAShapeLayer中可用的所有属性的详细信息。
Next, insert the following methods in the Rainbow class:
接下来,在Rainbow类中插入以下方法:
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)
}
The default implementation of the drawRect
method does nothing. In order to draw circles in the view, we override the method to implement our own drawing code. The addCircle
method takes in three parameters: arcRadius, capRadius and color. The arcRadius
is the radius of the circle, while the capRadius
is the radius of the rounded cap.
drawRect方法的默认实现什么都不做。为了在视图中绘制圆圈,我们重写方法来实现我们自己的绘图代码。addCircle方法包含三个参数:圆弧半径、capRadius和color。弧半径是圆的半径,而帽半径是圆帽的半径。
The addCircle method makes use of UIBezierPath to draw the arcs and it works like this:
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
In the drawRect method, we call the addCircle method three times with different radius and color. This figure illustrates how the circles are drawn:
在drawRect方法中,我们三次调用不同半径和颜色的addCircle方法。这个图说明了圆圈是如何绘制的:
Tip: If you need more information about UIBezierPath, you can check out Apple’s official documentation.
提示:如果你需要更多关于UIBezierPath的信息,你可以查看苹果的官方文档。
With the IBInspectable properties, you are now free to change the color of each circle right in the Interface Builder without diving into the code:
通过IBInspectable属性,您现在可以在界面构建器中更改每个圆的颜色,而无需深入代码:
Obviously, you can further expose arcRadius as an IBInspectable property. I’ll leave it as an exercise for you.
显然,您可以将arcRadius公开为IBInspectable属性。我把它留给你作为练习。
for Example code click here: https://github.com/appcoda/Rainbow-IBDesignable-Demo
例如,代码点击这里:https://github.com/appcoda/Rainbow-IBDesignable-Demo
#2
4
I was having the same problem and I managed to fix it.
我遇到了同样的问题,我设法解决了它。
Swift 3
斯威夫特3
let bundle = Bundle(for: MyView.self)
let view = UINib(nibName: "MyView", bundle: bundle).instantiate(withOwner: self) as! MyView
The important bit is the bundle
重要的一点是包
#3
0
For both errors like below:
对于以下两个错误:
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 ...
I suggest to have a small quick self verification can help to figure out where the issues should be addressed:
我建议进行一次简短的自我验证,可以帮助我们找到问题应该解决的地方:
- Check if .xib files are added correctly in to a project
- 检查.xib文件是否正确地添加到项目中
- Check if nibName is set correctly, sometimes typo happens here
- 检查nibName是否设置正确,有时这里会发生错误
- Check if both outlet & action are connect appropriately, include codes implementation
- 检查outlet和action是否适当连接,包括代码实现
#1
15
First Step:
第一步:
I will give you an introduction to IBDesignable and IBInspectable, and show you guys how to take advantage of the new feature. There is no better way to elaborate a feature than creating a demo. So we will build a custom interface called “Rainbow” together.
我将向您介绍IBDesignable和IBInspectable,并向您展示如何利用这个新特性。没有比创建一个demo更好的方式来阐述特性了。因此,我们将一起构建一个名为“Rainbow”的自定义接口。
IBDesignable and IBInspectable
IBDesignable和IBInspectable
With IBDesignable and IBInspectable, developers are allowed to create interface (or view) that renders in Interface Builder in real time. In general, to apply this new feature, all you need to do is create a visual class by subclassing UIView or UIControl and then prefix the class name with @IBDesignable keyword in Swift. If you are using Objective-C, you use IB_DESIGNABLE macro instead. Here is a sample code in Swift:
使用IBDesignable和IBInspectable,开发人员可以创建接口(或视图),在接口构建器中实时呈现。通常,要应用这个新特性,只需通过子类化UIView或UIControl创建一个可视类,然后在Swift中使用@IBDesignable关键字对类名进行前缀。如果使用Objective-C,则使用IB_DESIGNABLE宏。以下是Swift代码示例:
@IBDesignable
class Rainbow: UIView {
}
In older versions of Xcode, you can edit the user-defined runtime attributes to change properties of an object (e.g. layer.cornerRadius) in Interface Builder. The problem is you have to key in the exact name of the properties. IBInspectable takes a step forward. When you prefix a property of the visual class with IBInspectable, the property will be exposed to the Interface Builder such that you can change its value in a much straightforward way:
在旧版本的Xcode中,您可以编辑用户定义的运行时属性来更改接口构建器中的对象的属性(例如,layer. radius - radius)。问题是你必须键入属性的确切名称。IBInspectable更进一步。当您在visual类的属性前面加上IBInspectable的前缀时,该属性将公开给接口构建器,以便您可以以一种非常简单的方式更改其值:
Again if you are developing your app in Swift, what you have to do is just prefix your chosen property with the keyword @IBInspectable. Here is a sample code snippet:
同样,如果您正在使用Swift开发应用程序,您需要做的就是在您选择的属性前面加上关键字@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
}
Building Your Xcode Project
建立你的Xcode项目
Let’s get started by creating a new project in Xcode and choose Single View Application as a template, and name it RainbowDemo. We will use Swift in this project as the programming language, so don’t forget to choose it when creating the project.
让我们从在Xcode中创建一个新项目开始,选择单个视图应用程序作为模板,并将其命名为RainbowDemo。我们将在这个项目中使用Swift作为编程语言,所以在创建项目时不要忘记选择它。
Once finished, select the Main.storyboard in the Project Navigator and drag a View object from the Object Library to the View Controller. Change its color to #38334C (or whatever color you want) as well as set its size to 600 by 434. Then put it in the center of the main view. Don’t forget to change the color of the main view to the same color of the view object. Tip: If you want to change the RGB Color values for your code, just open up your Color Palette and switch to the Sliders tab to alter the RGB values.
完成后,选择Main。在项目导航器中,将视图对象从对象库拖到视图控制器。将它的颜色更改为#38334C(或任何您想要的颜色),并将它的大小设置为600 * 434。然后把它放在主视图的中心。不要忘记将主视图的颜色更改为视图对象的相同颜色。提示:如果您想更改代码的RGB颜色值,只需打开颜色面板并切换到Sliders选项卡来更改RGB值。
Getting confused? No worries. You will understand what I mean after going through the project demo.
感到困惑吗?不用担心。通过项目演示,您将理解我的意思。
With Xcode 6, you have to configure auto layout constraints for the view in order to support all types of iOS devices. Auto Layout is pretty powerful in the latest version of Xcode. For simple constraints, you can just click the Issues option of the Auto Layout menu and choose “Add Missing Contraints”, and Xcode will automatically configure the layout constraints for the view.
使用Xcode 6,您必须为视图配置自动布局约束,以便支持所有类型的iOS设备。在最新版本的Xcode中,自动布局非常强大。对于简单的约束,您可以单击Auto Layout菜单的Issues选项,选择“添加缺失的约束”,Xcode将自动为视图配置布局约束。
Creating Custom View Class
创建自定义视图类
Now that you’ve created the view in storyboard, it’s time to create our custom view class. We’ll use the Swift class template for the class creation. Name it “Rainbow”.
既然您已经在故事板中创建了视图,现在是创建自定义视图类的时候了。我们将使用Swift类模板创建类。命名为“彩虹”。
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)
}
}
As mentioned before, the visual class is a subclass of UIView. In order to use our custom class in live rendering, we need to override both initializers as shown above. Next split the view by selecting the assistant editor:
正如前面提到的,visual类是UIView的一个子类。为了在实时呈现中使用我们的自定义类,我们需要覆盖上面所示的两个初始化器。接下来通过选择助理编辑器来分割视图:
Once done, select the main storyboard in the assistant editor, so you can see what you are building in real time. Remember to change the class name of the view to “Rainbow” under the Identity inspector:
一旦完成,在助理编辑器中选择主故事板,这样您就可以实时看到正在构建的内容。请记住在标识符检查器下将视图的类名更改为“Rainbow”:
Implementing IBDesignable Controls
实现IBDesignable控制
The first step to enable a control for live rendering is to set the custom view as Designable by prefixing the class name with @IBDesignable:
启用实时呈现控件的第一步是将自定义视图设置为可设计的,方法是在类名前面加上@IBDesignable:
@IBDesignable
class Rainbow: UIView {
...
}
It’s kinda simple as you can see. But this simple keyword would make your development much easier. Next, we will add a few properties for setting the colors of the circles. Insert these lines of code in the Rainbow class:
这就像你看到的一样简单。但是这个简单的关键字将使您的开发更加容易。接下来,我们将添加一些属性来设置圆圈的颜色。在Rainbow类中插入这些代码行:
@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)
Here, we predefine each property with a default colour, and tell it to redraw the view each time a user changes its value. Most importantly, we prefix each property with the @IBInspectable keyword. If you go to the Attributes inspectable of the view, you should find these properties visually:
在这里,我们用默认颜色预先定义每个属性,并告诉它在用户每次更改其值时重新绘制视图。最重要的是,我们用@IBInspectable关键字对每个属性进行前缀。如果您查看视图的属性检查表,您应该在视觉上找到这些属性:
Cool, right? By indicating the properties as IBInspectable, you can edit them visually using color picker.
很酷,对吧?通过将属性表示为IBInspectable,您可以使用颜色选择器来可视化地编辑它们。
Okay let’s move to implement the main methods of the Rainbow class, which is used to draw a circle on the screen. Insert the following method in the class:
好,让我们来实现彩虹类的主要方法,它用于在屏幕上画一个圆圈。在类中插入以下方法:
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)
}
To make the code clean and readable, we create a common method for drawing a full or half circle according to the parameters provided by the caller. It’s pretty straightforward to draw a circle or an arc using CAShapeLayer class. You can control the start and end of the stoke using the strokeStart and strokeEnd properties. By varying the value of stokeEnd between 0.0 and 1.0, you can draw a full or partial circle. The rest of the properties are just used to set the color of a stroke, shadow color, etc. You can check out the official documentation for details of all the properties available in CAShapeLayer.
为了使代码清晰易读,我们根据调用者提供的参数创建一个绘制完整或半圆的通用方法。使用CAShapeLayer类来画一个圆或弧是非常简单的。您可以使用strokeStart和strokeEnd属性控制stoke的起始和结束。通过在0.0和1.0之间改变stokeEnd的值,您可以绘制一个完整的或部分的圆。其余的属性只是用来设置描边、阴影颜色等的颜色。您可以查看官方文档,了解在CAShapeLayer中可用的所有属性的详细信息。
Next, insert the following methods in the Rainbow class:
接下来,在Rainbow类中插入以下方法:
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)
}
The default implementation of the drawRect
method does nothing. In order to draw circles in the view, we override the method to implement our own drawing code. The addCircle
method takes in three parameters: arcRadius, capRadius and color. The arcRadius
is the radius of the circle, while the capRadius
is the radius of the rounded cap.
drawRect方法的默认实现什么都不做。为了在视图中绘制圆圈,我们重写方法来实现我们自己的绘图代码。addCircle方法包含三个参数:圆弧半径、capRadius和color。弧半径是圆的半径,而帽半径是圆帽的半径。
The addCircle method makes use of UIBezierPath to draw the arcs and it works like this:
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
In the drawRect method, we call the addCircle method three times with different radius and color. This figure illustrates how the circles are drawn:
在drawRect方法中,我们三次调用不同半径和颜色的addCircle方法。这个图说明了圆圈是如何绘制的:
Tip: If you need more information about UIBezierPath, you can check out Apple’s official documentation.
提示:如果你需要更多关于UIBezierPath的信息,你可以查看苹果的官方文档。
With the IBInspectable properties, you are now free to change the color of each circle right in the Interface Builder without diving into the code:
通过IBInspectable属性,您现在可以在界面构建器中更改每个圆的颜色,而无需深入代码:
Obviously, you can further expose arcRadius as an IBInspectable property. I’ll leave it as an exercise for you.
显然,您可以将arcRadius公开为IBInspectable属性。我把它留给你作为练习。
for Example code click here: https://github.com/appcoda/Rainbow-IBDesignable-Demo
例如,代码点击这里:https://github.com/appcoda/Rainbow-IBDesignable-Demo
#2
4
I was having the same problem and I managed to fix it.
我遇到了同样的问题,我设法解决了它。
Swift 3
斯威夫特3
let bundle = Bundle(for: MyView.self)
let view = UINib(nibName: "MyView", bundle: bundle).instantiate(withOwner: self) as! MyView
The important bit is the bundle
重要的一点是包
#3
0
For both errors like below:
对于以下两个错误:
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 ...
I suggest to have a small quick self verification can help to figure out where the issues should be addressed:
我建议进行一次简短的自我验证,可以帮助我们找到问题应该解决的地方:
- Check if .xib files are added correctly in to a project
- 检查.xib文件是否正确地添加到项目中
- Check if nibName is set correctly, sometimes typo happens here
- 检查nibName是否设置正确,有时这里会发生错误
- Check if both outlet & action are connect appropriately, include codes implementation
- 检查outlet和action是否适当连接,包括代码实现