Swift kullanıyorum ve manzaraya döndüğümde bir UIViewController yüklemek istiyorum, kimse beni doğru yönde gösterebilir mi?
Çevrimiçi olarak hiçbir şey bulamıyorum ve dokümantasyon biraz karıştı.
Swift kullanıyorum ve manzaraya döndüğümde bir UIViewController yüklemek istiyorum, kimse beni doğru yönde gösterebilir mi?
Çevrimiçi olarak hiçbir şey bulamıyorum ve dokümantasyon biraz karıştı.
Yanıtlar:
İşte nasıl çalıştıracak:
In AppDelegate.swift
içine didFinishLaunchingWithOptions
ben koymak işlevi:
NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
ve sonra AppDelegate sınıfının içine aşağıdaki işlevi koydum:
func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
print("Landscape")
}
if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
print("Portrait")
}
}
Umarım bu herkese yardımcı olur!
Teşekkürler!
selector
bir dize biçimine sahip olmamalıdır "rotated:"
??
rotated()
değilim (sadece değil) argüman kabul ediyorsanız
UIDeviceOrientation
farklı bir şeydir UIInterfaceOrientation
.. Bunun nedeni, UIDeviceOrientation
yüz aşağı ve yüz yukarı yönlerini de algılamasıdır, yani cihazınız neredeyse düz ancak biraz düz olmayan bir yüzeye (yani çıkıntılı sallanan) 6 / 6s fotoğraf makinesi)
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")
}
}
Kamerayı kullanırken döndürmeyi saptamam gerekiyor AVFoundation
ve didRotate
( artık kullanımdan kaldırıldı ) ve willTransition
yöntemlerin ihtiyaçlarım için güvenilir olmadığını gördüm. David tarafından gönderilen bildirimi kullanmak işe yaradı, ancak Swift 3.x / 4.x için geçerli değil.
Swift 4.2 Bildirim adı değiştirildi.
Kapatma değeri Swift 4.0 ile aynı kalır:
var didRotate: (Notification) -> Void = { notification in
switch UIDevice.current.orientation {
case .landscapeLeft, .landscapeRight:
print("landscape")
case .portrait, .portraitUpsideDown:
print("Portrait")
default:
print("other")
}
}
Swift 4.2 için bildirim ayarlamak için :
NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: .main,
using: didRotate)
Swift 4.2 bildirimini kaldırmak için :
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
Kullanımdan kaldırma ifadesiyle ilgili olarak, ilk yorumum yanıltıcıydı, bu yüzden bunu güncellemek istedim. Belirtildiği gibi, @objc
çıkarım kullanımı kullanımdan kaldırılmıştır, bu da a'nın kullanılması için gerekli olmuştur #selector
. Bunun yerine bir kapatma kullanarak bu önlenebilir ve şimdi geçersiz bir seçici çağırmaktan kaynaklanan bir çökmeyi önlemek için bir çözümünüz var.
Swift 4.0 Swift 4.0
ile Apple bizi kullanmaktan kaçınmaya teşvik etti #selector
, bu yüzden bu yaklaşım şimdi bir tamamlama bloğu kullanıyor. Bu yaklaşım ayrıca Swift 3.x ile geriye dönük olarak uyumludur ve ileriye dönük olarak önerilen yaklaşım olacaktır.
Bu, çıkarımın #selector
kullanımdan kaldırılması nedeniyle işlevi kullanırsanız bir Swift 4.x projesinde alacağınız derleyici uyarısıdır @objc
:
Bu değişimde hızlı evrime giriş .
Geri aramayı ayarlayın:
// 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")
}
}
Bildirimi ayarlayın:
NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
object: nil,
queue: .main,
using: didRotate)
Bunu yıkın:
NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)
Kullanılması -orientation
malı UIDevice
(vakaların çoğunda işe yarayabilir bile) ve örnek için, bazı hatalar yol açabilecek doğru değil UIDeviceOrientation
aşağı yüz yukarı mı yoksa doğrudan çifti de vardır, ayrıca cihazın yönünü dikkate UIInterfaceOrientation
olanlar için enum değerler.
Ayrıca, uygulamanızı belirli bir yönde kilitlerseniz, UIDevice bunu dikkate almadan cihaz yönünü verir.
Diğer tarafta iOS8, sınıftaki interfaceOrientation
mülkü kullanımdan kaldırmıştır UIViewController
.
Arabirim yönünü algılamak için 2 seçenek vardır:
Hala eksik olan, animasyonlar sırasında çok önemli olan arayüz yönünün değişmesinin yönünü anlamanın bir yoludur.
WWDC 2014 "iOS8'deki denetleyici ilerlemesini görüntüle" oturumunda hoparlör, yerine geçen yöntemi kullanarak da bu soruna bir çözüm sağlar -will/DidRotateToInterfaceOrientation
.
Burada önerilen çözüm kısmen uygulandı, daha fazla bilgi burada :
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)
}
}
Bu sorunun olduğunu biliyorum Swift
, ancak bir Google araması için en iyi bağlantılardan biri olduğu ve aynı kodu şu konumda arıyorsanız 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
}
Kolay, bu iOS8 ve 9 / Swift 2 / Xcode7'de çalışır, sadece bu kodu viewcontroller.swift'inize yerleştirin. Her yön değişikliği ile ekran boyutlarını yazdıracak, bunun yerine kendi kodunuzu koyabilirsiniz:
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()
güvenilir bir şekilde çalışmaz. Bazı rotasyonları kaçırıyor. iewWillTransitionToSize:withTransitionCoordinator:
iyi çalışıyor.
Yönlendirme bildirimini kontrol etmeyi seviyorum çünkü bu özelliği herhangi bir sınıfa ekleyebilirsiniz, bir görünüm veya görünüm denetleyicisi olmaya gerek yok. Uygulama temsilcinizde bile.
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)
bildirimi önbelleğe almaktan
@objc func orientationChanged(notification : NSNotification) {
//your code there
}
Hedef C
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
Hızlı
func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Yön değişikliğini tespit etmek için bu yöntemi geçersiz kılın.
Swift 3 | UIDeviceOrientationDidChange Bildirimi Çok Sık Gözlemlendi
Aşağıdaki kod, cihazınız 3B alanda her yön değiştirdiğinde (dikeyden yatay yöne değişmeksizin) "deviceDidRotate" yazdırır. Örneğin, telefonunuzu dikey yönde tutar ve ileri ve geri yatırırsanız, deviceDidRotate () tekrar tekrar çağrılır.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIDeviceOrientationDidChange,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Bu sorunu gidermek için önceki aygıt yönünü koruyabilir ve deviceDidRotate () öğesinde bir değişiklik olup olmadığını denetleyebilirsiniz.
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")
}
Veya yalnızca cihaz yataydan portreye değiştiğinde çağrılan farklı bir bildirim kullanabilirsiniz. Bu durumda UIApplicationDidChangeStatusBarOrientation
bildirimi kullanmak istersiniz .
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIApplicationDidChangeStatusBarOrientation,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Swift 3.0'da oryantasyon değişikliğinin nasıl tespit edileceğinin tam çalışma uygulaması.
Çünkü telefon yönlendirmeleri bu uygulama kullanmayı seçti face up
ve face down
benim için önemli idi ve ben görünümü ben oryantasyon belirtilen pozisyonda olduğunu biliyordum sadece bir kez değiştirmek istedim.
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")
}
}
}
Dikkat edilmesi gereken önemli parçalar şunlardır:
unknown
.Umarım birisi bunu faydalı bulur.
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)")
}
Döndürme tamamlandıktan SONRA bir şey yapmak istiyorsanız, UIViewControllerTransitionCoordinator
tamamlama işleyicisini şöyle kullanabilirsiniz
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()
}
}
İOS 8'den beri bunu yapmanın doğru yolu budur.
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`
})
}
Döndürmenin değişip değişmediğini kontrol edin: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
İle coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)
geçişin tamamlanıp tamamlanmadığını kontrol edebilirsiniz.
Aşağıdaki koda bakın:
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")
}
}
Cihazın yönünü saptamanın kolay bir yolu: ( 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
artık kullanımdan kaldırıldı, daha iyi kullanım viewWillTransition
.
Hızlı 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
}
}
Çeşitli görünüm denetleyicilerinde algılamanız gerektiğinde birçok yanıt yardımcı olmaz. Bu hile yapar.
viewWillDisappear
ve eklemek addObserver
içinde viewDidLoad
. iOS, görünüm denetleyicisini otomatik olarak iptal eder.
UIDevice.current.orientation.isFlat
Yaklaşımım bpedit'in yukarıda gösterdiği şeye benziyor , ancak iOS 9+ odaklı. Görünüm döndüğünde FSCalendar kapsamını değiştirmek istedim .
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)
}
Aşağıdaki çalıştı, ama bu konuda koyun hissettim :)
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
}
}
Ben böyle UIUserInterfaceSizeClass
bir UIViewController
sınıfta değişti yönünü tespit etmek için kullanın :
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...
}
}
Swift 3 için
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
Hızlı 5
Aygıt yönü değişikliği bildirimleri almak için kurulum sınıfı:
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)
...
}
...
}
Kurulum işleyici kodu:
@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");
}
}
NOT: UIViewController'ın hangi yönde olduğunu belirlemek için bu kodu kullanın
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...
}
İOS 13.1.2 ile cihaz döndürülene kadar yönelim daima 0'a döner. Herhangi bir döndürme olayı gerçekleşmeden önce gerçek döndürme almak için UIDevice.current.beginGeneratingDeviceOrientationNotifications () çağırmak gerekir.