IBDesignables 的某种 "global"?

Some sort of "global" for IBDesignables?

在情节提要中有一个 UIView,具有例如“0.1”比例高度的约束。

假设您对许多不同场景中的视图有类似的约束“0.1”。

假设您要将值 0.1 更改为 0.975。

你必须在每个地方单独更改它。

有什么方法可以使用@IBInspectable and/or 约束来进行某种 "global value" 排序吗?

这样您就可以一次性更改所有内容,并一次性查看所有结果在情节提要

(当然,在 运行-time 你可以在代码中传播这些。但最好在故事板上看到它。)


请注意,例如,Wain 的以下解决方案非常有效:您可以设置一次值,并影响应用程序中的所有位置。但不幸的是,它只在 运行 时这样做,你不会在故事板上看到它。

我没试过,只是在这里输入,请原谅打字错误,但我会考虑在 NSLayoutConstraint 上创建一个扩展,类似于:

let constants = [
    "bannerHeight" : CGFloat(50)
]

extension NSLayoutConstraint {
func setCommonConstant(name: String) {
    self.constant = constants[name]!
}
}

然后在 Xcode 中使用用户定义的运行时属性,因此指定要使用的名称:

commonConstant, type String, value name

所以,就像这样,在情节提要中的任何地方的每个约束上:

当我开始使用 Storyboard 和 Interface Builder 进行开发时,我试图找到类似的东西。不幸的是,xCode 的可扩展性不强,使用 Interface Builder 的代码集中化无法像在 Android 开发中那样轻松实现。

您可以尝试这样的操作,在 UIView 扩展中使用自定义 @IBDesignable 属性并更改约束值或在运行时添加约束(但我不知道它是否也会影响 Interface Builder):

extension UIView {
    @IBInspectable var insertTopConstraint: Bool {
        set {
            // suppose 10 is your fixed value
            addConstraint(NSLayoutConstraint(item: self, attribute: .Top, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: 10))
            updateConstraintsIfNeeded() // could be useful..
        }
        get {
            return true
        }
    }
}

这可能是一个起点。希望对你有帮助

当单个实例发生 属性 值更改时,我想不出一种方法让 IB 在设计时更新所有 "instances"(而且我认为这通常是不希望的,也不是-标准行为)。我相当肯定它无法完成,因为我认为 IB 不会在 IB 会话期间在内存中保留您的自定义视图的实例。我认为它所做的是实例化视图,为其设置属性,对其进行快照以进行渲染,然后释放它。

应该可以设置设置 "default" 值的属性,以供视图的未来实例使用。我们可以通过在 NSUserDefaults (XCode's) 中存储 "default" 值,并读取 initWithFrame: 中的默认值来实现这一点,IB 将调用它来初始化一个新实例。我们可以使用 #if TARGET_INTERFACE_BUILDER 关闭所有这些默认内容,这样它就不会在运行时显示在设备上。

IB_DESIGNABLE
@interface CoolView : UIView

@property (strong, nonatomic) IBInspectable UIColor* frameColor;

#if TARGET_INTERFACE_BUILDER
@property (strong, nonatomic) IBInspectable UIColor* defaultFrameColor;
#endif

@end

@implementation CoolView

- (id) initWithFrame:(CGRect)frame
{
    self = [super initWithFrame: frame];
    if ( self != nil ) {

#if TARGET_INTERFACE_BUILDER
        NSData *colorData = [[NSUserDefaults standardUserDefaults] objectForKey: @"defaultCoolViewFrameColor"];
        if ( colorData != nil ) {
            self.frameColor = [NSKeyedUnarchiver unarchiveObjectWithData: colorData];;
        }
#endif

    }
    return self;
}

- (void) drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(context, 10);
    CGRect f = CGRectInset(self.bounds, 10, 10);
    [self.frameColor set];
    UIRectFrame(f);
}

#if TARGET_INTERFACE_BUILDER
- (void) setDefaultFrameColor:(UIColor *)defaultFrameColor
{
    _defaultFrameColor = defaultFrameColor;

    NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject: defaultFrameColor];
    [[NSUserDefaults standardUserDefaults] setObject:colorData forKey:@"defaultCoolViewFrameColor"];
}
#endif

@end

如果您同意强制 IB 重新加载您的 xib/storyboard 文件,您可能会更接近您的原始目标(更新 IB 中的所有 "instances")。为此,您可能必须使用上述技术并将其扩展以在视图中的自定义 initWithCoder: 方法中包含代码。

可能你会变得非常棘手并尝试 "touch" 正在编辑的 xib 文件,这可能会提示 IB 重新加载?