ฉันกำลังใช้ Swift และฉันต้องการโหลด UIViewController เมื่อฉันหมุนไปสู่แนวนอนทุกคนสามารถชี้ให้ฉันไปในทิศทางที่ถูกต้องได้หรือไม่?
ฉันไม่พบสิ่งใดออนไลน์และสับสนเล็กน้อยจากเอกสารประกอบ
ฉันกำลังใช้ Swift และฉันต้องการโหลด UIViewController เมื่อฉันหมุนไปสู่แนวนอนทุกคนสามารถชี้ให้ฉันไปในทิศทางที่ถูกต้องได้หรือไม่?
ฉันไม่พบสิ่งใดออนไลน์และสับสนเล็กน้อยจากเอกสารประกอบ
คำตอบ:
นี่คือวิธีที่ฉันใช้งานได้:
ในAppDelegate.swift
ภายในdidFinishLaunchingWithOptions
ฟังก์ชั่นฉันใส่:
NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
และจากนั้นภายใน AppDelegate class ฉันใส่ฟังก์ชั่นต่อไปนี้:
func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
print("Landscape")
}
if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
print("Portrait")
}
}
หวังว่านี่ช่วยคนอื่นได้!
ขอบคุณ!
selector
มีรูปแบบสตริงเป็น"rotated:"
?
rotated()
ไม่ใช่)
UIDeviceOrientation
มันเป็นสิ่งที่แตกต่างจากUIInterfaceOrientation
.. นี่ก็เป็นเพราะUIDeviceOrientation
ตรวจจับคว่ำหน้าและเงยหน้าขึ้นมองซึ่งหมายความว่ารหัสของคุณสามารถข้ามระหว่างแนวตั้งและแนวนอนแบบสุ่มหากอุปกรณ์ของคุณวางอยู่บนพื้นผิวเกือบเรียบ แต่ไม่สม่ำเสมอเล็กน้อย กล้องของ 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")
}
}
ต้องการตรวจจับการหมุนในขณะที่ใช้กล้องด้วยAVFoundation
และพบว่า & didRotate
( เลิกใช้แล้ว ) & willTransition
วิธีการนี้ไม่น่าเชื่อถือสำหรับความต้องการของฉัน การใช้การแจ้งเตือนที่โพสต์โดย David ทำได้ แต่ไม่เป็นปัจจุบันสำหรับ Swift 3.x / 4.x
สวิฟต์ 4.2 เปลี่ยนชื่อการแจ้งเตือนแล้ว
มูลค่าการปิดยังคงเหมือนเดิมกับ 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")
}
}
วิธีตั้งค่าการแจ้งเตือนสำหรับ Swift 4.2 :
NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: .main,
using: didRotate)
หากต้องการยกเลิกการแจ้งเตือนสำหรับ Swift 4.2 :
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
เกี่ยวกับคำสั่งการคัดค้านความคิดเห็นเริ่มต้นของฉันทำให้เข้าใจผิดดังนั้นฉันจึงต้องการอัปเดต เท่าที่สังเกตการใช้งานของการอนุมานได้เลิกใช้ซึ่งจะเป็นสิ่งที่จำเป็นที่จะใช้@objc
#selector
โดยใช้การปิดแทนสิ่งนี้สามารถหลีกเลี่ยงได้และตอนนี้คุณมีวิธีแก้ปัญหาที่ควรหลีกเลี่ยงความล้มเหลวเนื่องจากการเรียกตัวเลือกที่ไม่ถูกต้อง
Swift 4.0
ด้วย Swift 4.0 Apple ได้สนับสนุนให้เราหลีกเลี่ยงการใช้#selector
วิธีการนี้จึงใช้บล็อกการทำให้เสร็จสมบูรณ์ในขณะนี้ วิธีนี้ยังใช้งานร่วมกับ Swift 3.x ได้และจะเป็นแนวทางที่แนะนำต่อไป
นี่คือคำเตือนของคอมไพเลอร์ที่คุณจะได้รับในโครงการ Swift 4.x หากคุณใช้#selector
ฟังก์ชั่นอันเนื่องมาจากการไม่ใช้การ@objc
อนุมาน:
รายการในวิวัฒนาการที่รวดเร็วในการเปลี่ยนแปลงนี้
ตั้งค่าการติดต่อกลับ:
// 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")
}
}
ตั้งค่าการแจ้งเตือน:
NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
object: nil,
queue: .main,
using: didRotate)
ฉีกมันลง:
NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)
การใช้-orientation
คุณสมบัติของUIDevice
ไม่ถูกต้อง (แม้ว่ามันจะสามารถทำงานได้ในกรณีส่วนใหญ่) และอาจนำไปสู่ข้อผิดพลาดบางอย่างเช่นUIDeviceOrientation
พิจารณาการวางแนวของอุปกรณ์หากมันคว่ำหน้าหรือลงไม่มีคู่โดยตรงในUIInterfaceOrientation
enum สำหรับสิ่งเหล่านั้น ค่า
นอกจากนี้หากคุณล็อกแอพของคุณในทิศทางเฉพาะ UIDevice จะให้การวางแนวอุปกรณ์โดยไม่คำนึงถึงสิ่งนั้น
ในอีกด้านหนึ่ง iOS8 ได้เลิกใช้interfaceOrientation
ทรัพย์สินในUIViewController
ชั้นเรียน
มี 2 ตัวเลือกสำหรับตรวจจับทิศทางของอินเทอร์เฟซ:
สิ่งที่ยังขาดหายไปคือวิธีที่จะเข้าใจทิศทางของการเปลี่ยนทิศทางของอินเทอร์เฟซซึ่งเป็นสิ่งสำคัญมากในระหว่างการเคลื่อนไหว
ในเซสชั่นของ WWDC 2014 "ดูความก้าวหน้าในการควบคุม iOS8" -will/DidRotateToInterfaceOrientation
ลำโพงให้วิธีการแก้ปัญหาที่มากเกินไปโดยใช้วิธีการที่จะแทนที่
นี่เป็นวิธีการแก้ปัญหาที่นำเสนอดำเนินการบางส่วนข้อมูลเพิ่มเติมได้ที่นี่ :
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)
}
}
ฉันรู้ว่าคำถามนี้มีไว้เพื่อSwift
แต่เนื่องจากเป็นหนึ่งในลิงค์ด้านบนสำหรับการค้นหาของ Google และหากคุณกำลังมองหารหัสเดียวกันใน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
}
ใช้งานได้ง่ายใน iOS8 และ 9 / Swift 2 / Xcode7 เพียงแค่ใส่รหัสนี้ไว้ใน viewcontroller.swift ของคุณ มันจะพิมพ์ขนาดหน้าจอที่มีการเปลี่ยนแปลงการวางแนวทุกครั้งคุณสามารถใส่รหัสของคุณเองแทน:
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()
ไม่ทำงานอย่างน่าเชื่อถือ มันขาดการหมุนบ้าง iewWillTransitionToSize:withTransitionCoordinator:
ทำงานได้ดี
ฉันชอบตรวจสอบการแจ้งเตือนการปฐมนิเทศเพราะคุณสามารถเพิ่มคุณสมบัตินี้ในชั้นเรียนใด ๆ ไม่จำเป็นต้องเป็นมุมมองหรือตัวควบคุมมุมมอง แม้ในตัวแทนแอปของคุณ
สวิฟท์ 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)
กว่าการแคชการแจ้งเตือน
@objc func orientationChanged(notification : NSNotification) {
//your code there
}
ในวัตถุประสงค์ C
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
อย่างรวดเร็ว
func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
แทนที่วิธีนี้เพื่อตรวจจับการเปลี่ยนแปลงการวางแนว
สวิฟท์ 3 | UIDeviceOrientationDidChange การแจ้งเตือนที่สังเกตบ่อยเกินไป
รหัสต่อไปนี้จะพิมพ์ "deviceDidRotate" ทุกครั้งที่อุปกรณ์ของคุณเปลี่ยนการวางแนวในพื้นที่ 3 มิติโดยไม่คำนึงถึงการเปลี่ยนจากแนวตั้งเป็นแนวนอน ตัวอย่างเช่นหากคุณถือโทรศัพท์ในแนวตั้งและเอียงไปข้างหน้าและข้างหลัง - DeviceDidRotate () ถูกเรียกซ้ำ ๆ
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIDeviceOrientationDidChange,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
เพื่อหลีกเลี่ยงปัญหานี้คุณสามารถระงับการวางแนวอุปกรณ์ก่อนหน้านี้และตรวจสอบการเปลี่ยนแปลงใน 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")
}
หรือคุณสามารถใช้การแจ้งเตือนที่แตกต่างกันซึ่งจะถูกเรียกเมื่ออุปกรณ์เปลี่ยนจากแนวนอนเป็นแนวตั้งเท่านั้น ในกรณีนี้คุณต้องการใช้การUIApplicationDidChangeStatusBarOrientation
แจ้งเตือน
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIApplicationDidChangeStatusBarOrientation,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
การใช้งานอย่างเต็มรูปแบบของวิธีตรวจจับการเปลี่ยนแปลงการวางแนวใน Swift 3.0
ฉันเลือกที่จะใช้การใช้งานนี้เพราะทิศทางของโทรศัพท์face up
และface down
มีความสำคัญต่อฉันและฉันต้องการให้มุมมองการเปลี่ยนแปลงเพียงครั้งเดียวที่ฉันรู้ว่าการวางแนวอยู่ในตำแหน่งที่ระบุ
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")
}
}
}
สิ่งสำคัญที่ควรทราบคือ:
unknown
วางแนวในบางครั้งหวังว่าบางคนพบว่ามีประโยชน์
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)")
}
หากคุณต้องการทำบางสิ่งบางอย่างหลังจากการหมุนเสร็จสมบูรณ์คุณสามารถใช้UIViewControllerTransitionCoordinator
ตัวจัดการความสมบูรณ์เช่นนี้
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()
}
}
ตั้งแต่ iOS 8 นี่เป็นวิธีที่ถูกต้องที่จะทำ
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`
})
}
ตรวจสอบว่าการหมุนมีการเปลี่ยนแปลงด้วย: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
กับ coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)
คุณสามารถตรวจสอบว่าการเปลี่ยนแปลงเสร็จสิ้น
ดูรหัสด้านล่าง:
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")
}
}
นี่เป็นวิธีที่ง่ายในการตรวจจับการวางแนวอุปกรณ์: ( 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
viewWillTransition
จะเลิกตอนนี้ใช้ดีกว่า
สวิฟท์ 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
}
}
คำตอบจำนวนมากช่วยไม่ได้เมื่อต้องการตรวจสอบตัวควบคุมมุมมองที่หลากหลาย อันนี้ทำอุบาย
viewWillDisappear
และเพิ่มในaddObserver
viewDidLoad
iOS ยกเลิกการเป็นสมาชิกตัวควบคุมการดูโดยอัตโนมัติ
UIDevice.current.orientation.isFlat
วิธีการของฉันคล้ายกับสิ่งที่bpeditแสดงด้านบน แต่ด้วยการมุ่งเน้น iOS 9+ ฉันต้องการเปลี่ยนขอบเขตของFSCalendarเมื่อมุมมองหมุน
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)
}
ด้านล่างนี้ใช้งานได้ แต่ฉันรู้สึกอายมาก :)
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
}
}
ฉันใช้UIUserInterfaceSizeClass
เพื่อตรวจจับทิศทางที่เปลี่ยนไปในUIViewController
ชั้นเรียนเช่นเดียวกับที่:
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
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
สวิฟท์ 5
ตั้งค่าคลาสเพื่อรับการแจ้งเตือนการเปลี่ยนทิศทางของอุปกรณ์:
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)
...
}
...
}
ตั้งค่ารหัสตัวจัดการ:
@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");
}
}
หมายเหตุ: เพียงใช้รหัสนี้เพื่อระบุ UIViewController ว่าอยู่ในทิศทางใด
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...
}
ด้วย iOS 13.1.2 การวางแนวจะส่งคืน 0 เสมอจนกว่าอุปกรณ์จะหมุน ฉันต้องโทรหา UIDevice.current.beginGeneratingDeviceOrientationNotifications () เพื่อรับการหมุนจริงก่อนที่เหตุการณ์การหมุนจะเกิดขึ้น