Цвет границы UIView в построителе интерфейса не работает?

Я пытаюсь настроить свойства слоя вида через IB. Все работает, за исключением цвета границы (свойство layer.borderColor):

enter image description here

Я помню, что я столкнулся с этой проблемой год назад, и в итоге я сделал это программно. И все же я могу сделать это программно, но мне любопытно, почему свойство layer.borderColor никогда не работает через построитель интерфейсов. Я не хочу импортировать QuartzCore, а затем писать лишнюю строку кода только из-за этого, похоже на перебор.

Ответ 1

Это можно сделать, но это не встроенная функция. Это связано с тем, что тип Color на панели атрибутов User Defined Runtime Attributes создает UIColor, но layer.borderColor содержит тип CGColorRef. К сожалению, нет способа назначить тип CGColorRef в Interface Builder.

Однако это возможно через свойство прокси. См. Peter DeWeese ответ на другой вопрос для возможного решения этой проблемы. Его ответ определяет категорию, которая позволяет задать цвет прокси-сервера через Interface Builder.

Ответ 2

Вам нужно создать категорию для CALayer:

CALayer + UIColor.h

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>

@interface CALayer(UIColor)

// This assigns a CGColor to borderColor.
@property(nonatomic, assign) UIColor* borderUIColor;

@end

CALayer + UIColor.m

#import "CALayer+UIColor.h"

@implementation CALayer(UIColor)

- (void)setBorderUIColor:(UIColor*)color {
    self.borderColor = color.CGColor;
}

- (UIColor*)borderUIColor {
    return [UIColor colorWithCGColor:self.borderColor];
}

@end

И затем в Пользовательских атрибутах Runtime. Вы можете использовать его, как показано на рисунке ниже:

enter image description here

Для Swift это намного проще:

@IBInspectable var borderColor: UIColor? {
    didSet {
        layer.borderColor = borderColor?.CGColor
        layer.borderWidth = 1
    }
}

Затем в Xcode вы можете использовать его следующим образом:

enter image description here

Как только вы выберете sth, он автоматически добавится к вашим атрибутам времени выполнения:

Ответ 3

Мои два цента за портирование Бартломий Семанкика отвечают на Свифт:

Создайте расширение для CALayer в контроллере вида:

import UIKit

extension CALayer {
    func borderUIColor() -> UIColor? {
        return borderColor != nil ? UIColor(CGColor: borderColor!) : nil
    }

    func setBorderUIColor(color: UIColor) {
        borderColor = color.CGColor
    }
}

Ответ 4

Скопируйте и вставьте этот класс:

import UIKit

@IBDesignable class BorderView : UIView {
    @IBInspectable var borderColor: UIColor = .clear {
        didSet {
        layer.borderColor = borderColor.cgColor
        }
    }

    @IBInspectable var borderWidth: CGFloat = 0 {
        didSet {
            layer.borderWidth = borderWidth
        }
    }

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
        }
    }
}

Теперь в Interface Builder перейдите к инспектору Identity и задайте свое представление как класс CustomView.

После этого проверьте свой инспектор атрибутов:

Инспектор атрибутов с новыми опциями IBInspectable

Не нужно возиться с пользовательскими атрибутами времени выполнения. И ваши изменения также появятся на холсте!

Ответ 5

Вот быстрый способ преодолеть это. Категории...

@interface UIView (IBAppearance)

@property (nonatomic, strong) UIColor *borderColor;

@end

Вам не нужно его хранить, это просто приятно, поэтому вы можете запросить позже. Важное значение имеет значение значения и присвоение UIColor CGColor для слоя.

#import <objc/runtime.h>

#define BORDER_COLOR_KEYPATH @"borderColor"

@implementation UIView (IBAppearance)

- (void)setBorderColor:(UIColor *)borderColor {
    UIColor *bc = objc_getAssociatedObject(self, BORDER_COLOR_KEYPATH);
    if(bc == borderColor) return;
    else {
        objc_setAssociatedObject(self, BORDER_COLOR_KEYPATH, borderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        self.layer.borderColor = [borderColor CGColor];
    }
}

- (UIColor *)borderColor {
    return objc_getAssociatedObject(self, BORDER_COLOR_KEYPATH);
}

@end

Конечно, в Interface Builder вы не устанавливаете значение на layer.borderColor, а просто на borderColor.

Ответ 6

Используйте IBDesignable вместо Runtime Attributes, это более понятно.

Поместите этот код в любой класс и отредактируйте свойства непосредственно на раскадровке.

import UIKit

@IBDesignable extension UIView {
    @IBInspectable var borderColor:UIColor? {
        set {
            layer.borderColor = newValue!.CGColor
        }
        get {
            if let color = layer.borderColor {
                return UIColor(CGColor:color)
            }
            else {
                return nil
            }
        }
    }
    @IBInspectable var borderWidth:CGFloat {
        set {
            layer.borderWidth = newValue
        }
        get {
            return layer.borderWidth
        }
    }
    @IBInspectable var cornerRadius:CGFloat {
        set {
            layer.cornerRadius = newValue
            clipsToBounds = newValue > 0
        }
        get {
            return layer.cornerRadius
        }
    }
}

Ответ 7

В Swift вы можете расширить класс UIButton и добавить @IBInspectable, который позволит вам выбрать цвет из раскадровки и установить его цвет (с шириной 1, которая может быть изменена). Добавьте это в конец вашего контроллера вида:

extension UIButton{
    @IBInspectable var borderColor: UIColor? {
        get {
            return UIColor(CGColor: layer.borderColor!)
        }
        set {
            layer.borderColor = newValue?.CGColor
            layer.borderWidth = 1
        }
    }
}

Ответ 8

Чтобы сделать CALayer KVC-совместимым для свойства borderColorFromUIColor, просто выполните

layer.borderColorFromUIColor=[UIColor red];

Эта ссылка имеет awnser

Ответ 9

Я встретил ту же проблему, я работал вокруг нее, создав собственный класс кнопок:

class UIButtonWithRoundBorder: UIButton {

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.layer.cornerRadius = 6
    self.layer.borderWidth = 1
    self.layer.borderColor = UIColor.whiteColor().CGColor
    self.clipsToBounds = true
}

}

Затем в IB измените тип с "UIButton" на "UIButtonWithRoundBorder".

Просто и удобно.:)

Ответ 10

Я думаю, это может быть потому, что у вас есть maskSoBounds установлен на YES. Я не думаю, что граница рисуется в пределах слоя, поэтому она не будет нарисована, так как вы скрываете все за пределами ее границ.

Ответ 11

borderColor не будет работать, если для свойства borderWidth для слоя установлено значение больше 0.

Swift 3:

button.layer.borderColor = UIColor.white.cgColor
button.layer.borderWidth = 1.0 // Default value is 0, that why omitting this line will not make the border color show.

Ответ 12

Вы можете установить значение для ключа borderColor в XIB и использовать:

extension UIView {

    open override func setValue(_ value: Any?, forKey key: String) {
        guard key == "borderColor", let color = value as? UIColor else {
            super.setValue(value, forKey: key)
            return
        }

        layer.borderColor = color.cgColor
    }
}