iOS 8键盘扩展名出现呼叫栏时出现约束错误?

时间:2014-11-10 21:24:32

标签: objective-c ios8 autolayout nslayoutconstraint custom-keyboard

我注意到当我在手机上并且屏幕顶部出现绿色调用栏时,我的自定义键盘将不会出现(就像它被跳过一样)。所以我调试它并发现它是一个约束错误。

以下是调试器中的错误:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The layout constraints still need update after sending -updateViewConstraints to <KeyboardViewController: 0x16dfbe30>.
KeyboardViewController or one of its superclasses may have overridden -updateViewConstraints without calling super or sending -updateConstraints to the view. Or, something may have dirtied layout constraints in the middle of updating them.  Both are programming errors.'
*** First throw call stack:
(0x2ab43c1f 0x382eec8b 0x2ab43b65 0x2e6300ef 0x2b7cb5b9 0x2e630203 0x2e0ef4e9 0x2b7cb5b9 0x2e0ef2c3 0x2e630487 0x2e29ba8b 0x2e0004d7 0x2da28a0d 0x2da243e5 0x2da2426d 0x2da23c51 0x2da23a55 0x2dff8965 0x2ab0a3b5 0x2ab07a73 0x2ab07e7b 0x2aa56211 0x2aa56023 0x31e4f0a9 0x2e0621d1 0x389cf9fb 0x389d1021 0x2b916635 0x33956065 0x33955d3b 0x33956099 0x37c7a4fd 0x3886eaaf)
libc++abi.dylib: terminating with uncaught exception of type NSException

重要的是要注意,当没有调用栏时,我从未在方向或方向更改中收到任何错误/警告。我使用以下内容将键盘的高度从216调整到270:

- (id)initWithCoder:(NSCoder *)aDecoder {

    if (self = [super initWithCoder:aDecoder]) {

        //Prepare our keyboard's values
        self.portraitHeight = 270;
        self.landscapeHeight = 190;
    }

    return self;
}

- (void)updateViewConstraints {

    //Super
    [super updateViewConstraints];

    //Check if self.view exists
    if (WIDTH(self.view) == 0 || HEIGHT(self.view) == 0) {return;}

    //Remove any previous constraints
    [self.inputView removeConstraint:self.heightConstraint];

    //Define landscape mode
    self.isLandscape = !(self.view.frame.size.width == ([[UIScreen mainScreen] bounds].size.width * ([[UIScreen mainScreen] bounds].size.width < [[UIScreen mainScreen] bounds].size.height)) + ([[UIScreen mainScreen] bounds].size.height *([[UIScreen mainScreen] bounds].size.width > [[UIScreen mainScreen] bounds].size.height)));

    //Update view height depending on orientation
    if (self.isLandscape) {
        //Readjust our keyboard's height
        self.heightConstraint.constant = self.landscapeHeight;
        [self.inputView addConstraint:self.heightConstraint];
        self.view.frame = CGRectMake(0, 0, WIDTH(self.view), HEIGHT(self.view));
    } else {
        //Re-adjust our keyboard's height
        self.heightConstraint.constant = self.portraitHeight;
        self.heightConstraint.priority = 990;
        [self.inputView addConstraint:self.heightConstraint];
        self.view.frame = CGRectMake(0, 0, WIDTH(self.view), HEIGHT(self.view));
    }
}

&安培;这是我的观点WillAppear:

- (void)viewWillAppear:(BOOL)animated {

    //Update our keyboard's height when view appears
    self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.view
                                                         attribute:NSLayoutAttributeHeight
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:nil
                                                         attribute:NSLayoutAttributeNotAnAttribute
                                                        multiplier:0.0
                                                          constant:self.portraitHeight];
    self.heightConstraint.priority = 990;
    [self.view addConstraint:self.heightConstraint];
}

**注意:WIDTH()和HEIGHT()是宏。

我在xib中使用自动布局。我不知道从哪里开始解决这个问题。

更新

感谢您帮助调试此@Remus!我现在正试图检测设备是否在iOS 8的扩展程序中旋转,但我的updateConstraints方法仍未被调用。

