4

是否可以创建一个UIView在 Xcode 中实时呈现的子类(通过添加此处IB_DESIGNABLE解释的属性)但没有自定义方法?drawRect:

我们有一个自定义UIView子类,它使用一些CAShapeLayer添加到self.layer绘图的 s (因此,不需要覆盖drawRect:)。此类在 App 上运行良好,但不会在 Xcode 上呈现。

如果我们复制其中的代码,drawRect:它可以工作,但我们更愿意让绘图在图层上自动发生。

这可以做到吗?


我也试过做

- (void)drawRect:(CGRect)rect
{
    CGContextRef currentContext = UIGraphicsGetCurrentContext();
    CGContextMoveToPoint(currentContext, self.myLayer1.frame.origin.x, self.myLayer1.frame.origin.y);
    [self.myLayer1 renderInContext:currentContext];
    CGContextMoveToPoint(currentContext, self.myLayer1.frame.origin.x, self.myLayer1.frame.origin.y);
    [self.myLayer2 renderInContext:currentContext];    
}

这似乎适用于设备但不适用于 Xcode 的 IB。

4

3 回答 3

4

即使没有被覆盖UIView,您也可以在 IB中预览子类(使用IB_DESIGNABLE宏)。 我在 XCode 6.1 中添加了您的代码并将 a 添加到文件中。然后我通过在选择器中设置断点来调试它(使用菜单/ ) 。 drawRect:
OEProgressIndicatorxibEditorDebug Selected ViewcommonProgressIndicatorInit

这就是为什么您在当前代码的预览中看不到任何内容的原因commonProgressIndicatorInit调用 (从initWithFrame:(CGRect)frame构造函数)时,frame等于CGRectZero( x:0 y:0 width:0 height:0),因此您的中心变量实际上等于(0, 0)并且半径是-1
在设备上,根据类的使用方式,您可能会被正确的帧直接调用,这就是为什么它可以在设备上工作但不能在 IB 中工作的原因。

为了解决这个问题,我将实现layoutSubviews选择器(从 覆盖它UIView)来正确组织子层。frame当要从更改CGRectZero为在 Interface Builder 中设置的正确值时,将调用此选择器。

于 2015-01-30T21:12:32.207 回答
2

我一直在使用该方法- (void)prepareForInterfaceBuilder来告诉 IB 实时渲染视图。

请参见此处:创建自定义对象的实时视图

另外,你们是对的,这个功能也适用于 Objective-C。

你不一定需要使用drawRect,你可以尝试使用- (void)layoutSubviews,它似乎工作。仅仅为了实时渲染而将代码留在地方的问题- (void)layoutSubviews是它可能性能较低等(例如,您可以在 中做很多事情- (void)awakeFromNib,但该方法不会从实时渲染中调用,所以只需确保您也完成了所有设置- (void)prepareForInterfaceBuilder

于 2014-10-25T21:51:34.753 回答
0

如果不查看所有代码,很难看出问题的根源是什么,但要回答您的问题,是的,您可以使用 IBInspectable / IBDesignable 而无需实现任何其他特定方法。我已经为使用许多图层且不进行任何绘图的视图(为此使用嵌套图层)完成了此操作。

对于带有圆角的快速测试示例片段:

@IBDesignable
class MyView : UIView {

    @IBInspectable var cornerRadius:CGFloat {
        get { return self.layer.cornerRadius }
        set { self.layer.cornerRadius = newValue    }
    }

    @IBInspectable var borderWidth:CGFloat {
        get { return self.layer.borderWidth }
        set { self.layer.borderWidth = newValue }
    }

    @IBInspectable var borderColor:UIColor {
        get { return UIColor(CGColor: self.layer.borderColor) }
        set { self.layer.borderColor = newValue.CGColor }
    }
}

有关进行渐变的简单示例,请参阅这篇文章

有关如何调试实时视图的说明,请参阅 WWDC §411 大约 22 分钟标记处。

到目前为止,我看到的唯一限制是您可以在类扩展中添加可检查的属性,但它们只能在设备上正确呈现。

于 2014-10-07T18:21:43.103 回答