UINavigationController перемещает весь UIView в верхний левый угол

#ios #swift

#iOS #swift

Вопрос:

Я работаю в течение 100 дней с Swift без использования раскадровок и сталкиваюсь с некоторыми проблемами, когда представление пользовательского интерфейса почти полностью помещается под UINavigationController. При удалении UINavigationController все работает так, как ожидалось. Я попытался добавить новый вид, установить edgesForExtendedLayout =[] и настроить y мой CGRect безрезультатно. Я почти уверен, что делаю что-то довольно глупое, но ни за что на свете не могу понять, что именно.

Скриншот того, как выглядит представление:
введите описание изображения здесь

Ожидается, что 3 кнопки будут отображаться, начиная с NavView.

Удаление сцены.swift:

 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
      guard let windowScene = (scene as? UIWindowScene) else { return }
      window = UIWindow(frame: windowScene.coordinateSpace.bounds)
      let viewController = ViewController()
      window?.rootViewController = UINavigationController(rootViewController: viewController)
      window?.makeKeyAndVisible()
      window?.windowScene = windowScene
    }
  

ViewController.swift:

 class ViewController: UIViewController {

    var button1: UIButton!
    var button2: UIButton!
    var button3: UIButton!
        
    var countries = [String]()
    var score = 0
    var correctAnswer = 0
            
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        button1 = UIButton(type: .custom)
        button1.setImage(UIImage(named: "us"), for: .normal)
        button1.translatesAutoresizingMaskIntoConstraints = false
        button1.frame = CGRect(x: 100, y: 100, width: 200, height: 100)
        button1.layer.borderWidth = 1
        button1.layer.borderColor = UIColor.lightGray.cgColor
        view.addSubview(button1)
        
        button2 = UIButton(type: .custom)
        button2.setImage(UIImage(named: "us"), for: .normal)
        button2.translatesAutoresizingMaskIntoConstraints = false
        button2.frame = CGRect(x: 100, y: 230, width: 200, height: 100)
        button2.layer.borderWidth = 1
        button2.layer.borderColor = UIColor.lightGray.cgColor
        view.addSubview(button2)
        
        button3 = UIButton(type: .custom)
        button3.setImage(UIImage(named: "us"), for: .normal)
        button3.translatesAutoresizingMaskIntoConstraints = false
        button3.frame = CGRect(x: 100, y: 360, width: 200, height: 100)
        button3.layer.borderWidth = 1
        button3.layer.borderColor = UIColor.lightGray.cgColor
        view.addSubview(button3)
        
        countries  = ["estonia", "france", "germany", "ireland", "italy", "monaco", "nigeria", "poland", "russia", "spain", "uk", "us"]
        
        
        askQuestion()
    }
    
    func askQuestion() {
        countries.shuffle()
        correctAnswer = Int.random(in: 0...2)
        
        button1.setImage(UIImage(named: countries[0]), for: .normal)
        button2.setImage(UIImage(named: countries[1]), for: .normal)
        button3.setImage(UIImage(named: countries[2]), for: .normal)
        
        title = countries[correctAnswer].uppercased()
    }
}
  

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

1. На всех 3 кнопках выполняется настройка .translatesAutoresizingMaskIntoConstraints = false … но тогда вы пытаетесь установить .frame`. Это действительно действительно старый курс, что вы не используете ограничения автоматической компоновки?

2. HA! Честно говоря, я видел это на стольких примерах, что предположил, что это «правильный» способ, поскольку я в основном выполнял swift с помощью раскадровок или swiftui. Удаление этой строки из всех 3 кнопок было исправлением. Если вы хотите добавить это в качестве ответа против комментария, я отмечу как правильный. Спасибо за вашу помощь @DonMag

Ответ №1:

Согласно комментариям OP…

Проблема в том, что для каждой кнопки, которую вы устанавливаете:

 button1.translatesAutoresizingMaskIntoConstraints = false
  

но затем пытаются явно установить рамки кнопок:

 button1.frame = CGRect(x: 100, y: 100, width: 200, height: 100)
  

Вы хотите либо использовать автоматическую компоновку, либо явные фреймы. Их смешивание приведет к проблемам, поскольку элементы пользовательского интерфейса не будут отображаться там, где вы их ожидаете (как вы видели).

Ответ №2:

Поскольку вы создаете представление без использования раскадровки. Вы должны добавить ограничения для программного размещения кнопок.

Добавьте приведенный ниже код в viewDidLoad функцию

 button1.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.init(item: button1!, attribute: .top, relatedBy: .equal, toItem: view.safeAreaLayoutGuide, attribute: .top, multiplier: 1, constant: 0).isActive = true
  

Или,

 button1.translatesAutoresizingMaskIntoConstraints = false
button1.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
  

Они делают то же самое — программно добавляют ограничение от button1 к началу safeArea . Вы также можете добавить ограничения к button2 и button3 по своему усмотрению.