- (void)viewDidLayoutSubviews {

    [super viewDidLayoutSubviews];
    [self.view setNeedsLayout];
    [self.view updateConstraintsIfNeeded];
    //I've also tried [self.view updateConstraints]; instead
}

- (void)updateConstraints {

    NSLog(@"Check Width");
    //Check if self.view exists
    if (WIDTH(self.view) == 0 || HEIGHT(self.view) == 0) {return;}

    NSLog(@"Remove Old Constraints");
    //Remove any previous constraints
    [self.inputView removeConstraint:self.heightConstraint];

    NSLog(@"Define Landscape");
    //Define landscape mode
    self.isLandscape = !(self.view.frame.size.width == ([[UIScreen mainScreen] bounds].size.width * ([[UIScreen mainScreen] bounds].size.width < [[UIScreen mainScreen] bounds].size.height)) + ([[UIScreen mainScreen] bounds].size.height *([[UIScreen mainScreen] bounds].size.width > [[UIScreen mainScreen] bounds].size.height)));

    NSLog(@"Update view height depending on orientation.");
    //Update view height depending on orientation
    if (self.isLandscape) {
        //Readjust our keyboard's height
        self.heightConstraint.constant = self.landscapeHeight;
        [self.inputView addConstraint:self.heightConstraint];
        self.view.frame = CGRectMake(0, 0, WIDTH(self.view), HEIGHT(self.view));
    } else {
        NSLog(@"Detected in portrait.");
        //Re-adjust our keyboard's height
        self.heightConstraint.constant = self.portraitHeight;
        self.heightConstraint.priority = 990;
        [self.inputView addConstraint:self.heightConstraint];
        self.view.frame = CGRectMake(0, 0, WIDTH(self.view), HEIGHT(self.view));
    }
}

- (void)viewWillAppear:(BOOL)animated {

    NSLog(@"View Did Appear: Add Constraint.");
    [self.view updateConstraints];

    //Update our keyboard's height when view appears
    self.heightConstraint = [NSLayoutConstraint constraintWithItem:self.view
                                                         attribute:NSLayoutAttributeHeight
                                                         relatedBy:NSLayoutRelationEqual
                                                            toItem:nil
                                                         attribute:NSLayoutAttributeNotAnAttribute
                                                        multiplier:0.0
                                                          constant:self.portraitHeight];
    self.heightConstraint.priority = 990;
    [self.view addConstraint:self.heightConstraint];
}

1 个答案:

答案 0 :(得分:1)

让我们尝试调用viewDidLayoutSubviews内的函数。这也可以在任何其他约束事件(如updateViewConstraints等)内单独调用。

- (void)viewDidLayoutSubviews {

    [super viewDidLayoutSubviews];
    [self setKeyboardConstraints];
}

- (void)setKeyboardConstraints {

    NSLog(@"Check Width");
    //Check if self.view exists
    if (WIDTH(self.view) == 0 || HEIGHT(self.view) == 0) {return;}

    NSLog(@"Remove Old Constraints");
    //Remove any previous constraints
    [self.inputView removeConstraint:self.heightConstraint];

    NSLog(@"Define Landscape");
    //Define landscape mode
    self.isLandscape = !(self.view.frame.size.width == ([[UIScreen mainScreen] bounds].size.width * ([[UIScreen mainScreen] bounds].size.width < [[UIScreen mainScreen] bounds].size.height)) + ([[UIScreen mainScreen] bounds].size.height *([[UIScreen mainScreen] bounds].size.width > [[UIScreen mainScreen] bounds].size.height)));

    NSLog(@"Update view height depending on orientation.");
    //Update view height depending on orientation
    if (self.isLandscape) {
        //Readjust our keyboard's height
        self.heightConstraint.constant = self.landscapeHeight;
        [self.inputView addConstraint:self.heightConstraint];
        self.view.frame = CGRectMake(0, 0, WIDTH(self.view), HEIGHT(self.view));
    } else {
        NSLog(@"Detected in portrait.");
        //Re-adjust our keyboard's height
        self.heightConstraint.constant = self.portraitHeight;
        self.heightConstraint.priority = 990;
        [self.inputView addConstraint:self.heightConstraint];
        self.view.frame = CGRectMake(0, 0, WIDTH(self.view), HEIGHT(self.view));
    }
}