在故事板中有一个UIView,约束例如“0.1”比例高度。
想象一下,对于许多不同场景中的视图,你有类似的约束“0.1”。
假设您要将值0.1更改为0.975。
你必须在任何地方单独更改它。
是否有某种方法可以使用@IBInspectable和/或约束来制作一种“全局值”?
这样您就可以一次性更改所有内容,并在故事板中一次性查看结果。
(当然,在运行时你可以在代码中传播它们。但最好在故事板上看到它。)
请注意,以下Wain的解决方案可以完美运行:您可以设置一次值,并影响应用程序中的任何位置。但不幸的是,它只在运行时才这样做,你没有在故事板上看到它。
答案 0 :(得分:4)
我还没有尝试过,这只是输入这里的借口错别字,但我会考虑在NSLayoutConstraint
上创建一个扩展名,类似于:
let constants = [
"bannerHeight" : CGFloat(50)
]
extension NSLayoutConstraint {
func setCommonConstant(name: String) {
self.constant = constants[name]!
}
}
然后在Xcode中使用用户定义的运行时属性,指定要使用的名称:
commonConstant, type String, value name
所以,像这样,在故事板中的任何地方的每个约束上:
答案 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
}
}
}
这可能是一个起点。希望它有所帮助