Swift 4: пользовательский интерфейс не обновляется после ротации устройства - PullRequest
0 голосов
/ 07 июля 2019

Я хочу изменить ширину и высоту моего bearImageView на 100 при переходе от портрета -> ландшафт и до 200 при переходе в противоположном направлении.

Внутри setupLayout я вызываю деактивацию, а затем активирую ограничение на widthAnchor и heightAnchor. Поэтому я ожидаю, что он изменит ширину и высоту.

Проблема: она достигает 100, но не возвращается обратно к 200. Почему это случилось?

Это код.

class ViewController: UIViewController {

    // closure objects
    let bearImageView: UIImageView = {
        let imageView = UIImageView(image: #imageLiteral(resourceName: "bear_first")) // type `image literal` and double click
        imageView.translatesAutoresizingMaskIntoConstraints = false // enable autolayout
        return imageView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()            
        view.addSubview(bearImageView) // display image        
        setupLayout(imageView: bearImageView) // apply constraints
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        if UIDevice.current.orientation.isLandscape {
            print("landscape")
            setupLayout(imageView: bearImageView) // apply constraints                
        } else {
            print("portrait")
            setupLayout(imageView: bearImageView) // apply constraints                
        }
    }

    private func setupLayout(imageView: UIImageView){

        if UIDevice.current.orientation.isLandscape == true {
            imageView.widthAnchor.constraint(equalToConstant: 200).isActive = false
            imageView.heightAnchor.constraint(equalToConstant: 200).isActive = false
            imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
            imageView.widthAnchor.constraint(equalToConstant: 100).isActive = true
            imageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
            print("changed to landscape")

        } else {
            imageView.widthAnchor.constraint(equalToConstant: 100).isActive = false
            imageView.heightAnchor.constraint(equalToConstant: 100).isActive = false
            imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
            imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
            imageView.widthAnchor.constraint(equalToConstant: 200).isActive = true
            imageView.heightAnchor.constraint(equalToConstant: 200).isActive = true
            print("changed to portrait")
        }

    }

Это ошибка.

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x6000031923a0 UIImageView:0x7fbf72508060.width == 200   (active)>",
    "<NSLayoutConstraint:0x6000031e4730 UIImageView:0x7fbf72508060.width == 100   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000031923a0 UIImageView:0x7fbf72508060.width == 200   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

1 Ответ

2 голосов
/ 07 июля 2019

Обратите внимание, что метод constraint создает new для вашего изображения.

При первом вызове setupLayout в viewDidLoad добавляются ограничения ширины и высоты 200просмотр изображения.Затем вы поворачиваете устройство, чтобы перейти в ландшафт.setupLayout вызывается снова.На этот раз он добавляет ограничения ширины и высоты 100, , но не деактивирует ограничения с константой 200, которые вы ранее добавили .Выполнение этой строки:

imageView.widthAnchor.constraint(equalToConstant: 200).isActive = false

Создает новое неактивное ограничение, not деактивирует старое.

Что вам нужно сделать, это сохранить ограничения ширины и высоты каксвойства ViewController:

var widthConstraint: NSLayoutConstraint!
var heightConstraint: NSLayoutConstraint!

И в setupLayout присвойте эти свойства:

private func setupLayout(imageView: UIImageView){
    widthConstraint = imageView.widthAnchor.constraint(equalToConstant: 200)
    heightConstraint = imageView.heightAnchor.constraint(equalToConstant: 200)
    widthConstraint.isActive = true
    heightConstraint.isActive = true
    imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true

}

И вам следует вызывать setupLayout только один раз.

Затем вы создаете другой метод с именем updateConstraints, который обновляет константы widthConstraint и heightConstraint:

private func updateConstraints() {
    if UIDevice.current.orientation.isLandscape {
        heightConstraint.constant = 100
        widthConstraint.constant = 100
    } else {
        heightConstraint.constant = 200
        widthConstraint.constant = 200
    }
}

Вызывайте это в viewWillTransitionToSize вместо setupLayout.

...