用户定义的运行时属性(IBInspectable)是否在预定义属性之后设置?

时间:2016-09-05 09:11:52

标签: ios storyboard interface-builder nib

我希望通过类别方法向IBInspectable添加新的UILabel属性(计算属性)。理想情况下,我希望在设置标签文本后设置此属性(通过setValue:forKey),因为此IBInspectable属性可能导致UILabels文本更新,我们不希望{{1}中的文本以后替换它。查看文档时,没有提及在Interface Builder中配置的属性的UILabel加载期间是否始终在用户定义的属性之前设置了预定义的属性。

使用nib/storyboard将自定义属性添加到Interface Builder中的对象,还是保证在标准预定义对象属性/属性之后设置用户定义的运行时属性?

2 个答案:

答案 0 :(得分:2)

以下实验的结论是,本地文本属性是在category属性之前设置的,因此类别setter可以安全地覆盖该值。

标签类别:

//  UILabel+Thingy.h

#import <UIKit/UIKit.h>

@interface UILabel (Thingy)

@property (nonatomic, strong) IBInspectable NSString *thingy;

@end

//  UILabel+UILabel_Thingy.m

#import "UILabel+Thingy.h"
#import <objc/runtime.h>

@implementation UILabel (Thingy)

- (NSString *)thingy {
    return objc_getAssociatedObject(self, @selector(thingy));
}

- (void)setThingy:(NSString *)thingy {
    NSLog(@"setting thingy to '%@', my text is currently '%@'", thingy, self.text);
    objc_setAssociatedObject(self, @selector(thingy), thingy, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

在IB中,设置可检查的类别属性和文本属性....

enter image description here

包含视图控制器中的一些小工具:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"didLoad text is '%@' and thingy is '%@'", self.label.text, self.label.thingy);
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    NSLog(@"willAppear text is '%@' and thingy is '%@'", self.label.text, self.label.thingy);
}

运行它,NSLog输出表明在从nib唤醒期间,native属性是在调用category属性setter时设置的......

  

... [794:41622]将东西设置为&#39; thingy value&#39;,我的文字目前是&#39;文字值&#39;

     

... [794:41622] didload text是&#39; text value&#39;而且物有所值&#39;

     

... [794:41622] willappear文字是&#39;文字值&#39;而且物有所值&#39;

在category属性setter中设置标签的text属性(并且我测试过它)会导致text属性被覆盖到thingy属性,因为text属性首先被初始化。

当呈现为XML时,可以在XIB文件中看到更多证据...

<label opaque="NO" (... all the native properties) text="text value" (...) id="XAM-6h-4fn">
    <rect key="frame" x="274" y="147" width="278" height="34"/>

    (... and so on)

    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="string" keyPath="thingy" value="thingy value"/>
    </userDefinedRuntimeAttributes>
</label>

...这与通过预订遍历实例化和初始化的视图一致,从而在(子标记)userDefinedRuntimeAttributes之前设置(父标记)标签属性。

答案 1 :(得分:0)

如果使用IBInspectable计算机变量创建扩展,则在Interface Builder中设置两个值时,置于Interface Builder中该自定义字段中的值将覆盖标签文本字段中的值,即使它将不能在Interface Builder中预览。

extension UILabel {

    @IBInspectable var value: String? {
        get {
            return text
        }

        set {
            text = newValue
            setNeedsDisplay()
        }
    }

}

Interface builder enter image description here