Получить текущую ориентацию устройства (расширение приложения)
Как получить текущую ориентацию устройства в расширении приложения, я попробовал ниже два метода, но безуспешно.
Всегда возвращать UIDeviceOrientationUnknown
[[UIDevice currentDevice] orientation]
На нем отображается красное сообщение о том, что "sharedApplication" недоступно на iOS (расширение приложения)
[[UIApplication sharedApplication] statusBarOrientation];
Я также добавляю наблюдателя, но мне не звонят.
[[NSNotificationCenter defaultCenter] addObserver:self.view selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; - (void)notification_OrientationWillChange:(NSNotification*)n { UIInterfaceOrientation orientation = (UIInterfaceOrientation)[[n.userInfo objectForKey:UIApplicationStatusBarOrientationUserInfoKey] intValue]; if (orientation == UIInterfaceOrientationLandscapeLeft) [self.textDocumentProxy insertText:@"Left"]; if (orientation == UIInterfaceOrientationLandscapeRight) [self.textDocumentProxy insertText:@"Right"]; }
Так что теперь, как кто-то может получить текущую ориентацию устройства.
11 ответов
У меня есть идея!
extension UIScreen {
var orientation: UIInterfaceOrientation {
let point = coordinateSpace.convertPoint(CGPointZero, toCoordinateSpace: fixedCoordinateSpace)
if point == CGPointZero {
return .Portrait
} else if point.x != 0 && point.y != 0 {
return .PortraitUpsideDown
} else if point.x == 0 && point.y != 0 {
return .LandscapeLeft
} else if point.x != 0 && point.y == 0 {
return .LandscapeRight
} else {
return .Unknown
}
}
}
РЕДАКТИРОВАТЬ: На Swift 4 вы можете сделать:
extension UIScreen {
var orientation: UIInterfaceOrientation {
let point = coordinateSpace.convert(CGPoint.zero, to: fixedCoordinateSpace)
switch (point.x, point.y) {
case (0, 0):
return .portrait
case let (x, y) where x != 0 && y != 0:
return .portraitUpsideDown
case let (0, y) where y != 0:
return .landscapeLeft
case let (x, 0) where x != 0:
return .landscapeRight
default:
return .unknown
}
}
}
Я нашел способ, которым мы можем рассчитать ориентацию нашего устройства, например, в (Расширение приложения)
- (void)viewDidLayoutSubviews
{
if(self.view.frame.size.width > self.view.frame.size.height)
NSLog(@"Landscape");
else
NSLog(@"Portrait");
}
Это дает мне правильную ориентацию, но все равно не получается, так как устройство это LandscapeLeft или LandscapeRight, а также Portrait или PortraitUpsideDown.
Все еще нужна помощь.
В BroadcastExtension вы можете использовать sampleBuffer, чтобы понять ориентацию:
if let orientationAttachment = CMGetAttachment(sampleBuffer, RPVideoSampleOrientationKey as CFString, nil) as? NSNumber
{
let orientation = CGImagePropertyOrientation(rawValue: orientationAttachment.uint32Value)
}
Метод наблюдателя будет вызван, если вы добавите это раньше:[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
Редактировать: я использую UIApplicationDidChangeStatusBarOrientationNotification
для наблюдателя
И в моем методе я проверяю:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
BOOL isPortrait = UIDeviceOrientationIsPortrait(orientation);
Редактировать 2- Xcode 6.2 - iOS 7 & 8
Кажется, что если вы хотите использовать это как на iOS 7, так и на 8, приведенный выше код даст вам неверный результат на iOS 7.
Поэтому я использую что-то еще, потому что в iOS 7 границы основного экрана никогда не изменятся, но в iOS 8 изменится, если ориентация изменится.
У меня есть 3 макроса, которые дают мне правильный размер ширины и высоты экрана независимо от версии iOS:
#define IOS_VERSION_OLDER_THAN_8 ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
#define SCREEN_WIDTH_CALCULATED (IOS_VERSION_OLDER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) : [[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT_CALCULATED (IOS_VERSION_OLDER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) : [[UIScreen mainScreen] bounds].size.height)
Затем, когда уведомление запускается, я проверяю ориентацию следующим образом:
BOOL isPortrait = SCREEN_WIDTH_CALCULATED < SCREEN_HEIGHT_CALCULATED;
Это будет работать на iOS 7 и iOS 8, но я не проверял более старые версии Xcode, только 6.2
Это вернется, только если устройство находится в книжной или альбомной ориентации, не все 4 типа ориентации
Использование CoreMotion Framework позволяет получить ориентацию устройства.
func startMonitorDeviceOrientation() {
if motionManager.isDeviceMotionAvailable {
motionManager.deviceMotionUpdateInterval = 1.0
let queue = OperationQueue()
motionManager.startDeviceMotionUpdates(to: queue) { (deviceMotion, error) in
guard let x = deviceMotion?.gravity.x,
let y = deviceMotion?.gravity.y
else {
return
}
if fabs(y) >= fabs(x) {
if y >= 0 {
// UIDeviceOrientationPortraitUpsideDown;
print("device orientation UIDeviceOrientationPortraitUpsideDown")
} else {
// UIDeviceOrientationPortrait;
print("device orientation UIDeviceOrientationPortrait")
}
} else {
if x >= 0 {
// UIDeviceOrientationLandscapeRight;
print("device orientation UIDeviceOrientationLandscapeRight")
} else {
// UIDeviceOrientationLandscapeLeft;
print("device orientation UIDeviceOrientationLandscapeLeft")
}
}
}
} else {
print("Device motion is not avaliable")
}
}
Удобный метод расширения, просто позвоните
UIInterfaceOrientation.current
extension UIInterfaceOrientation {
static var current: UIInterfaceOrientation {
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? UIInterfaceOrientation.portrait
}
}
Я знаю, что уже поздно, но ошибка в этом вопросе была в этой строке:
[[NSNotificationCenter defaultCenter] addObserver:self.view selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
addObserver:self.view
неправильно, уведомление должно быть прикреплено на self
быть призванным Работа также на iOS8.
Мне не удалось заставить его работать в расширении приложения iMessage. Apple, кажется, молча отключил его, насколько я могу судить. https://forums.developer.apple.com/thread/53981
Я сделал в моем собственном расширении клавиатуры, надеюсь, это поможет вам..
Чтобы обновить пользовательскую клавиатуру при изменении ориентации, переопределите viewDidLayoutSubviews в UIInputViewController. Другими словами, мы можем сказать, что viewDidLayoutSubviews всегда вызывается, когда вращение сделано.
В расширении клавиатуры мы не можем использовать традиционный поток, как мы обычно использовали:
[UIApplication sharedApplication] statusBarOrientation]
Таким образом, чтобы определить текущую ориентацию, я использовал следующий код: В Objc:
if([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height){
// Portrait Orientation
}
else{
//Landscape Orientation
}
И в swift4 вы можете использовать это:
if UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height {
//portrait Orientation
}
else
{
//landscape Orientation
}
Этот код не даст вам точную UIDeviceOrientation, но вы сможете узнать, в книжном или альбомном режиме
BOOL isLandScape = !(self.view.frame.size.width == ([[UIScreen mainScreen] bounds].size.width*([[UIScreen mainScreen] bounds].size.width<[[UIScreen mainScreen] bounds].size.height))+([[UIScreen mainScreen] bounds].size.height*([[UIScreen mainScreen] bounds].size.width>[[UIScreen mainScreen] bounds].size.height)));