虽然崩溃信息非常清楚,但我检查了我的代码,一切看起来都很好。我唯一担心的是因为我在一个被设置为键盘附件视图的视图上设置约束,这可能是整个视图层次结构设置不正确的原因。
这是我正在做的事情:
步骤1:创建自定义配件视图(0到9之间的数字栏)并将其放在常规键盘上。
MyAccessoryView *anAccessoryView = [[MyAccessoryView alloc] initWithFrame:CGRectMake(0, 0, 320, 46.0f)];
anAccessoryView.delegate = self;
self.textField.inputAccessoryView = anAccessoryView;
第2步:在自定义配件视图(UIView的子视图)中,添加按钮和相关处理。将它们添加到超级视图,然后在延迟1秒后调用方法以添加约束。
- (id)initWithFrame:(CGRect)iFrame {
if (self = [super initWithFrame:iFrame]) {
[self refresh];
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
}
[self setExclusiveTouch:YES];
return self;
}
- (void)refresh {
if (!self.layoutController) {
self.layoutController = [[MyAccessoryViewLayoutController alloc] init];
}
self.backgroundColor = [self.layoutController colorForNumericInputAccessory:self];
self.userInteractionEnabled = YES;
NSMutableArray *buttonsArray = [NSMutableArray arrayWithCapacity:10];
// Adding number keys to the accessory view and setting thier properties
for (NSInteger i = 1; i < 11; i++) {
MyAccessoryViewNumericButton *aKeyboardButton = [MyAccessoryViewNumericButton buttonWithType:UIButtonTypeCustom];
aKeyboardButton.tag = i;
aKeyboardButton.frame = CGRectMake(0, 0, 32.0, 44);
[aKeyboardButton setTitle: [NSString stringWithFormat:@"%ld", (long)i % 10] forState:UIControlStateNormal];
NSString *aButtonImageTitle = [self.layoutController buttonNormalStateImageNameForIndex:(i % 10) forNumericInputAccessory:self];
[aKeyboardButton setBackgroundImage:[UIImage imageNamed:aButtonImageTitle] forState:UIControlStateNormal];
aKeyboardButton.backgroundColor = [UIColor clearColor];
[aKeyboardButton setTitleColor:[UIColor blackColor] forState: UIControlStateNormal];
[aKeyboardButton setExclusiveTouch:YES];
aKeyboardButton.titleLabel.font = [self.layoutController fontForButtonTitlesForNumericInputAccessory:self];
if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
aKeyboardButton.titleLabel.textAlignment = NSTextAlignmentCenter;
} else {
NSString *aButtonHighlightedImageTitle = [self.layoutController buttonHighlightedStateImageNameForIndex:(i % 10) forNumericInputAccessory:self];
[aKeyboardButton setBackgroundImage:[UIImage imageNamed:aButtonHighlightedImageTitle] forState:UIControlStateHighlighted];
}
aKeyboardButton.hidden = NO;
aKeyboardButton.enabled = YES;
aKeyboardButton.tag = i;
[aKeyboardButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:aKeyboardButton];
[buttonsArray addObject:aKeyboardButton];
if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
UIImage *aPressedButtonImage = [UIImage imageNamed:[self.layoutController buttonHighlightedStateImageNameForIndex:(i % 10) forNumericInputAccessory:self]];
CGRect aPressedButtonViewFrame = [self.layoutController frameForPressedButtonViewWithIndex:(i % 10) forNumericInputAccessory:self];
UIView *aPressedButtonView = [[UIView alloc] initWithFrame:aPressedButtonViewFrame];
aPressedButtonView.backgroundColor = [UIColor clearColor];
aPressedButtonView.userInteractionEnabled = YES;
aPressedButtonView.hidden = YES;
UIImageView *aPressedButtonImageView = [[UIImageView alloc] initWithImage:aPressedButtonImage];
aPressedButtonImageView.frame = CGRectMake(0.0, 0.0, aPressedButtonViewFrame.size.width, aPressedButtonViewFrame.size.height);
aPressedButtonImageView.contentMode = UIViewContentModeBottom;
aPressedButtonImageView.backgroundColor = [UIColor clearColor];
CGRect aPressedButtonLabelFrame = [self.layoutController frameForPressedButtonLabelWithIndex:(i % 10) forNumericInputAccessory:self];
UILabel *aPressedButtonLabel = [[UILabel alloc] initWithFrame:aPressedButtonLabelFrame];
aPressedButtonLabel.backgroundColor = [UIColor clearColor];
aPressedButtonLabel.text = [NSString stringWithFormat: @"%ld", (long)i % 10];
aPressedButtonLabel.textAlignment = NSTextAlignmentCenter;
aPressedButtonView.tag = i + 100;
aPressedButtonLabel.font = [UIFont fontWithName: @"Helvetica-Bold" size: 44.0f];
aPressedButtonLabel.shadowColor = [UIColor colorWithRed: 0.95f green: 0.95f blue: 0.95f alpha: 1.0f];
aPressedButtonLabel.shadowOffset = CGSizeMake(0.0f, 0.75f);
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication]statusBarOrientation])) {
aPressedButtonImageView.frame = CGRectMake(aPressedButtonImageView.frame.origin.x, aPressedButtonImageView.frame.origin.y - 2.0f, aPressedButtonImageView.frame.size.width, aPressedButtonImageView.frame.size.height);
}
[aPressedButtonView addSubview:aPressedButtonImageView];
[aPressedButtonView addSubview:aPressedButtonLabel];
[self addSubview:aPressedButtonView];
}
}
CALayer *aLightGreyBorder = [CALayer layer];
aLightGreyBorder.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y + 1.0f, self.bounds.size.width, 1.0f);
UIColor *aColor = [UIColor colorWithRed:178.0f/255.0f green:184.0f/255.0f blue:191.0f/255.0f alpha:1.0f];
aLightGreyBorder.backgroundColor = [aColor CGColor];
[self.layer insertSublayer:aLightGreyBorder atIndex:0];
CALayer *aDarkGreyBorder = [CALayer layer];
aDarkGreyBorder.frame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.bounds.size.width, 1.0f);
UIColor *aSecondColor;
aSecondColor = [UIColor colorWithRed:100.0f/255.0f green:100.0f/255.0f blue:100.0f/255.0f alpha:1.0f];
aDarkGreyBorder.backgroundColor = [aSecondColor CGColor];
[self.layer insertSublayer:aDarkGreyBorder atIndex:0];
if (self.layoutController.interfaceIdiom == UIUserInterfaceIdiomPhone) {
for (UIView *aPressedButtonView in [self subviews]) {
if ([aPressedButtonView isMemberOfClass:[UIView class]]) {
[self bringSubviewToFront:aPressedButtonView];
}
}
}
// Now lets add constaints
[self performSelector:@selector(addConstraintsForButtons:) withObject:buttonsArray afterDelay:1.0];
}
第3步:为所有按钮添加约束(0到9)。在这里,我只显示前2个按钮。
- (void)addConstraintsForButtons:(NSMutableArray *)iButtons {
// First Button
MyAccessoryViewNumericButton *firstButton = (MyAccessoryViewNumericButton *)iButtons[0];
// Left edge constraint for First button
NSLayoutConstraint *leading =[NSLayoutConstraint
constraintWithItem:firstButton
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:4.f];
[self addConstraint:leading];
// Middle in the super view
NSLayoutConstraint *vertical =[NSLayoutConstraint
constraintWithItem:firstButton
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0];
[self addConstraint:vertical];
// Width-Height Constraint for First button
[self addWHContraintForButton:firstButton];
// Second Button
MyAccessoryViewNumericButton *secondButton = (MyAccessoryViewNumericButton *)iButtons[1];
// Left edge constraint for First button
NSLayoutConstraint *secondLeading =[NSLayoutConstraint
constraintWithItem:secondButton
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:firstButton
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:4.f];
[secondButton addConstraint:secondLeading];
// Middle in the super view
NSLayoutConstraint *secondVertical =[NSLayoutConstraint
constraintWithItem:secondButton
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:firstButton
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0];
[secondButton addConstraint:secondVertical];
// Width-Height Constraint for Second button
[self addWHContraintForButton:secondButton];
// Add constaints to rest of the buttons...
}
- (void)addWHContraintForButton:(MyAccessoryViewNumericButton *)iButton {
CGFloat buttonWidth = 32.0f;
CGFloat buttonHeight = 44.0f;
// Height Constraint
NSLayoutConstraint *height = [NSLayoutConstraint
constraintWithItem:iButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:0
constant:buttonHeight];
// Width Constraint
NSLayoutConstraint *width = [NSLayoutConstraint
constraintWithItem:iButton
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:0
multiplier:0
constant:buttonWidth];
[iButton addConstraint:height];
[iButton addConstraint:width];
}
但是当我运行此代码时,它会崩溃并显示以下消息:
View not found in container hierarchy: <MyAccessoryViewNumericButton: 0x7fb506036f90; baseClass = UIButton; frame = (0 0; 32 44); opaque = NO; tag = 1; layer = <CALayer: 0x7fb506039c70>>
That view's superview: <MyAccessoryView: 0x7fb503ddfb50; frame = (0 0; 320 46); autoresize = W; layer = <CALayer: 0x7fb503dc1fe0>>
这是我在调试时看到的(通过在keyboardDidShow:
和didMoveToSuperview
方法中设置约束来尝试):
(lldb) po [secondButton superview]
<MyAccessoryView: 0x7fcd6d04f6c0; frame = (0 0; 320 46); autoresize = W; layer = <CALayer: 0x7fcd6adf5ed0>>
(lldb) po [[secondButton superview] superview]
<UIInputSetHostView: 0x7fcd6d0346c0; frame = (0 522; 320 262); layer = <CALayer: 0x7fcd6adef270>>
(lldb) po [[[secondButton superview] superview] superview]
<UIInputSetContainerView: 0x7fcd6d014000; frame = (0 0; 320 568); layer = <CALayer: 0x7fcd6add78d0>>
(lldb) po [[[[secondButton superview] superview] superview] superview]
<UITextEffectsWindow: 0x7fcd6d033c30; frame = (0 0; 320 568); opaque = NO; autoresize = W+H; layer = <UIWindowLayer: 0x7fcd6d034250>>
(lldb) po [[[[[secondButton superview] superview] superview] superview] superview]
0x0000000000000000
虽然视图有父级。有人可以在这里提出建议。