Ios 在iPhone 6/6+中,UIBezierPath未在UIView的正确边框上绘制;

Ios 在iPhone 6/6+中,UIBezierPath未在UIView的正确边框上绘制;,ios,objective-c,uiview,uibezierpath,Ios,Objective C,Uiview,Uibezierpath,我有一个我使用了很长时间的类,它在UIView(或者从UIView继承的任何东西)周围绘制边框,并为该视图提供圆角。我今天做了一些测试(在升级到Xcode 7并首次在iOS 8.3上编译之后),发现当我在模拟器上运行iPhone 6/6+时,UIView的右边缘被截断(我没有实际的设备,但我假设结果是相同的) 下面是一个简单的例子。请注意我是如何给superview一个红色背景以使其跳出的。子视图是具有固定高度且与视图中心垂直对齐的UIView。这很有效。应将前缘和后缘固定到superview的

我有一个我使用了很长时间的类,它在
UIView
(或者从
UIView
继承的任何东西)周围绘制边框,并为该视图提供圆角。我今天做了一些测试(在升级到Xcode 7并首次在iOS 8.3上编译之后),发现当我在模拟器上运行iPhone 6/6+时,UIView的右边缘被截断(我没有实际的设备,但我假设结果是相同的)

下面是一个简单的例子。请注意我是如何给superview一个红色背景以使其跳出的。子视图是具有固定高度且与视图中心垂直对齐的UIView。这很有效。应将前缘和后缘固定到superview的边缘,如图中的约束所示。请注意内部的
ui标签
ui按钮
是如何居中的,但是
ui视图
容器在右侧被截断,即使正在绘制边框

以下是故事板设置。具有边框的
ui视图
具有固定高度,垂直居中,前缘和后缘固定在superview上:

最后,这里是代码。在
UIViewController
中,我要求这样的边框。如果我注释掉这段代码,视图看起来很好,当然,除了没有我想要的边界之外

BorderMaker *borderMaker = [[BorderMaker alloc] init];
[borderMaker makeBorderWithFourRoundCorners:_doneUpdatingView borderColor:[SharedVisualElements primaryFontColor] radius:8.0f];
以及BorderMaker类:

@implementation BorderMaker

- (void) makeBorderWithFourRoundCorners  : (UIView *) view
                             borderColor : (UIColor *) borderColor
                                  radius : (CGFloat) radius
{
    UIRectCorner corners = UIRectCornerAllCorners;
    CGSize radii = CGSizeMake(radius, radius);
    [self drawBorder : corners
         borderColor : borderColor
                view : view
               radii : radii];
}


- (void) drawBorder : (UIRectCorner) corners
        borderColor : (UIColor *) borderColor
               view : (UIView *) view
              radii : (CGSize) radii
{

    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:view.bounds
                                               byRoundingCorners:corners
                                                     cornerRadii:radii];

    // Mask the container view’s layer to round the corners.
    CAShapeLayer *cornerMaskLayer = [CAShapeLayer layer];
    [cornerMaskLayer setPath:path.CGPath];
    view.layer.mask = cornerMaskLayer;

    // Make a transparent, stroked layer which will dispay the stroke.
    CAShapeLayer *strokeLayer = [CAShapeLayer layer];
    strokeLayer.path = path.CGPath;
    strokeLayer.fillColor = [UIColor clearColor].CGColor;
    strokeLayer.strokeColor = borderColor.CGColor;
    strokeLayer.lineWidth = 1.5; // the stroke splits the width evenly inside and outside,
    // but the outside part will be clipped by the containerView’s mask.

    // Transparent view that will contain the stroke layer
    UIView *strokeView = [[UIView alloc] initWithFrame:view.bounds];
    strokeView.userInteractionEnabled = NO; // in case your container view contains controls
    [strokeView.layer addSublayer:strokeLayer];

    // configure and add any subviews to the container view

    // stroke view goes in last, above all the subviews
    [view addSubview:strokeView];

}

