Методы macOS Sierra (setFrameOrigin / setFrame) не устанавливают фрейм NSButton

#objective-c #macos #macos-sierra

#objective-c #macos #macos-sierra

Вопрос:

Я просто пытаюсь изменить положение своих кнопок, немного отрегулировав его, чтобы он был правильно размещен в моем приложении. До сих пор в предыдущих версиях (минимум 10.8) он работал, но прямо в последней версии Mac (10.12 sierra) он каким-то образом не меняет свой фрейм или положение..

пример:

  -(void)awakeFromNib
{
  [self.mybutton setFrameOrigin:NSMakePoint(0,0)]; // not working...
  [self.mybutton setFrame:NSRectFromCGRect(CGRectMake(0,0,100,100)]; // also not working...
}
  

Я что-то упускаю? Это должно быть как прямая настройка frame.

Комментарии:

1. Извините, ложная тревога это было потому, что я использовал более старый Xcode (версия 7.3) для создания приложения, в результате чего setFrameOrigin не работал, поэтому я упаковываю новое приложение с последней версией Xcode.

Ответ №1:

Я столкнулся с той же проблемой.

У меня есть NSImageView в моем NSWindow , и мне нужно переместить его после того, как пользователь нажмет на него (это своего рода окно калибровки). Создается NSImageView с помощью Xcode 6.2 IB.

Однако по другим причинам мне нужно скомпилировать мое приложение с этой более старой версией Xcode (6.2, на Mavericks), поэтому я не могу обновиться до Xcode 8, как это было предложено OP в комментариях к вопросу. Я даже не пробовал решение OP.

TL; DR: Для меня это была проблема с автозаполнением. Похоже, что macOS 10.12 Sierra имеет более строгие правила автозапуска, чем в macOS 10.9-10.10-10.11 (где мое приложение тестируется и поддерживается). Перейдите сразу к варианту 3 для лучшего решения.

Вариант 1 (сбой в macOS 10.9):

Первый обходной путь — просто удалить NSView из своего супервизора, отправить setFrameOrigin , а затем повторно добавить его в супервизор:

 NSView *supView = myView.superview;
[myView setFrameOrigin:NSZeroPoint];
[supView addSubview:myView];
  

Это довольно хорошо работает в macOS 10.12 Sierra, однако при тестировании на Mavericks myView всегда застревает в позиции (0,0).

Затем я понимаю, что на самом NSWindow деле включена функция автозапуска и установлены некоторые ограничения для некоторых других NSView (но НЕ для myView ): я использую смешанный подход с ручной компоновкой и автоматической компоновкой.

Оказывается, это основная причина setFrameOrigin того, что в моем случае это не работает.

Вариант 2 (быстрый способ):

Есть волшебная ручка, которая поможет вам при переходе от традиционного подхода, не связанного с автоматическим описанием, к подходу с автоматическим описанием:

 myView.translatesAutoresizingMaskIntoConstraints = YES;
  

Я установил это в своей awakeFromNib перегрузке: теперь все работает правильно в macOS Sierra.

К сожалению, тестирование на Mavericks показывает некоторые проблемы (снова): хотя поведение правильное ( setFrameOrigin myView перемещается), Xcode выдает много предупреждений о автозаполнении на консоли. Однако это кажется одним шагом в правильном направлении и может быть окончательным решением для кого-то другого.

Вариант 3 (решение):

Определите некоторые NSLayoutConstraint s myView с помощью IB, затем используйте removeConstraints и addConstraints в супервизоре:

 NSView *supView = myView.superview;
[supView removeConstraints:@[self.bottomConstraint, self.rightConstraint]];
[supView addConstraints:@[self.topConstraint, self.leftConstraint]];
[supView layoutSubtreeIfNeeded];
  

ПРИМЕЧАНИЕ: layoutSubtreeIfNeeded необязательно; вы должны использовать его, если вам нужно работать с myView.frame использованием обновленных значений (как в моем случае).

Этот код корректно работает на macOS 10.9-10.10-10.11-10.12 .