web-dev-qa-db-ja.com

iOS 8では[UIScreen mainScreen] .bounds.sizeは向きに依存するようになりますか?

私はiOS 7とiOS 8の両方で次のコードを実行しました。

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
BOOL landscape = (orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight);
NSLog(@"Currently landscape: %@, width: %.2f, height: %.2f", 
      (landscape ? @"Yes" : @"No"), 
      [[UIScreen mainScreen] bounds].size.width, 
      [[UIScreen mainScreen] bounds].size.height);

以下はiOS 8からの結果です。

Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 568.00, height: 320.00

IOS 7の結果と比較すると、

Currently landscape: No, width: 320.00, height: 568.00
Currently landscape: Yes, width: 320.00, height: 568.00

この変更を明記した文書はありますか?それともiOS 8 APIの一時的なバグですか?

182
lwxted

はい、iOS 8では向きに依存しますが、バグではありません。詳細については、WWDC 2014のセッション214を参照してください。 「iOS 8でView Controller Advancements」

プレゼンテーションから引用:

UIScreenはインターフェース指向になりました。

  • [UIScreen bounds]今インターフェース指向
  • [UIScreen applicationFrame]はインターフェース指向になりました
  • ステータスバーフレーム通知はインターフェース指向です
  • キーボードフレーム通知はインタフェース指向です
173
vhristoskov

はい、iOS 8では向きに依存します。

私はOSの古いバージョンをサポートする必要があるアプリのためにこの問題を解決するためにUtilメソッドを書きました。

+ (CGSize)screenSize {
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    if ((NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        return CGSizeMake(screenSize.height, screenSize.width);
    }
    return screenSize;
}
59
cbartel

はい、確かに、iOS 8では画面サイズが向きに依存するようになりました。ただし、サイズを縦向きに固定したい場合があります。これが私のやり方です。

+ (CGRect)screenBoundsFixedToPortraitOrientation {
    UIScreen *screen = [UIScreen mainScreen];

    if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
                    return [screen.coordinateSpace convertRect:screen.bounds toCoordinateSpace:screen.fixedCoordinateSpace];
    } 
    return screen.bounds;
}
34
MaxK

はい、それは今オリエンテーションに依存しています。

画面サイズを向きに依存しない方法で上記のいくつかの回答よりも小さくする方法は、単純であることと、どの向きコードにも依存しないこと(両方の状況に依存する可能性があるため)の両方を好みます。それらが呼ばれる時間)またはバージョンチェックの時。あなたは新しいiOS 8の振る舞いを望んでいるかもしれませんが、あなたがそれをiOSのすべてのバージョンで安定させる必要があるなら、これはうまくいくでしょう。

+(CGSize)screenSizeOrientationIndependent {
     CGSize screenSize = [UIScreen mainScreen].bounds.size;
     return CGSizeMake(MIN(screenSize.width, screenSize.height), MAX(screenSize.width, screenSize.height));
}
32
mnemia

それが私の問題を解決したのでこの質問に関連して、ここで2つは私がスクリーンの幅と高さの計算に使う定義を定義する:

#define SCREEN_WIDTH (IOS_VERSION_LOWER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) : [[UIScreen mainScreen] bounds].size.width)

#define SCREEN_HEIGHT (IOS_VERSION_LOWER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) : [[UIScreen mainScreen] bounds].size.height)

#define IOS_VERSION_LOWER_THAN_8 (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)

IOS 7とiOS 8の両方をサポートしている場合は、これがこの問題に対する最善の解決策です。

11
Antoine

nativeBoundsを使用できます(向きに依存しません)

nativeBounds

物理画面の外接矩形(ピクセル単位)。 (読み取り専用)

宣言スウィフト

  var nativeBounds: CGRect { get }

この長方形は、縦向きのデバイスに基づいています。この値はデバイスが回転しても変わりません。

装置の高さを検出する:

if UIScreen.mainScreen().nativeBounds.height == 960.0 {

}

デバイスの幅を検出する:

if UIScreen.mainScreen().nativeBounds.width == 640.0 {

}
9
Leo Dabus

IOS 8 SDKのバグではありません。 境界インターフェースの方向に依存するようになりました。その事実に関するいくつかの参照またはドキュメントに関する質問によると、 WWDC 2014の214セッションであるView Controller Advancements in iOS 8を視聴することを強くお勧めします。 。最も興味深い部分は(あなたの疑問によると)50:45から始まるScreen Coordinatesです。

8
Julian Król

