Saya menggunakan Swift dan saya ingin dapat memuat UIViewController ketika saya memutar ke lanskap, adakah yang bisa mengarahkan saya ke arah yang benar?
Saya tidak dapat menemukan apa pun secara online dan sedikit bingung dengan dokumentasi.
Saya menggunakan Swift dan saya ingin dapat memuat UIViewController ketika saya memutar ke lanskap, adakah yang bisa mengarahkan saya ke arah yang benar?
Saya tidak dapat menemukan apa pun secara online dan sedikit bingung dengan dokumentasi.
Jawaban:
Begini cara saya membuatnya bekerja:
Di AppDelegate.swift
dalam didFinishLaunchingWithOptions
fungsi saya meletakkan:
NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
dan kemudian di dalam kelas AppDelegate saya meletakkan fungsi berikut:
func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
print("Landscape")
}
if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
print("Portrait")
}
}
Semoga ini bisa membantu orang lain!
Terima kasih!
selector
memiliki format string "rotated:"
??
rotated()
tidak)
UIDeviceOrientation
ada sesuatu yang berbeda dengan UIInterfaceOrientation
.. Ini karena UIDeviceOrientation
juga mendeteksi orientasi menghadap ke bawah dan menghadap ke atas yang berarti bahwa kode Anda dapat melompat antara potret dan lansekap secara acak jika perangkat Anda bersandar pada permukaan yang hampir datar tetapi sedikit tidak rata (yaitu bergoyang di permukaan yang menonjol) kamera 6 / 6s)
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
}
if UIDevice.current.orientation.isFlat {
print("Flat")
} else {
print("Portrait")
}
}
Perlu mendeteksi rotasi saat menggunakan kamera dengan AVFoundation
, dan menemukan bahwa didRotate
( sekarang sudah usang ) & willTransition
metode tidak dapat diandalkan untuk kebutuhan saya. Menggunakan notifikasi yang diposting oleh David berhasil, tetapi tidak berlaku untuk Swift 3.x / 4.x.
Swift 4.2 Nama notifikasi telah diubah.
Nilai penutupan tetap sama dengan Swift 4.0:
var didRotate: (Notification) -> Void = { notification in
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight:
print("landscape")
case .portrait, .portraitUpsideDown:
print("Portrait")
default:
print("other")
}
}
Untuk mengatur notifikasi untuk Swift 4.2 :
NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: .main,
using: didRotate)
Untuk meruntuhkan pemberitahuan untuk Swift 4.2 :
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
Mengenai pernyataan penghentian , komentar awal saya menyesatkan, jadi saya ingin memperbarui itu. Sebagaimana dicatat, penggunaan @objc
inferensi telah ditinggalkan, yang pada gilirannya diperlukan untuk menggunakan a #selector
. Dengan menggunakan penutupan sebagai gantinya, ini dapat dihindari dan Anda sekarang memiliki solusi yang harus menghindari kerusakan karena memanggil pemilih yang tidak valid.
Swift 4.0
Dengan Swift 4.0, Apple telah mendorong kami untuk menghindari penggunaan #selector
, jadi pendekatan ini menggunakan blok penyelesaian sekarang. Pendekatan ini juga kompatibel dengan Swift 3.x & akan menjadi pendekatan yang disarankan untuk maju.
Ini adalah peringatan kompiler yang akan Anda terima dalam proyek Swift 4.x jika Anda menggunakan #selector
fungsi karena penghentian @objc
inferensi:
Entri dalam evolusi cepat pada perubahan ini .
Siapkan panggilan balik:
// If you do not use the notification var in your callback,
// you can safely replace it with _
var didRotate: (Notification) -> Void = { notification in
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight:
print("landscape")
case .portrait, .portraitUpsideDown:
print("Portrait")
default:
print("other")
}
}
Siapkan notifikasi:
NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
object: nil,
queue: .main,
using: didRotate)
Runtuhkan:
NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)
Menggunakan -orientation
properti dari UIDevice
tidak benar (bahkan jika itu bisa bekerja di sebagian besar kasus) dan dapat menyebabkan beberapa bug, misalnya UIDeviceOrientation
mempertimbangkan juga orientasi perangkat jika menghadap ke atas atau ke bawah, tidak ada pasangan langsung di UIInterfaceOrientation
enum untuk mereka. nilai-nilai.
Selain itu, jika Anda mengunci aplikasi Anda dalam beberapa orientasi tertentu, UIDevice akan memberi Anda orientasi perangkat tanpa memperhitungkannya.
Di sisi lain iOS8 telah mencabut interfaceOrientation
properti di UIViewController
kelas.
Ada 2 opsi yang tersedia untuk mendeteksi orientasi antarmuka:
Apa yang masih hilang adalah cara untuk memahami arah perubahan orientasi antarmuka, yang sangat penting selama animasi.
Dalam sesi WWDC 2014 "Lihat kemajuan pengontrol di iOS8" pembicara juga memberikan solusi untuk masalah itu, menggunakan metode yang menggantikan -will/DidRotateToInterfaceOrientation
.
Di sini solusi yang diusulkan sebagian dilaksanakan, info lebih lanjut di sini :
func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
let orientation = orientationFromTransform(coordinator.targetTransform())
let oldOrientation = UIApplication.sharedApplication().statusBarOrientation
myWillRotateToInterfaceOrientation(orientation,duration: duration)
coordinator.animateAlongsideTransition({ (ctx) in
self.myWillAnimateRotationToInterfaceOrientation(orientation,
duration:duration)
}) { (ctx) in
self.myDidAnimateFromInterfaceOrientation(oldOrientation)
}
}
Saya tahu pertanyaan ini untuk Swift
, tetapi karena ini adalah salah satu tautan teratas untuk pencarian Google dan jika Anda mencari kode yang sama di Objective-C
:
// add the observer
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rotated:) name:UIDeviceOrientationDidChangeNotification object:nil];
// remove the observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
// method signature
- (void)rotated:(NSNotification *)notification {
// do stuff here
}
Mudah, ini berfungsi di iOS8 dan 9 / Swift 2 / Xcode7, cukup masukkan kode ini di dalam viewcontroller.swift Anda. Ini akan mencetak dimensi layar dengan setiap perubahan orientasi, Anda dapat menempatkan kode Anda sendiri sebagai gantinya:
override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
getScreenSize()
}
var screenWidth:CGFloat=0
var screenHeight:CGFloat=0
func getScreenSize(){
screenWidth=UIScreen.mainScreen().bounds.width
screenHeight=UIScreen.mainScreen().bounds.height
print("SCREEN RESOLUTION: "+screenWidth.description+" x "+screenHeight.description)
}
didRotateFromInterfaceOrientation()
tidak berfungsi dengan baik. Itu melewatkan beberapa rotasi. iewWillTransitionToSize:withTransitionCoordinator:
berfungsi ok.
Saya suka memeriksa pemberitahuan orientasi karena Anda dapat menambahkan fitur ini di kelas mana pun, tidak perlu tampilan atau pengontrol tampilan. Bahkan dalam delegasi aplikasi Anda.
SWIFT 5:
//ask the system to start notifying when interface change
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
//add the observer
NotificationCenter.default.addObserver(
self,
selector: #selector(orientationChanged(notification:)),
name: UIDevice.orientationDidChangeNotification,
object: nil)
dari caching notifikasi
@objc func orientationChanged(notification : NSNotification) {
//your code there
}
Dalam Tujuan C
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
Dengan cepat
func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Ganti metode ini untuk mendeteksi perubahan orientasi.
Swift 3 | UIDeviceOrientationDidChange Notification Diamati Terlalu Sering
Kode berikut mencetak "deviceDidRotate" setiap kali perangkat Anda mengubah orientasi dalam ruang 3D - terlepas dari perubahan dari orientasi potret ke lanskap. Misalnya, jika Anda memegang telepon dalam orientasi potret dan memiringkannya ke depan dan ke belakang - deviceDidRotate () dipanggil berulang kali.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIDeviceOrientationDidChange,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Untuk mengatasinya, Anda dapat memegang orientasi perangkat sebelumnya dan memeriksa perubahan deviceDidRotate ().
var previousDeviceOrientation: UIDeviceOrientation = UIDevice.current.orientation
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIDeviceOrientationDidChange,
object: nil
)
}
func deviceDidRotate() {
if UIDevice.current.orientation == previousDeviceOrientation { return }
previousDeviceOrientation = UIDevice.current.orientation
print("deviceDidRotate")
}
Atau Anda dapat menggunakan notifikasi berbeda yang hanya dipanggil ketika perangkat berubah dari landscape ke portrait. Dalam hal ini Anda ingin menggunakan UIApplicationDidChangeStatusBarOrientation
notifikasi.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIApplicationDidChangeStatusBarOrientation,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Implementasi kerja penuh bagaimana mendeteksi perubahan orientasi di Swift 3.0.
Saya memilih untuk menggunakan implementasi ini karena orientasi telepon face up
dan face down
penting bagi saya, dan saya ingin pandangan berubah hanya setelah saya tahu orientasi berada di posisi yang ditentukan.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//1
NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
deinit {
//3
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
func deviceOrientationDidChange() {
//2
switch UIDevice.current.orientation {
case .faceDown:
print("Face down")
case .faceUp:
print("Face up")
case .unknown:
print("Unknown")
case .landscapeLeft:
print("Landscape left")
case .landscapeRight:
print("Landscape right")
case .portrait:
print("Portrait")
case .portraitUpsideDown:
print("Portrait upside down")
}
}
}
Bagian penting yang perlu diperhatikan adalah:
unknown
orientasi di kali.Semoga seseorang menemukan ini bermanfaat.
override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) {
//swift 3
getScreenSize()
}
func getScreenSize(){
let screenWidth = UIScreen.main.bounds.width
let screenHeight = UIScreen.main.bounds.height
print("SCREEN RESOLUTION: \(screenWidth.description) x \(screenHeight.description)")
}
Jika Anda ingin melakukan sesuatu SETELAH rotasi selesai, Anda dapat menggunakan UIViewControllerTransitionCoordinator
penangan selesai seperti ini
public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// Hook in to the rotation animation completion handler
coordinator.animate(alongsideTransition: nil) { (_) in
// Updates to your UI...
self.tableView.reloadData()
}
}
Sejak iOS 8 ini adalah cara yang benar untuk melakukannya.
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { context in
// This is called during the animation
}, completion: { context in
// This is called after the rotation is finished. Equal to deprecated `didRotate`
})
}
Periksa apakah rotasi telah berubah dengan: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Dengan coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)
Anda dapat memeriksa apakah transisi selesai.
Lihat kode di bawah ini:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext) in
// if you want to execute code after transition finished
print("Transition finished")
}
if size.height < size.width {
// Landscape
print("Landscape")
} else {
// Portrait
print("Portrait")
}
}
Berikut cara mudah mendeteksi orientasi perangkat: ( Swift 3 )
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
handleViewRotaion(orientation: toInterfaceOrientation)
}
//MARK: - Rotation controls
func handleViewRotaion(orientation:UIInterfaceOrientation) -> Void {
switch orientation {
case .portrait :
print("portrait view")
break
case .portraitUpsideDown :
print("portraitUpsideDown view")
break
case .landscapeLeft :
print("landscapeLeft view")
break
case .landscapeRight :
print("landscapeRight view")
break
case .unknown :
break
}
}
willRotate
sudah ditinggalkan sekarang, lebih baik digunakan viewWillTransition
.
Swift 4:
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(deviceRotated), name: UIDevice.orientationDidChangeNotification, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: UIDevice.orientationDidChangeNotification, object: nil)
}
@objc func deviceRotated(){
if UIDevice.current.orientation.isLandscape {
//Code here
} else {
//Code here
}
}
Banyak jawaban yang tidak membantu ketika perlu mendeteksi berbagai pengontrol tampilan. Yang ini berhasil.
viewWillDisappear
dan menambahkan addObserver
di viewDidLoad
. iOS berhenti berlangganan controller tampilan secara otomatis.
UIDevice.current.orientation.isFlat
Pendekatan saya mirip dengan apa yang ditampilkan bpedit di atas, tetapi dengan fokus iOS 9+. Saya ingin mengubah ruang lingkup FSCalendar ketika tampilan berputar.
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
coordinator.animateAlongsideTransition({ (context) in
if size.height < size.width {
self.calendar.setScope(.Week, animated: true)
self.calendar.appearance.cellShape = .Rectangle
}
else {
self.calendar.appearance.cellShape = .Circle
self.calendar.setScope(.Month, animated: true)
}
}, completion: nil)
}
Ini di bawah ini bekerja, tetapi saya merasa malu tentang hal itu :)
coordinator.animateAlongsideTransition({ (context) in
if size.height < size.width {
self.calendar.scope = .Week
self.calendar.appearance.cellShape = .Rectangle
}
}) { (context) in
if size.height > size.width {
self.calendar.scope = .Month
self.calendar.appearance.cellShape = .Circle
}
}
Saya gunakan UIUserInterfaceSizeClass
untuk mendeteksi orientasi yang berubah di UIViewController
kelas begitu saja:
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
let isiPadLandscapePortrait = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .regular
let isiPhonePlustLandscape = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .compact
let isiPhonePortrait = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .regular
let isiPhoneLandscape = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .compact
if isiPhonePortrait {
// do something...
}
}
Untuk Swift 3
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
if UIDevice.current.orientation.isLandscape {
//Landscape
}
else if UIDevice.current.orientation.isFlat {
//isFlat
}
else {
//Portrait
}
}
UIDevice.current.orientation.isFlat
Cepat 5
Atur kelas untuk menerima pemberitahuan perubahan orientasi perangkat:
class MyClass {
...
init (...) {
...
super.init(...)
// subscribe to device orientation change notifications
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil)
...
}
...
}
Kode penangan pengaturan:
@objc extension MyClass {
func orientationChanged(_ notification: NSNotification) {
let device = notification.object as! UIDevice
let deviceOrientation = device.orientation
switch deviceOrientation {
case .landscapeLeft: //do something for landscape left
case .landscapeRight: //do something for landscape right
case .portrait: //do something for portrait
case .portraitUpsideDown: //do something for portrait upside-down
case .faceDown: //do something for face down
case .faceUp: //do something for face up
case .unknown: //handle unknown
@unknown default: //handle unknown default
}
}
}
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
-(void)OrientationDidChange:(NSNotification*)notification {
UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];
if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight) {
NSLog(@"Landscape");
} else if(Orientation==UIDeviceOrientationPortrait) {
NSLog(@"Potrait Mode");
}
}
CATATAN: Cukup gunakan kode ini untuk mengidentifikasi UIViewController di mana orientasi
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(MyController.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
//...
}
@objc
private func rotated() {
if UIDevice.current.orientation.isLandscape {
} else if UIDevice.current.orientation.isPortrait {
}
//or you can check orientation separately UIDevice.current.orientation
//portrait, portraitUpsideDown, landscapeLeft, landscapeRight...
}
Dengan iOS 13.1.2, orientasi selalu kembali 0 hingga perangkat diputar. Saya perlu menghubungi UIDevice.current.beginGeneratingDeviceOrientationNotifications () untuk mendapatkan rotasi aktual sebelum terjadi peristiwa rotasi.