在这个类中的某个地方,视图边界似乎没有反映这样一个事实,即AutoLayout已经拉伸视图以填充较大的iPhone 6/6+屏幕宽度。只是一个猜测,因为我没有主意了。感谢您的帮助。谢谢

BorderMaker根据输入视图的当前大小创建各种图层和视图。当输入视图更改大小时,如何调整这些图层和视图的大小?回答:他们没有

您可以添加代码以各种方式更新大小,但我不推荐这样做。由于您无论如何都要舍入所有四个角,因此只需使用现有的
CALayer
支持来绘制边框、舍入角并屏蔽其内容,就可以更好地解决这一问题

下面是一个简单的
BorderView
类:

BorderView.h 现在,如果在序列图像板中创建视图并将其自定义类设置为
BorderView
,则可以在序列图像板中设置其边框:

请注意,我在情节提要中设置了“剪辑子视图”,因此如果子视图恰好超出
边框视图的圆形边界,它将剪辑子视图

如果在
边界视图上设置约束,它们将保持所有内容的大小和位置:


我解决了这个问题。问题是我在
UIViewController
viewDidLoad
方法中调用了这些
BorderMaker
方法。我所要做的就是将它移动到
viewdideappear
。据推测,正如Rob Mayoff所说,在视图传递给
BorderMaker
类时,自动布局还没有完成,因此它得到的帧没有考虑屏幕的大小,而只是使用IB中定义的宽度


经过一些尝试和错误,似乎
viewdide
是我可以在自动布局完成工作时使用的最早的生命周期方法。

Wow。谢谢你的详细回复。我遇到的问题是,我有许多不同的UIView(文本字段、视图、scollviews等),要将它们全部迁移到一个全新的类可能需要一整天的时间。如果我需要的话,我会的,但是为了这个应用的目的,我的首选是找到一种方法来修改BorderMaker类来处理这个问题,如果可能的话。再次感谢!很好的建议。我不明白为什么自动布局传递给bezier类的帧不是在屏幕上渲染的最终帧。可能在设置边框时自动布局还没有运行。无论如何,您可以在任何视图的图层上设置
borderColor
borderWidth
cornerRadius
属性。因此,您可以修改
BorderMaker
来实现它,而不是它现在所做的。我在实现这个建议时遇到的一个问题是,我在许多不同类型的视图上使用了这个BorderMaker类。所以我不知道这个类继承了什么。如果它继承自UIView,则我的UITextFields不能是它的子类。如果它继承自UITextField,那么我的UIScrollView不能是它的子类。等等我不知道如何解决这个问题(除了为我想要画边框的每种类型的视图创建这样的类之外)。实际上,
viewdilayoutsubviews
应该可以工作,并且可以避免在屏幕上瞬间出现没有边框的视图闪烁。
#import <UIKit/UIKit.h>

IB_DESIGNABLE
@interface BorderView : UIView

@property (nonatomic, strong) IBInspectable UIColor *borderColor;
@property (nonatomic) IBInspectable CGFloat borderWidth;
@property (nonatomic) IBInspectable CGFloat cornerRadius;

@end
#import "BorderView.h"

@implementation BorderView

- (void)setBorderColor:(UIColor *)borderColor {
    self.layer.borderColor = borderColor.CGColor;
}

- (UIColor *)borderColor {
    CGColorRef cgColor = self.layer.borderColor;
    return cgColor ? [UIColor colorWithCGColor:self.layer.borderColor] : nil;
}

- (void)setBorderWidth:(CGFloat)borderWidth {
    self.layer.borderWidth = borderWidth;
}

- (CGFloat)borderWidth {
    return self.layer.borderWidth;
}

- (void)setCornerRadius:(CGFloat)cornerRadius {
    self.layer.cornerRadius = cornerRadius;
}

- (CGFloat)cornerRadius {
    return self.layer.cornerRadius;
}

@end