Tôi đang sử dụng Swift và tôi muốn có thể tải UIViewControll khi tôi xoay sang ngang, có ai có thể chỉ cho tôi đi đúng hướng không?
Tôi không thể tìm thấy bất cứ điều gì trực tuyến và một chút bối rối bởi các tài liệu.
Tôi đang sử dụng Swift và tôi muốn có thể tải UIViewControll khi tôi xoay sang ngang, có ai có thể chỉ cho tôi đi đúng hướng không?
Tôi không thể tìm thấy bất cứ điều gì trực tuyến và một chút bối rối bởi các tài liệu.
Câu trả lời:
Đây là cách tôi làm cho nó hoạt động:
Trong AppDelegate.swift
bên trong didFinishLaunchingWithOptions
chức năng tôi đặt:
NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: UIDevice.orientationDidChangeNotification, object: nil)
và sau đó bên trong lớp AppDelegate tôi đặt hàm sau:
func rotated() {
if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) {
print("Landscape")
}
if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) {
print("Portrait")
}
}
Hy vọng điều này sẽ giúp bất cứ ai khác!
Cảm ơn!
selector
có định dạng chuỗi "rotated:"
??
rotated()
không có)
UIDeviceOrientation
có gì đó khác với UIInterfaceOrientation
.. Điều này là do UIDeviceOrientation
cũng phát hiện hướng xuống và hướng lên trên có nghĩa là mã của bạn có thể nhảy ngẫu nhiên giữa dọc và ngang nếu thiết bị của bạn nằm trên một bề mặt gần như phẳng nhưng hơi không bằng phẳng (tức là rung lên trên phần nhô ra máy ảnh của 6/6)
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")
}
}
Cần phát hiện xoay trong khi sử dụng máy ảnh AVFoundation
và thấy rằng các phương thức didRotate
( hiện không dùng nữa ) willTransition
không đáng tin cậy cho nhu cầu của tôi. Sử dụng thông báo được đăng bởi David đã hoạt động, nhưng không có sẵn cho Swift 3.x / 4.x.
Swift 4.2 Tên thông báo đã được thay đổi.
Giá trị đóng vẫn giữ nguyên như 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")
}
}
Để thiết lập thông báo cho Swift 4.2 :
NotificationCenter.default.addObserver(forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: .main,
using: didRotate)
Để phá bỏ thông báo cho Swift 4.2 :
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
Về tuyên bố phản đối , nhận xét ban đầu của tôi là sai lệch, vì vậy tôi muốn cập nhật điều đó. Như đã lưu ý, việc sử dụng @objc
suy luận đã không được chấp nhận, do đó cần phải sử dụng a #selector
. Bằng cách sử dụng một bao đóng thay thế, điều này có thể tránh được và bây giờ bạn có một giải pháp để tránh sự cố do gọi một bộ chọn không hợp lệ.
Swift 4.0
Với Swift 4.0, Apple đã khuyến khích chúng tôi tránh sử dụng #selector
, vì vậy phương pháp này sử dụng một khối hoàn thành ngay bây giờ. Cách tiếp cận này cũng tương thích ngược với Swift 3.x & sẽ là cách tiếp cận được đề xuất trong tương lai.
Đây là cảnh báo trình biên dịch bạn sẽ nhận được trong dự án Swift 4.x nếu bạn sử dụng #selector
chức năng do không dùng nữa@objc
suy luận:
Tham gia vào sự tiến hóa nhanh chóng về sự thay đổi này .
Thiết lập cuộc gọi lại:
// 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")
}
}
Cài đặt thông báo:
NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange,
object: nil,
queue: .main,
using: didRotate)
Rơi nước mắt:
NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)
Sử dụng -orientation
thuộc tính của UIDevice
là không chính xác (ngay cả khi nó có thể hoạt động trong hầu hết các trường hợp) và có thể dẫn đến một số lỗi, ví dụ, UIDeviceOrientation
cũng xem xét hướng của thiết bị nếu nó hướng lên hoặc xuống, không có cặp nào trực tiếp trong UIInterfaceOrientation
enum các giá trị.
Hơn nữa, nếu bạn khóa ứng dụng của mình theo một số hướng cụ thể, UIDevice sẽ cung cấp cho bạn hướng thiết bị mà không tính đến điều đó.
Mặt khác, iOS8 đã phản đối interfaceOrientation
tài sản trên UIViewController
lớp.
Có 2 tùy chọn có sẵn để phát hiện hướng giao diện:
Điều còn thiếu là một cách để hiểu hướng thay đổi hướng giao diện, điều này rất quan trọng trong các hình ảnh động.
Trong phiên WWDC 2014 "Xem tiến bộ điều khiển trong iOS8", người nói cũng cung cấp giải pháp cho vấn đề đó, sử dụng phương pháp thay thế -will/DidRotateToInterfaceOrientation
.
Ở đây, giải pháp đề xuất được thực hiện một phần, thông tin thêm ở đây :
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)
}
}
Tôi biết câu hỏi này là dành cho Swift
, nhưng vì đây là một trong những liên kết hàng đầu cho tìm kiếm Google và nếu bạn đang tìm kiếm cùng một mã trong 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
}
Thật dễ dàng, điều này hoạt động trong iOS8 và 9 / Swift 2 / Xcode7, chỉ cần đặt mã này bên trong viewcontroll.swift của bạn. Nó sẽ in kích thước màn hình với mỗi thay đổi hướng, thay vào đó bạn có thể đặt mã của riêng mình:
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()
không làm việc đáng tin cậy. Nó bỏ lỡ một số vòng quay. iewWillTransitionToSize:withTransitionCoordinator:
hoạt động tốt
Tôi thích kiểm tra thông báo định hướng vì bạn có thể thêm tính năng này vào bất kỳ lớp nào, không cần phải là chế độ xem hoặc bộ điều khiển xem. Ngay cả trong đại biểu ứng dụng của bạn.
Chuyển 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)
hơn bộ nhớ đệm thông báo
@objc func orientationChanged(notification : NSNotification) {
//your code there
}
Trong mục tiêu C
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
Trong nhanh chóng
func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Ghi đè phương thức này để phát hiện sự thay đổi định hướng.
Swift 3 | UIDeviceOrientationDidChange Thông báo được quan sát quá thường xuyên
Đoạn mã sau in "deviceDidRotate" mỗi khi thiết bị của bạn thay đổi hướng trong không gian 3D - bất kể thay đổi từ hướng dọc sang hướng ngang. Ví dụ: nếu bạn giữ điện thoại của mình theo hướng dọc và nghiêng điện thoại về phía trước và phía sau - deviceDidRotate () được gọi liên tục.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIDeviceOrientationDidChange,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Để khắc phục điều này, bạn có thể giữ hướng thiết bị trước đó và kiểm tra sự thay đổi trong 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")
}
Hoặc bạn có thể sử dụng một thông báo khác chỉ được gọi khi thiết bị thay đổi từ ngang sang dọc. Trong trường hợp này, bạn muốn sử dụng UIApplicationDidChangeStatusBarOrientation
thông báo.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(deviceDidRotate),
name: .UIApplicationDidChangeStatusBarOrientation,
object: nil
)
}
func deviceDidRotate() {
print("deviceDidRotate")
}
Thực hiện đầy đủ cách thực hiện cách phát hiện thay đổi định hướng trong Swift 3.0.
Tôi đã chọn sử dụng triển khai này vì định hướng điện thoại face up
và face down
quan trọng đối với tôi và tôi muốn chế độ xem chỉ thay đổi khi tôi biết hướng ở vị trí đã chỉ định.
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")
}
}
}
Những phần quan trọng cần lưu ý là:
unknown
hướng.Hy vọng ai đó tìm thấy điều này hữu ích.
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)")
}
Nếu bạn muốn làm một cái gì đó SAU khi xoay xong, bạn có thể sử dụng UIViewControllerTransitionCoordinator
trình xử lý hoàn thành như thế này
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()
}
}
Vì iOS 8, đây là cách chính xác để làm điều đó.
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`
})
}
Kiểm tra xem xoay có thay đổi với: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
Với coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext)
bạn có thể kiểm tra xem quá trình chuyển đổi đã kết thúc chưa.
Xem mã dưới đây:
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")
}
}
Đây là một cách dễ dàng để phát hiện hướng thiết bị: ( 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
bị phản đối bây giờ, sử dụng tốt hơn 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
}
}
Rất nhiều câu trả lời không giúp ích gì khi cần phát hiện trên nhiều bộ điều khiển xem khác nhau. Đây là một mẹo.
viewWillDisappear
và thêm addObserver
vào viewDidLoad
. iOS hủy đăng ký bộ điều khiển xem tự động.
UIDevice.current.orientation.isFlat
Cách tiếp cận của tôi tương tự như những gì bpedit thể hiện ở trên, nhưng với trọng tâm iOS 9+. Tôi muốn thay đổi phạm vi của FSCalWiki khi chế độ xem xoay.
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)
}
Điều này dưới đây đã làm việc, nhưng tôi cảm thấy ngượng ngùng về nó :)
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
}
}
Tôi sử dụng UIUserInterfaceSizeClass
để phát hiện một hướng thay đổi trong một UIViewController
lớp giống như vậy:
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...
}
}
Dành cho 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
Swift 5
Lớp thiết lập để nhận thông báo thay đổi hướng thiết bị:
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)
...
}
...
}
Thiết lập mã xử lý:
@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");
}
}
LƯU Ý: Chỉ cần sử dụng mã này để xác định UIViewControll theo hướng nào
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...
}
Với iOS 13.1.2, định hướng luôn trả về 0 cho đến khi thiết bị được xoay. Tôi cần gọi UIDevice.c hiện.beginGeneratingDeviceOrientationNotutions () để có được vòng quay thực tế trước khi bất kỳ sự kiện xoay vòng nào xảy ra.