IBDesignables的某种“全球”?

时间:2016-06-23 19:26:45

标签: ios uistoryboard nslayoutconstraint ibinspectable

在故事板中有一个UIView,约束例如“0.1”比例高度。

想象一下,对于许多不同场景中的视图,你有类似的约束“0.1”。

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

你必须在任何地方单独更改它。

是否有某种方法可以使用@IBInspectable和/或约束来制作一种“全局值”

这样您就可以一次性更改所有内容,并在故事板中一次性查看结果

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

请注意,以下Wain的解决方案可以完美运行:您可以设置一次值,并影响应用程序中的任何位置。但不幸的是,它只在运行时才这样做,你没有在故事板上看到它。

3 个答案:

答案 0 :(得分:4)

我还没有尝试过,这只是输入这里的借口错别字,但我会考虑在NSLayoutConstraint上创建一个扩展名,类似于:

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

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

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

commonConstant, type String, value name

所以,像这样,在故事板中的任何地方的每个约束上:

enter image description here

答案 1 :(得分:3)

我无法想办法让IB更新所有"实例"在设计时,单个实例的属性值发生变化(我认为这通常是不受欢迎的非标准行为)。我相当肯定它无法完成,因为我不认为IB会在IB会话期间在内存中保留自定义视图的实例。我认为它的作用是实例化视图,在其上设置属性,为渲染创建快照,然后释放它。

应该可以设置设置"默认"的属性。将来的视图实例使用的值。我们可以通过存储"默认"来实现这一点。 NSUserDefaults中的值(XCode' s),并读取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中)。为此,您可能必须使用上述技术并对其进行扩展,以在您的视图中使用自定义initWithCoder:方法中的代码。

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

答案 2 :(得分:2)

当我开始使用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
        }
    }
}

这可能是一个起点。希望它有所帮助