Подтвердить что ты не робот

Swift - Как определить изменения ориентации

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

Я пробовал этот ответ, но требуется только одно изображение

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.currentDevice().orientation.isLandscape.boolValue {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

Я новичок в разработке iOS, любые советы будут очень благодарны!

4b9b3361

Ответ 1

let const = "Background" //image name
let const2 = "GreyBackground" // image name
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = UIImage(named: const)
        // Do any additional setup after loading the view.
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        if UIDevice.current.orientation.isLandscape {
            print("Landscape")
            imageView.image = UIImage(named: const2)
        } else {
            print("Portrait")
            imageView.image = UIImage(named: const)
        }
    }

Ответ 2

Swift 3 Выше кода обновлен:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

Ответ 3

Swift 3 Использование NotificationCenter

override func viewDidLoad() {
    super.viewDidLoad()        

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}

deinit {
     NotificationCenter.default.removeObserver(self)
}

func rotated() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

Ответ 4

Свифт 4+: я использовал это для создания мягкой клавиатуры, и по какой-то причине метод UIDevice.current.orientation.isLandscape продолжал говорить мне, что это Portrait, поэтому здесь я использовал вместо этого:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if(size.width > self.view.frame.size.width){
        //Landscape
    }
    else{
        //Portrait
    }
}

Ответ 5

Swift 4.2, RxSwift

Если нам нужно перезагрузить collectionView.

NotificationCenter.default.rx.notification(UIDevice.orientationDidChangeNotification)
    .observeOn(MainScheduler.instance)
    .map { _ in }            
    .bind(to: collectionView.rx.reloadData)
    .disposed(by: bag)

Swift 4, RxSwift

Если нам нужно перезагрузить collectionView.

NotificationCenter.default.rx.notification(NSNotification.Name.UIDeviceOrientationDidChange)
    .observeOn(MainScheduler.instance)
    .map { _ in }            
    .bind(to: collectionView.rx.reloadData)
    .disposed(by: bag)

Ответ 6

Если вы используете Swift version> = 3.0, вам нужно применить некоторые обновления кода, как уже говорили другие. Просто не забудьте позвонить супер:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

   super.viewWillTransition(to: size, with: coordinator)

   // YOUR CODE OR FUNCTIONS CALL HERE

}

Если вы подумываете использовать StackView для своих изображений, вы можете сделать что-то вроде следующего:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

   super.viewWillTransition(to: size, with: coordinator)

   if UIDevice.current.orientation.isLandscape {

      stackView.axis = .horizontal

   } else {

      stackView.axis = .vertical

   } // else

}

Если вы используете Interface Builder, не забудьте выбрать пользовательский класс для этого объекта UIStackView в разделе Identity Inspector на правой панели. Затем просто создайте (также через Interface Builder) ссылку IBOutlet на пользовательский экземпляр UIStackView:

@IBOutlet weak var stackView: MyStackView!

Возьмите идею и приспособите ее к вашим потребностям. Надеюсь, это поможет вам!

Ответ 7

Swift 4

У меня возникли некоторые незначительные проблемы при обновлении представления ViewControllers с использованием UIDevice.current.orientation, таких как обновление ограничений элементов tableview во время вращения или анимации подвью.

Вместо приведенных выше методов я в настоящее время сравниваю размер перехода с размером представления диспетчера представлений. Это похоже на правильный путь, так как у вас есть доступ к обоим в этом пункте кода:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    print("Will Transition to size \(size) from super view size \(self.view.frame.size)")

    if (size.width > self.view.frame.size.width) {
        print("Landscape")
    } else {
        print("Portrait")
    }

    if (size.width != self.view.frame.size.width) {
        // Reload TableView to update cell constraints.
    // Ensuring no dequeued cells have old constraints.
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }


}

Выход на iPhone 6:

Will Transition to size (667.0, 375.0) from super view size (375.0, 667.0) 
Will Transition to size (375.0, 667.0) from super view size (667.0, 375.0)

Ответ 8

Все предыдущие вложения в порядке, но небольшая заметка:

а) если ориентация установлена в Plist, только портрет или, например, Вы будете не уведомлены через viewWillTransition

б) если нам все равно нужно знать, имеет ли пользователь вращающееся устройство (например, игру или подобное.), мы можем использовать только:

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

проверено на Xcode8, iOS11

Ответ 9

Я считаю, что правильный ответ на самом деле представляет собой комбинацию обоих подходов: viewWIllTransition(toSize:) и NotificationCenter UIDeviceOrientationDidChange.

viewWIllTransition(toSize:) уведомляет вас о перед.

NotificationCenter UIDeviceOrientationDidChange уведомляет вас после.

Вы должны быть очень осторожны. Например, в UISplitViewController, когда устройство вращается в определенные ориентации, DetailViewController выталкивается из массива UISplitViewController viewcontrollers и нажимается на главный UINavigationController. Если вы перейдете к поиску контроллера подробного представления до завершения вращения, он может не существовать и сбой.

Ответ 10

Чтобы получить правильную ориентацию в начале приложения, вы должны проверить его в viewDidLayoutSubviews(). Другие методы, описанные здесь, не будут работать.

Вот пример, как это сделать:

var mFirstStart = true

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if (mFirstStart) {
        mFirstStart = false
        detectOrientation()
    }
}

func detectOrientation() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
        // do your stuff here for landscape
    } else {
        print("Portrait")
        // do your stuff here for portrait
    }
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    detectOrientation()
}

Это будет работать всегда, при первом запуске приложения и при повороте во время работы приложения.