Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/102.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 视图控制器:如何正确初始化依赖于NIB的值_Ios_Objective C_Uiviewcontroller - Fatal编程技术网

Ios 视图控制器:如何正确初始化依赖于NIB的值

Ios 视图控制器:如何正确初始化依赖于NIB的值,ios,objective-c,uiviewcontroller,Ios,Objective C,Uiviewcontroller,我想知道初始化依赖于NIB中对象的值的最佳方法是什么。例如,假设我有一个ui视图,它获取一个自定义corneradius和borderColor 现在我要做的是 @interface MyViewController () @property (nonatomic, weak) IBOutlet UIView *roundyView; @end @implementation MyViewController - (id)initWithNibName:(NSString *)nibName

我想知道初始化依赖于NIB中对象的值的最佳方法是什么。例如,假设我有一个
ui视图
,它获取一个自定义
corneradius
borderColor

现在我要做的是

@interface MyViewController ()
@property (nonatomic, weak) IBOutlet UIView *roundyView;
@end

@implementation MyViewController

- (id)initWithNibName:(NSString *)nibNameOrNil 
               bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // (!) Can't assign to roundyView, hasn't been loaded from NIB yet
        // ...
    }
    return self;
}

-(void)viewDidLoad {
    // Ahh, NIB loaded, roundyView has a value
    self.roundyView.layer.cornerRadius = 5.0f;
    self.roundyView.layer.borderColor = [UIColor redColor].CGColor;
}

@end
到目前为止,一切顺利。接下来我添加了一个setter,这样我就可以从程序中的其他地方更改边框颜色

@property (nonatomic, strong) UIColor *roundBorderColor;

问题是,我通常在实例化类时调用该访问器,但在它出现之前。差不多

MyViewController *vc = [[MyViewController alloc] initWithNibName:@"MyViewController" 
                                                          bundle:nil];
// Setting the color, NIB hasn't loaded though (!)
vc.roundBorderColor = [UIColor yellowColor];
[self presentViewController:vc animated:YES completion:nil];
这不起作用,因为setter在
viewDidLoad
之前运行。因此,我通常会这样放置积垢:

-(void)viewDidLoad {
    // ...
    if (_roundBorderColor != nil) {
        // The setter was already called somewhere,
        // call it again now that we have the NIB
        [self setRoundBorderColor:_roundBorderColor];
    }
}

有没有更干净的方法来处理这个问题

通过在
initWithNibName
中初始化属性,您可以使它更干净一点,这样您就可以在
viewDidLoad
中安全地访问属性,而无需进行检查

-(id)initWithNibName:(NSString *)nibNameOrNil 
               bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        _roundBorderColor = [UIColor redColor];
    }
    return self;
}

-(void)viewDidLoad {
// ...

    [self setRoundBorderColor:_roundBorderColor];
}

转到Interface Builder中的identity inspector(Interface Builder视图左侧的第三个选项),并为您的视图设置“用户定义的运行时属性”并添加以下内容:
关键路径:图层。拐角半径值:数字,5。
不幸的是,这似乎不适用于边框颜色,因为UI只允许“颜色”,而不允许CGColor。
保持代码不受颜色影响的一个简单解决方法是将用户定义的属性设置到视图控制器,并通过nib进行设置。
在视图控制器中:

@property (nonatomic,strong) UIColor* borderColor;
然后在界面生成器中,通过用户定义的运行时属性将颜色设置为所需颜色。
然后在
viewDidLoad
中设置图层边框的颜色
涉及一些代码,而不仅仅是UI生成器,但至少不需要在代码中指定颜色。

或者,如果您只想使用代码设置颜色,而不想等待“viewDidLoad”,则可以执行以下操作:

-(void)setRoundBorderColor:(UIColor*)roundBorderColor {
    [self view]; // force view load from nib
    self.roundyView.layer.borderColor = roundBorderColor.CGColor;
}

您应该使用isViewLoaded方法

- (void)setRoundBorderColor:(UIColor *)roundBorderColor {
    _roundBorderColor = roundBorderColor;

    // would be launched only if view is initialised
    if ([self isViewLoaded]) {
        self.roundyView.layer.borderColor = roundBorderColor.CGColor;
    }
}

- (void)setBorderRagius:... // same idea as before

- (void)viewDidLoad {
    self.roundyView.layer.cornerRadius = self.cornerRadius;
    self.roundyView.layer.borderColor = self.borderColor;
}

您需要将一些默认值设置为cornerRadiusborderColor属性。如果要设置nil值,则不执行任何操作。

从Xcode 6开始,使用IBInspectable功能可以优雅地解决此问题。例如,在UIButton子类中:

@IBInspectable var borderColor : UIColor? {
    get {
        let cg = self.layer.borderColor
        return cg == nil ? nil : UIColor(CGColor: cg!)
    }
    set {
        self.layer.borderColor = newValue?.CGColor ?? nil
    }
}
故事板/xib中此按钮的一个实例现在在属性检查器中显示“borderColor”颜色弹出菜单


这设置了一个UIColor,但我们的属性只是层的
borderColor
的外观,并在UIColor和CGColor之间转换。

不错,我不知道有
isViewLoaded
方法。谢谢,我不知道“用户定义的运行时属性”。奇怪的是,似乎几乎没有关于这个特性的文档。一个名为“site:apple.com”的网站提供了20个邮件列表结果,没有官方文档。其他一些好文章:和。
@IBInspectable var borderColor : UIColor? {
    get {
        let cg = self.layer.borderColor
        return cg == nil ? nil : UIColor(CGColor: cg!)
    }
    set {
        self.layer.borderColor = newValue?.CGColor ?? nil
    }
}