はい、iOS 8では向きに依存します。

SDKとOSのバージョンを問わず、iOS 8のように境界を読み取るための一貫した方法があります。

#ifndef NSFoundationVersionNumber_iOS_7_1
# define NSFoundationVersionNumber_iOS_7_1 1047.25
#endif

@implementation UIScreen (Legacy)

// iOS 8 way of returning bounds for all SDK's and OS-versions
- (CGRect)boundsRotatedWithStatusBar
{
    static BOOL isNotRotatedBySystem;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        BOOL OSIsBelowIOS8 = [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0;
        BOOL SDKIsBelowIOS8 = floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1;
        isNotRotatedBySystem = OSIsBelowIOS8 || SDKIsBelowIOS8;
    });

    BOOL needsToRotate = isNotRotatedBySystem && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
    if(needsToRotate)
    {
        CGRect screenBounds = [self bounds];
        CGRect bounds = screenBounds;
        bounds.size.width = screenBounds.size.height;
        bounds.size.height = screenBounds.size.width;
        return bounds;
    }
    else
    {
        return [self bounds];
    }
}

@end
5
hfossli

私の解決策は、MaxKとhfossliを組み合わせたものです。このメソッドをUIScreenのカテゴリで作成しましたが、バージョンチェックは行われていません(これは不適切な方法です)。

//Always return the iOS8 way - i.e. height is the real orientation dependent height
+ (CGRect)screenBoundsOrientationDependent {
    UIScreen *screen = [UIScreen mainScreen];
    CGRect screenRect;
    if (![screen respondsToSelector:@selector(fixedCoordinateSpace)] && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        screenRect = CGRectMake(screen.bounds.Origin.x, screen.bounds.Origin.y, screen.bounds.size.height, screen.bounds.size.width);
    } else {
        screenRect = screen.bounds;
    }

    return screenRect;
}
4
Uzair Khan

以下の方法は、iOSのバージョンとは関係なく、特定の方向の画面境界を見つけるために使用できます。このメソッドは、デバイスの画面サイズに基づいて境界を返し、iOSのバージョンに関係なく同じCGRect値を返します。

- (CGRect)boundsForOrientation:(UIInterfaceOrientation)orientation {

    CGFloat width   = [[UIScreen mainScreen] bounds].size.width;
    CGFloat height  = [[UIScreen mainScreen] bounds].size.height;

    CGRect bounds = CGRectZero;

    if (UIInterfaceOrientationIsLandscape(orientation)) {
        bounds.size = CGSizeMake(MAX(width, height), MIN(width, height));
    } else {
        bounds.size = CGSizeMake(MIN(width, height), MAX(width, height));
    }

    return bounds;
}

// For the below example, bounds will have the same value if you run the code on iOS 8.x or below versions.
CGRect bounds = [self boundsForOrientation:UIInterfaceOrientationPortrait]; 
3
user4226071

私はiOS8の下でiOS7と同じ振る舞いを保つクイックヘルパー関数を必要としていました - これは私が私の[[UIScreen mainScreen] bounds]呼び出しを交換することを可能にし、他のコードに触れないで...

+ (CGRect)iOS7StyleScreenBounds {
    CGRect bounds = [UIScreen mainScreen].bounds;
    if (([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0) && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) {
        bounds.size = CGSizeMake(bounds.size.height, bounds.size.width);
    }
        return bounds;
}
3
Joe Booth

正しい四角形を計算するために使用したものがその通りです。

UIScreen* const mainScreen = [UIScreen mainScreen];
CGRect rect = [mainScreen bounds];
#ifdef __IPHONE_8_0
if ([mainScreen respondsToSelector:@selector(coordinateSpace)])
{
    if ([mainScreen respondsToSelector:@selector(fixedCoordinateSpace)])
    {
        id tmpCoordSpace = [mainScreen coordinateSpace];
        id tmpFixedCoordSpace = [mainScreen fixedCoordinateSpace];

        if ([tmpCoordSpace respondsToSelector:@selector(convertRect:toCoordinateSpace:)])
        {
            rect = [tmpCoordSpace convertRect:rect toCoordinateSpace: tmpFixedCoordSpace];
        }
    }
}
#endif
1
hhamm

私の問題はマイナスになっていたUIWindowsフレームに関連していました。だからMyViewControllerで以下のようにコードを作った - (NSUInteger)supportedInterfaceOrientationsメソッド

[[UIApplication sharedApplication] setStatusBarHidden:NO];

[self.view setFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];

[appDel.window setFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height)];

