我创建了 MyCustomView.xib / h / m:,它扩展了UIView
类。然后在我的Main.storyboard中,放置UIView
对象,将类更改为 MyCustomView 并链接到 MainController.h 。因此,MainController包含对MyCustomView实例的引用。
要从xib加载,在MyCustomView中我执行以下操作:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
if (self.subviews.count == 0) {
[self commonInit];
}
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self commonInit];
}
return self;
}
- (void) stretchToSuperView:(UIView*)view
{
view.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *bindings = NSDictionaryOfVariableBindings(view);
NSString *formatTemplate = @"%@:|[view]|";
for (NSString * axis in @[@"H",@"V"]) {
NSString * format = [NSString stringWithFormat:formatTemplate,axis];
NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings];
[view.superview addConstraints:constraints];
}
}
- (void)commonInit
{
MyCustomView* view = nil;
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"MyCustomView" owner:self options:nil];
view = views.firstObject;
[self addSubview:view];
[self stretchToSuperView:views.firstObject];
}
这很有效,直到我想在MyCustomView中声明委托才能通知MainController任何更改(按钮点击等)。所以,我的ManController符合MyCustomViewDelegate
并实现方法。
编辑1 设置代理
//MainViewController.m file
@interface MainViewController ()
@property (strong, nonatomic) IBOutlet MyCustomView *customView;
@end
@implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.customView.delegate = self;
}
这里的问题是委托变为零,我不明白原因,所以不知道错误是什么。
编辑2 我认为我有两个不同的MyCustomView实例。 我在MyCustomView中添加了新属性:
@interface MyCustomView : UIView
@property (weak, nonatomic) IBOutlet UIButton *firstItem;
@property(nonatomic, weak)id <MyCustomViewDelegate> delegate;
// this is test property
@property(nonatomic, assign)int testProperty;
@end
当我在viewDidLoad中设置此属性然后单击第一个按钮时,我看到testProperty的值为0.因此,这可能意味着IBOutlet MyCustomView * customView出现了问题。
答案 0 :(得分:0)
不幸的是,我无法做出简单的评论,因此我必须提出问题并提出建议,并回答问题。
首先,我不知道你在哪里设置委托给你的MainController,但我想在控制器的viewDidLoad()中。
第二件事。如何设置MyCustomView.xib非常重要,因为您创建了一个全新的对象MyCustomView,其属性将无法从控制器中获取。
MyCustomView* view = nil;
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"MyCustomView" owner:self options:nil];
view = views.firstObject;
[self addSubview:view];
在不知道xib的设置和委托的设置方法的情况下,我猜这有什么可以帮到你:
将您的子视图创建为UIView。
UIView* view = nil;
NSArray *views = [[NSBundle mainBundle] loadNibNamed:@"MyCustomView" owner:self options:nil];
view = views.firstObject;
[self addSubview:view];
self.myCustomView.delegate = self;
我希望它会有所帮助,如果没有,那么请用代理setter代码块和你的xib设置方法扩展你的问题。 (文件类所有者,根视图类等)
答案 1 :(得分:0)
你是对的,你有两个视图对象。您添加到故事板的那个以及您通过loadNibNamed
创建的那个。
底线,loadNibNamed
将为您创建视图(假设您已指定MyCustomView
作为NIB中指定的视图的基类;您可以将NIB的“文件所有者”留空)。然后,您可以在MyCustomView
中编写一个便捷方法来实例化基于NIB的视图:
+ (instancetype)myCustomViewWithDelegate:(id<MyCustomViewDelegate>)delegate {
NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"MyCustomView" owner:delegate options:nil];
MyCustomView *view = array.firstObject;
NSAssert([view isKindOfClass:[MyCustomView class]], @"Base class of NIB's top level view is not MyCustomView");
view.delegate = delegate;
return view;
}
然后,您必须以编程方式实例化并将其添加到视图层次结构中,而不是在故事板上指定视图,例如:
- (void)viewDidLoad {
[super viewDidLoad];
MyCustomView *view = [MyCustomView myCustomViewWithDelegate:self]; // since `self.myCustomView` should be `weak`, let's hold the view in local variable
[self.view addSubview:view];
self.myCustomView = view; // then set the property after the view is safely added to view hierarchy
NSDictionary *views = @{@"myCustomView" : self.myCustomView};
self.myCustomView.translatesAutoresizingMaskIntoConstraints = false;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[myCustomView]|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[myCustomView]|" options:0 metrics:nil views:views]];
// ...
}
显然,以编程方式添加视图时,您必须指定其frame
和autoresizingMask
,或使用如上所示的约束。