Пользовательская клавиатура iOS 8 self.view.frame возвращает 0

Я пишу пользовательскую клавиатуру для iOS 8. Мой основной UIView возвращает {{0, 0}, {0, 0}} в моем методе viewDidLoad. Я попытался получить CGRect с помощью view.frame и bounds, но оба возвращают 0. Однако, если я использую эти же методы для получения координат моего представления в методе viewDidAppear, они возвращаются нормально: {{0, 0}, {320, 216}}. Проблема здесь в том, что viewDidAppear запускается после didLoad, поэтому я не могу получить размер из didAppear и использовать его в didLoad. Вот мой вопрос:

Почему фрейм self.view возвращает 0 в viewDidLoad? Разве его размер не должен быть установлен здесь? Здесь (viewDidLoad) я должен выполнять большую часть своей инициализации и настройки пользовательского интерфейса, верно? У меня есть умеренный опыт работы с Xcode.

Я программирую это быстро, хотя это не должно иметь значения (?). Я подумал, что это стоит отметить. Ответы в Obj-C в порядке.

Изменить: я создал совершенно новый проект Xcode и нацелился на следующий класс и получил ту же ошибку:

import UIKit

class KeyboardViewController: UIInputViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    println(self.view.frame) // returns (0.0,0.0,0.0,0.0)
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

override func viewDidAppear(animated: Bool) {
    println(self.view.frame) // returns (0.0,0.0,320.0,216.0)
}


}

Я также тестировал симулятор и физические устройства в диапазоне от 6 до 4S. Ничто, кажется, не имеет значения.


person Alex    schedule 25.09.2014    source источник
comment
у меня проблема, что println ничего не может напечатать в журнале консоли!   -  person TomSawyer    schedule 20.10.2014


Ответы (3)


Вы должны проверить с помощью self.inputView.frame вместо self.view.frame для пользовательской клавиатуры

Вы можете использовать метод isPortraitLayout, чтобы проверить/инициализировать вид, если его ландшафтный режим или портретный режим...

-(BOOL) isPortraitLayout{
    int appExtensionWidth = (int)round(self.view.frame.size.width);

    int possibleScreenWidthValue1 = (int)round([[UIScreen mainScreen] bounds].size.width);
    int possibleScreenWidthValue2 = (int)round([[UIScreen mainScreen] bounds].size.height);

    int screenWidthValue;

    if (possibleScreenWidthValue1 < possibleScreenWidthValue2) {
        screenWidthValue = possibleScreenWidthValue1;
    } else {
        screenWidthValue = possibleScreenWidthValue2;
    }

    return (appExtensionWidth == screenWidthValue);
}
person Leo Moon85    schedule 27.09.2014
comment
Это по-прежнему возвращает 0 в viewDidLoad, но не в viewDidAppear. Вот скриншот для пояснения: i.imgur.com/SJib6WZ.png - person Alex; 27.09.2014
comment
Я заметил, что вы не назначили никаких представлений (или Xibs) для inputView или представления. как только вы его назначите (т.е. self.inputView = self.Keyboard, где self.keyboard — это view/xib), вы получите значение кадра. - person Leo Moon85; 29.09.2014

Это общее свойство иерархии отображения представления (не только расширений клавиатуры), что размер кадра не будет правильным в viewDidLoad. См. здесь и < href="http://kevindew.me/post/18579273258/where-to-progmatically-lay-out-views-in-ios-5-and" rel="nofollow noreferrer">здесь, который также дает несколько советов о том, как обращаться с макетом.

Я бы рекомендовал использовать автоматическую раскладку (аналогично тому, как «nextKeyboardButton» делается в примере кода расширения клавиатуры), и в этом случае по большей части вам не придется беспокоиться об обработке изменений кадров. Например. в представленииDidLoad

    MyKeyboardView* keyboardView = [[keyboardView alloc] init];
    keyboardView.translatesAutoresizingMaskIntoConstraints = NO;

    [self.inputView addSubview: keyboardView];

    NSLayoutConstraint *leftSideConstraint = [NSLayoutConstraint constraintWithItem:keyboardView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.inputView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0];
    NSLayoutConstraint *rightSideConstraint = [NSLayoutConstraint constraintWithItem:keyboardView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.inputView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0];
    NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:keyboardView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.inputView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0];
    NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:keyboardView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.inputView attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];

    [self.inputView addConstraints:@[leftSideConstraint, rightSideConstraint, bottomConstraint, topConstraint]];

Таким образом, кадр для вашего keyboardView будет отслеживать кадр inputView (который установлен на размер кадра клавиатуры по умолчанию для ориентации и устройства) и, следовательно, будет автоматически изменять размер при изменении ориентации. Затем вы можете обрабатывать дополнительные настраиваемые макеты в layoutSubviews вашего класса MyKeyboardView. И последнее, если ваш MyKeyboardView выполняет какой-либо пользовательский рисунок в drawRect, вам нужно будет установить contentMode в init self.contentMode = UIViewContentModeRedraw; MyKeyboardView, иначе drawRect не будет вызываться при изменении кадра.

person kb1ooo    schedule 21.10.2014

Я мог бы заставить его работать, добавив текстовое поле сверху и сделав его FirstResponder:

import UIKit

class KeyboardViewController: UIInputViewController {
    
    @IBOutlet var textField: UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.becomeFirstResponder()
        println(self.view.frame) // returns (0.0,0.0,375.0,667.0)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
    }
    
    override func viewDidAppear(animated: Bool) {
        println(self.view.frame) // returns (0.0,0.0,375.0,667.0)

    }
}
person Steve Rosenberg    schedule 25.09.2014