そして私のためにその仕事はそれを試してみてください。

1
Hardik Mamtora

上で答えた優れたcbartel関数のSwiftバージョンを追加するだけです。

func screenSize() -> CGSize {
    let screenSize = UIScreen.mainScreen().bounds.size
    if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) && UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) {
        return CGSizeMake(screenSize.height, screenSize.width)
    }
    return screenSize
}
1
Martin Koles

わずかに修正されたmnemiaのソリューションを使用しました。iOSバージョンチェックなしで、メイン画面の境界でmin/maxを使用します。
CGRectが必要だったので、メイン画面の境界からCGRectを取得し、size.width=min(w,h)size.height=max(w,h)を変更しました。次に、コード内の2つの場所でOSに依存しないget CGRect関数を呼び出し、そこでOpenGLの画面サイズ、タッチなどを取得しました。修正前に、2つの問題がありました-IOS 8.x OpenGLビューの位置が正しくありませんでした:左下部分の全画面の1/4。また、2回目のタッチで無効な値が返されました。説明したように両方の問題が修正されました。ありがとう!

0
NoAngel

私が注目したことの1つは、Info.plistでサポートされているインターフェースの向きのorderが重要です。私は自分のアプリでこの問題の問題を抱えていました(それはコードの向きを決める)が、デフォルトの向きが縦向きであることをどこにも指定しませんでした。

私はそのデフォルトの向きを考えましたあったいずれにせよポートレート。

Info.plistでitensを並べ替えて、Portraitを最初に配置すると、予想される動作が復元されました。

0
epx

これはiOS7iOS8の両方で正しいデバイスを提供します。

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define IS_PORTRAIT         UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)

+ (BOOL)isIPHONE4{

// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

        if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 480.0) {
            return YES;
        } else {
            return NO;
        }

// >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 480.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 480.0 && [self getDeviceHeight] == 320.0) {
            return YES;
        } else {
            return NO;
        }

    }

}


}

+ (BOOL)isIPHONE5{


// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

    if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 568.0) {
        return YES;
    } else {
        return NO;
    }

    // >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 320.0 && [self getDeviceHeight] == 568.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 568.0 && [self getDeviceHeight] == 320.0) {
            return YES;
        } else {
            return NO;
        }

    }

}

}

+ (BOOL)isIPHONE6{

// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

    if ([self getDeviceWidth] == 375.0 && [self getDeviceHeight] == 667.0) {
        return YES;
    } else {
        return NO;
    }

    // >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 375.0 && [self getDeviceHeight] == 667.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 667.0 && [self getDeviceHeight] == 375.0) {
            return YES;
        } else {
            return NO;
        }

    }

}


}
+ (BOOL)isIPHONE6Plus{


// < iOS 8.0
if(SYSTEM_VERSION_LESS_THAN(@"8.0")){

    if ([self getDeviceWidth] == 414.0 && [self getDeviceHeight] == 736.0) {
        return YES;
    } else {
        return NO;
    }

    // >= iOS 8.0
}else{

    if(IS_PORTRAIT){

        if ([self getDeviceWidth] == 414.0 && [self getDeviceHeight] == 736.0) {
            return YES;
        } else {
            return NO;
        }

    }else{

        if ([self getDeviceWidth] == 736.0 && [self getDeviceHeight] == 414.0) {
            return YES;
        } else {
            return NO;
        }

    }

}


}

+ (CGFloat)getDeviceHeight{

//NSLog(@"Device width: %f",[UIScreen mainScreen].bounds.size.height);
return [UIScreen mainScreen].bounds.size.height;
}
+ (CGFloat)getDeviceWidth{

//NSLog(@"Device width: %f",[UIScreen mainScreen].bounds.size.height);
return [UIScreen mainScreen].bounds.size.width;
}

//デバイスを追加することもできます(例:iPad)。

0
Zaid Pathan

iOS 8以上

画面サイズをポイント単位で調べたい(3.5インチ画面の320×480ポイント、4.0インチ画面の320×568ポイントなど)場合の解決策は次のとおりです。

- (CGSize)screenSizeInPoints
{
    CGFloat width = [[UIScreen mainScreen] bounds].size.width;
    CGFloat height = [[UIScreen mainScreen] bounds].size.height;

    if (width > height) {
        return CGSizeMake(height, width);
    }
    else {
        return [[UIScreen mainScreen] bounds].size;
    }
}
0
tesla