Some sort of “global” for IBDesignables?

前端 未结 3 1021
走了就别回头了
走了就别回头了 2021-01-12 08:34

In storyboard have a UIView, with a constraint for example \"0.1\" proportional height.

Imagine you have a similar constraint \"0.1\", on views in many different sce

相关标签:
3条回答
  • 2021-01-12 09:07

    I haven't tried it, and this is just typed in here so excuse typos, but I would consider creating an extension on NSLayoutConstraint, something along the lines of:

    let constants = [
        "bannerHeight" : CGFloat(50)
    ]
    
    extension NSLayoutConstraint {
    func setCommonConstant(name: String) {
        self.constant = constants[name]!
    }
    }
    

    and then using the user defined runtime attributes in Xcode so specify the name to use:

    commonConstant, type String, value name
    

    So, like this, on each Constraint anywhere in the storyboard:

    0 讨论(0)
  • 2021-01-12 09:15

    I tried to find something similar when i started developing using Storyboard and Interface Builder. Unfortunately, xCode is not so scalable and code centralization using Interface Builder can't be implemented easily as can be done in Android development for example.

    You could try something like this, use custom @IBDesignable attribute in UIView extension and change constraints values or adding constraint at runtime (but i don't know if it will affect Interface Builder too):

    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
            }
        }
    }
    

    It could be a starting point. Hope it helps

    0 讨论(0)
  • 2021-01-12 09:27

    I can't think of a way to make IB update all "instances" at design time when a single instance has a property value change (And I think this would generally be undesired and non-standard behavior). I'm fairly certain it can't be done because I don't think IB keeps an instance of your custom view in memory for the duration of the IB session. I think what it does is instantiate the view, set properties on it, snapshot it for rendering, then releases it.

    It should be possible to set up properties that set "default" values to be used by future instances of your view. We can achieve this by storing "default" values in NSUserDefaults (XCode's), and reading the default value inside initWithFrame:, which IB will call to initialize a new instance. We can gate all this default stuff using #if TARGET_INTERFACE_BUILDER so it doesn't show up at runtime on the device.

    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
    

    You could probably get closer to your original goal (updating all "instances" in IB) if you're okay with forcing IB to reload your xib/storyboard file altogether. To do this you'd likely have to use the technique above and extend it to include code in a custom initWithCoder: method on your view.

    Possibly possibly you could get really tricky and try to "touch" the xib file that is being edited, and that might prompt IB to reload?

    0 讨论(0)
提交回复
热议问题