您可以使用 categories/extensions 将 IBDesignable 属性添加到 UIView 吗?
Can you add IBDesignable properties to UIView using categories/extensions?
对于那些不知道我在说什么的人,Xcode 6.0 添加了新功能,IBDesignable 和 IBInspectable。
当您使用 IBInspectable 属性标记自定义视图时,这些属性会显示在 IB 的属性检查器中。
同样,当您使用 IBDesignable 标记自定义 UIView 子类时,Xcode 编译您的视图并调用代码以在 Xcode [=40] 中呈现您的视图对象=] 这样你就可以看到它们的样子了。
向自定义视图添加 IBDesignable 和 IBInspectable 属性的技术在 Swift 和 Objective-C 中几乎相同。 IBInspectable 属性出现在 Interface Builder Attributes Inspector 中,无论您使用哪种语言来定义它们。
我在 Objective-C 中创建了 UIView 的类别,在 Swift 中创建了 UIView 的扩展,以提升 borderWidth、cornerRadius、borderColor 和视图底层的 layerBackgroundColor 属性作为视图的属性。如果您更改 属性,extension/category 会根据需要进行类型转换并将更改转发到图层。
IBInspectable 部分效果很好。我看到并可以在 IB 属性检查器中设置新属性。
我本可以发誓,上周我的视图 category/extension 上的 IBDesignable 属性也起作用了,我可以在 IB 中看到我的自定义 UIView 类别呈现,其中图层属性已更改。这周它不起作用。
我是不是出现幻觉了?
现有系统 类 的 categories/extensions 可以在使用 IBDesignable 设置时在 Interface Builder 中绘制他们的自定义 UI 吗?
这个代码块对我来说效果很好。
import UIKit
public extension UIView {
@IBInspectable public var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
}
注意 从框架导入时它可能不起作用。我现在正在尝试找出原因。
自从发布这个问题后,我了解到@IBDesignable 不适用于 class 扩展。您可以添加标签,但它没有任何效果。
@IBDesignable 仅在自定义 class.For 示例中使用 UIView 扩展。 UILabel 是 UIView 的默认子class。它不会在那里工作,但如果您自定义 class 称为 MyUILabel subclassing UILabel。将 MyUILabel class 分配给您正在处理的标签。然后你在 UIView 扩展中的圆角半径将适用于这个 MyUILabel。
(我猜它对你有用的第一周是因为你正在处理一些习俗 class。)
我通过将一个@IBDesignable UIView 设置为我的视图控制器中的顶视图来为我的用例完成这项工作。我的特殊用例是让 ClassyKit 样式在默认 UIKit 视图的 Interface Builder 中可见,而不必为此进行子类化,而且效果很好。
以下是如何设置的示例:
// in Interface Builder set the class of your top view controller view to this
@IBDesignable class DesignableView: UIView {
}
extension UIView {
open override func prepareForInterfaceBuilder() {
subviews.forEach {
[=10=].prepareForInterfaceBuilder()
}
}
}
extension UILabel {
// just an example of doing something
open override func prepareForInterfaceBuilder() {
layer.cornerRadius = 8
layer.masksToBounds = true
backgroundColor = .red
textColor = .green
}
}
我能够使用下面的代码使其工作,但副作用是有时故事板中的 IB 代理会崩溃,因为它必须刷新太多 UI 元素。重新启动 Xcode 可以暂时解决问题,直到下次崩溃为止。也许这就是 OP 面临的问题
@IBDesignable
extension UIView
{
@IBInspectable
public var cornerRadius: CGFloat
{
set (radius) {
self.layer.cornerRadius = radius
self.layer.masksToBounds = radius > 0
}
get {
return self.layer.cornerRadius
}
}
@IBInspectable
public var borderWidth: CGFloat
{
set (borderWidth) {
self.layer.borderWidth = borderWidth
}
get {
return self.layer.borderWidth
}
}
@IBInspectable
public var borderColor:UIColor?
{
set (color) {
self.layer.borderColor = color?.cgColor
}
get {
if let color = self.layer.borderColor
{
return UIColor(cgColor: color)
} else {
return nil
}
}
}
}
这就是为什么我试图添加 where 子句以减少应该扩展此功能的子类:
Generic IBDesginables UIView extension
对于那些不知道我在说什么的人,Xcode 6.0 添加了新功能,IBDesignable 和 IBInspectable。
当您使用 IBInspectable 属性标记自定义视图时,这些属性会显示在 IB 的属性检查器中。
同样,当您使用 IBDesignable 标记自定义 UIView 子类时,Xcode 编译您的视图并调用代码以在 Xcode [=40] 中呈现您的视图对象=] 这样你就可以看到它们的样子了。
向自定义视图添加 IBDesignable 和 IBInspectable 属性的技术在 Swift 和 Objective-C 中几乎相同。 IBInspectable 属性出现在 Interface Builder Attributes Inspector 中,无论您使用哪种语言来定义它们。
我在 Objective-C 中创建了 UIView 的类别,在 Swift 中创建了 UIView 的扩展,以提升 borderWidth、cornerRadius、borderColor 和视图底层的 layerBackgroundColor 属性作为视图的属性。如果您更改 属性,extension/category 会根据需要进行类型转换并将更改转发到图层。
IBInspectable 部分效果很好。我看到并可以在 IB 属性检查器中设置新属性。
我本可以发誓,上周我的视图 category/extension 上的 IBDesignable 属性也起作用了,我可以在 IB 中看到我的自定义 UIView 类别呈现,其中图层属性已更改。这周它不起作用。
我是不是出现幻觉了?
现有系统 类 的 categories/extensions 可以在使用 IBDesignable 设置时在 Interface Builder 中绘制他们的自定义 UI 吗?
这个代码块对我来说效果很好。
import UIKit
public extension UIView {
@IBInspectable public var cornerRadius: CGFloat {
get {
return layer.cornerRadius
}
set {
layer.cornerRadius = newValue
layer.masksToBounds = newValue > 0
}
}
}
注意 从框架导入时它可能不起作用。我现在正在尝试找出原因。
自从发布这个问题后,我了解到@IBDesignable 不适用于 class 扩展。您可以添加标签,但它没有任何效果。
@IBDesignable 仅在自定义 class.For 示例中使用 UIView 扩展。 UILabel 是 UIView 的默认子class。它不会在那里工作,但如果您自定义 class 称为 MyUILabel subclassing UILabel。将 MyUILabel class 分配给您正在处理的标签。然后你在 UIView 扩展中的圆角半径将适用于这个 MyUILabel。 (我猜它对你有用的第一周是因为你正在处理一些习俗 class。)
我通过将一个@IBDesignable UIView 设置为我的视图控制器中的顶视图来为我的用例完成这项工作。我的特殊用例是让 ClassyKit 样式在默认 UIKit 视图的 Interface Builder 中可见,而不必为此进行子类化,而且效果很好。
以下是如何设置的示例:
// in Interface Builder set the class of your top view controller view to this
@IBDesignable class DesignableView: UIView {
}
extension UIView {
open override func prepareForInterfaceBuilder() {
subviews.forEach {
[=10=].prepareForInterfaceBuilder()
}
}
}
extension UILabel {
// just an example of doing something
open override func prepareForInterfaceBuilder() {
layer.cornerRadius = 8
layer.masksToBounds = true
backgroundColor = .red
textColor = .green
}
}
我能够使用下面的代码使其工作,但副作用是有时故事板中的 IB 代理会崩溃,因为它必须刷新太多 UI 元素。重新启动 Xcode 可以暂时解决问题,直到下次崩溃为止。也许这就是 OP 面临的问题
@IBDesignable
extension UIView
{
@IBInspectable
public var cornerRadius: CGFloat
{
set (radius) {
self.layer.cornerRadius = radius
self.layer.masksToBounds = radius > 0
}
get {
return self.layer.cornerRadius
}
}
@IBInspectable
public var borderWidth: CGFloat
{
set (borderWidth) {
self.layer.borderWidth = borderWidth
}
get {
return self.layer.borderWidth
}
}
@IBInspectable
public var borderColor:UIColor?
{
set (color) {
self.layer.borderColor = color?.cgColor
}
get {
if let color = self.layer.borderColor
{
return UIColor(cgColor: color)
} else {
return nil
}
}
}
}
这就是为什么我试图添加 where 子句以减少应该扩展此功能的子类: Generic IBDesginables UIView extension