iOS8에서 [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의 임시 버그입니까?
예, iOS8에서는 버그가 아니라 방향에 따라 다릅니다. 자세한 내용은 WWDC 2014의 세션 214를 검토 할 수 있습니다. "iOS 8의 컨트롤러 고급보기"
프레젠테이션에서 인용 :
UIScreen은 이제 인터페이스 지향입니다 :
- [UIScreen 경계] 이제 인터페이스 지향
- [UIScreen applicationFrame] 이제 인터페이스 지향
- 상태 표시 줄 프레임 알림은 인터페이스 지향
- 키보드 프레임 알림은 인터페이스 지향
예, iOS8에서는 방향에 따라 다릅니다.
이전 버전의 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;
}
그렇습니다. 실제로 화면 크기는 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;
}
예, 이제 방향에 따라 다릅니다.
위의 답변 중 일부가 방향과 무관하게 화면 크기를 얻는 방법을 선호합니다. 단순하고 방향 코드에 의존하지 않기 때문에 (상태는 호출 된 시간) 또는 버전 확인 중입니다. 새로운 iOS 8 동작을 원할 수도 있지만 모든 iOS 버전에서 안정적으로 작동해야하는 경우 작동합니다.
+(CGSize)screenSizeOrientationIndependent {
CGSize screenSize = [UIScreen mainScreen].bounds.size;
return CGSizeMake(MIN(screenSize.width, screenSize.height), MAX(screenSize.width, screenSize.height));
}
내 문제를 해결 한이 질문과 관련하여 화면 너비 및 높이 계산에 사용하는 두 가지 정의가 있습니다.
#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을 모두 지원하는 경우이 문제에 가장 적합한 솔루션입니다.
사용할 수 있습니다 nativeBounds
(방향 독립적)
nativeBounds
실제 화면의 경계 사각형으로 픽셀 단위로 측정됩니다. (읽기 전용)
선언 스위프트
var nativeBounds: CGRect { get }
이 사각형은 세로 방향의 장치를 기준으로합니다. 장치가 회전해도이 값은 변경되지 않습니다.
장치 높이 감지 :
if UIScreen.mainScreen().nativeBounds.height == 960.0 {
}
장치 너비 감지 :
if UIScreen.mainScreen().nativeBounds.width == 640.0 {
}
iOS 8 SDK의 버그는 아닙니다. 그들은 경계 인터페이스 방향에 의존했습니다. 그 사실에 대한 일부 참조 또는 문서에 대한 귀하의 질문에 따르면 WWDC 2014View Controller Advancements in iOS 8
에서 214 세션 을 시청 하는 것이 좋습니다 . 가장 흥미로운 부분은 (의심에 따라) 50:45에서 시작하는 것입니다.Screen Coordinates
예, iOS8에서는 방향에 따라 다릅니다.
다음은 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
내 솔루션은 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;
}
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;
}
아래 방법을 사용하면 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];
그것이 올바른 rect를 계산하는 데 사용한 것입니다.
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
위의 답변은 우수한 cbartel 기능의 신속한 버전을 추가하는 것입니다.
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
}
내 문제는 마이너스로 가고있는 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)];
그리고 나를 위해 그 일을 시도하십시오.
내가 주목 한 것은 Info.plist에서 지원되는 인터페이스 방향 의 순서 가 중요 하다는 것입니다 . 코드에서 방향을 지정하는 내 응용 프로그램 에서이 질문의 문제가 발생했지만 기본 방향이 세로 인 곳을 지정하지 않았습니다.
어쨌든 기본 방향 은 세로 라고 생각했습니다 .
Info.plist에서 itens를 다시 정렬하여 Portrait를 먼저 설정하면 예상되는 동작이 복원되었습니다.
이것은 iOS7 과 iOS8 에서 올바른 장치를 제공합니다 .
#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;
}
//You may add more devices as well(i.e.iPad).
iOS 8 or upper
A solution for those who want to find out the screen size in points (3.5 inches screen has 320 × 480 points, 4.0 inches screen has 320 × 568 points, etc) would be
- (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;
}
}
Used slightly modified mnemia's solution, that one without iOS version check, using min/max on mainscreen bounds.
I needed a CGRect
so got CGRect
from mainscreen bounds and changed size.width=min(w,h)
, size.height=max(w,h)
. Then I called that OS-independent get CGRect
function in two places in my code, where I getting screen size for OpenGL
, touches etc. Before fix I had 2 problems - on IOS 8.x in landscape mode display position of OpenGL
view was incorrect: 1/4 of full screen in left bottom part. And second touches returned invalid values. Both problems were fixed as explained. Thanks!
'IT' 카테고리의 다른 글
왜 GCC는 거의 동일한 C 코드에 대해 이렇게 완전히 다른 어셈블리를 생성합니까? (0) | 2020.05.17 |
---|---|
Linux에서 Latex 시작하기 (0) | 2020.05.17 |
CSS를 사용하여 입력 버튼 이미지를 변경하는 방법은 무엇입니까? (0) | 2020.05.17 |
WPF 탐색을위한 Window vs Page vs UserControl? (0) | 2020.05.17 |
주요 브라우저에서 구현 한 XHTML의 모든 유효한 자동 폐쇄 요소는 무엇입니까? (0) | 2020.05.17 |