Comment obtenir l'orientation actuelle du périphérique dans une extension d'application, j'ai essayé ci-dessous deux méthodes, mais sans succès.
Il retourne toujours UIDeviceOrientationUnknown
[[UIDevice currentDevice] orientation]
Il affiche un message rouge indiquant que «sharedApplication» n'est pas disponible sur iOS (App Extension).
[[UIApplication sharedApplication] statusBarOrientation];
J'ajoute aussi un observateur mais il ne s'appelle pas.
[[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"];
}
Alors maintenant, comment peut-on avoir une orientation de périphérique actuelle.
J'ai une idée!
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
}
}
}
EDIT: Sur Swift 4, vous pouvez faire:
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
}
}
}
J'ai trouvé un moyen de calculer l'orientation de notre appareil de cette manière dans (App Extension)
- (void)viewDidLayoutSubviews
{
if(self.view.frame.size.width > self.view.frame.size.height)
NSLog(@"Landscape");
else
NSLog(@"Portrait");
}
Cela me donne la bonne orientation mais ne fonctionne toujours pas car le périphérique est LandscapeLeft ou LandscapeRight ainsi que Portrait ou PortraitUpsideDown .
Encore besoin d'aide.
La méthode observateur sera appelée si vous ajoutez ceci avant: [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
Edit: J'utilise UIApplicationDidChangeStatusBarOrientationNotification
pour l'observateur
Et dans ma méthode je vérifie:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
BOOL isPortrait = UIDeviceOrientationIsPortrait(orientation);
Édition 2- Xcode 6.2 - iOS 7 & 8
Il semble que si vous voulez utiliser cela sur iOS 7 & 8, le code ci-dessus vous donnera un résultat erroné sur iOS 7.
J'utilise donc autre chose car sur iOS 7, les limites de l'écran principal ne changeront jamais, mais sur iOS 8, elles changeront si l'orientation change.
J'ai 3 macros qui me donneront la bonne taille de la largeur et de la hauteur de l'écran quelle que soit la version 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)
Puis, lorsque la notification est déclenchée, je vérifie l'orientation comme suit:
BOOL isPortrait = SCREEN_WIDTH_CALCULATED < SCREEN_HEIGHT_CALCULATED;
Cela fonctionnera sur iOS 7 et iOS 8, mais je n'ai pas vérifié d'anciennes versions de Xcode, seulement 6.2
Ceci ne sera renvoyé que si l'appareil est en mode portrait ou paysage, mais pas avec les 4 types d'orientation
Je sais qu'il est tard, mais l'erreur dans cette question était dans cette ligne:
[[NSNotificationCenter defaultCenter] addObserver:self.view selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
addObserver:self.view
est incorrect, la notification doit être jointe à self
pour être appelée. Fonctionne aussi sur iOS8.
Je n'ai pas réussi à le faire fonctionner dans une extension d'application iMessage. Apple semble l'avoir désactivé en silence, autant que je sache. https://forums.developer.Apple.com/thread/53981
L'utilisation de la structure CoreMotion permet d'obtenir l'orientation du périphérique.
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")
}
}
Dans BroadcastExtension, vous pouvez utiliser sampleBuffer pour comprendre l'orientation:
if let orientationAttachment = CMGetAttachment(sampleBuffer, RPVideoSampleOrientationKey as CFString, nil) as? NSNumber
{
let orientation = CGImagePropertyOrientation(rawValue: orientationAttachment.uint32Value)
}
Vous pouvez regarder this library et ses fourchettes . Il utilise CoreMotion pour détecter l'orientation du périphérique afin qu'il puisse fonctionner sur l'environnement restreint d'App Extension.