【问题标题】:Some sort of "global" for IBDesignables?IBDesignables 的某种“全球性”?
【发布时间】:2016-10-26 07:03:02
【问题描述】:

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

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

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

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

有没有办法使用@IBInspectable 和/或约束来制作一种“全局价值”

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

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


请注意,例如,Wain 的以下解决方案完美运行:您可以设置一次值,并影响应用程序中的所有位置。但不幸的是,它只在运行时这样做,您在情节提要上看不到它。

【问题讨论】:

  • 也许我误解了你的问题,但你不能在单个视图控制器中限制两个容器视图相对于彼此的高度吗?如果我理解错了,你能举一个更具体的例子吗?
  • 我想我明白了。您是否尝试过创建具有该约束的IBDesignable 视图控制器类并将其用作UIViews 的基类?我也对这是否可能很感兴趣。
  • 错误信息是什么意思?
  • 我增加了一个大赏金!我已经清理了这里的一些老cmets。让我们希望得到一些关注
  • 很遗憾,这个问题没有真正好的解决方案!!也许我会尝试问一个更集中的问题,也许会出现其他想法。谢谢大家!! (我点了票数最高的赏金,以免被机器人浪费掉,干杯)苹果肯定会在未来添加这个功能,看起来很明显。

标签: ios uistoryboard nslayoutconstraint ibinspectable


【解决方案1】:

当单个实例具有属性值更改时,我想不出一种方法让 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 重新加载?

【讨论】:

  • 复杂。必须对此进行调查!
  • “我想不出在设计时让 IB 更新所有“实例”的方法”...这是一个好点。因此,当您拥有 ab IBDesignable 并更改代码(即使是微不足道的)时,它确实会“重新编译”整个故事板。所以我真的认为,实现我所说的唯一方法是,确实你必须有一个值在代码文件中,然后改变它。 (这仍然非常方便,比更改 100 个 IBInspectables 或约束要好得多。)
【解决方案2】:

我没有尝试过,这只是在这里输入的,所以请原谅拼写错误,但我会考虑在NSLayoutConstraint 上创建一个扩展,类似于:

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

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

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

commonConstant, type String, value name

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

【讨论】:

  • 你的意思是因为这是一个运行时的事情,而不是故事板中的设计时间/?
  • 它确实有效,虽然该代码中有很多错别字,但有所改进
  • 是的,没错。另一个答案很有趣,也许两者都可以结合起来添加一个可检查的约束,这样你就可以选择一些预设。我看不到一种方法可以更改 IB 中的单个设置并自动更新不同视图的所有约束...
  • 好的,我终于明白了! 这确实工作得很好,谢谢,我不知道你能做到这一点。 但是遗憾的是 不幸的是,这并没有在情节提要上更新......仅在运行时! 如果有一种方法可以像 IBInspectable 一样“立即”完成这项工作!
  • 是的,我看不出你会如何组合它们并让它同时处理多个项目,因为设计能力是基于实例的。唯一的另一种方法可能是约束的子类。尽管常量仍然需要在代码中,但也许可以将它与可设计一起使用。
【解决方案3】:

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

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

【讨论】:

  • 它适用于视图上的 UI 更改,并且它们在 IB 中可见,因为我没有尝试过并且可能会出错的约束。否则,您可以使用这种方法保持约束值集中。
  • Inspectable borderColor 对我来说只是一个实用程序,我使用它是因为我需要不同的颜色。如果您必须为约束实现它,您不必在所有地方都更改它,您只需在 IB 中设置 insertTopConstraint = true ,如果您想更改所有受影响视图的约束常量,您只需在可检查代码中更改它跨度>
  • 你似乎有正确的想法,我希望比我更聪明的人可以从那里解决! :)
猜你喜欢
  • 1970-01-01
  • 2011-03-26
  • 1970-01-01
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 1970-01-01
相关资源
最近更新 更多