Обнаружение размеров экрана iPhone 6/6 + в значениях точек

Учитывая недавно анонсированные размеры экранов iPhone 6 :

iPhone 6: 1334h * 750w @2x (in points: 667h * 375w)
iPhone 6+: 1920 * 1080 @3x (in points: 640h * 360w)

Мне было интересно, есть ли код, который позволяет мне определить размер экрана, на котором находится пользовательское устройство, чтобы я мог настраивать и размер UIImages и другие материалы соответственно с пользовательским устройством.

До сих пор я использовал следующее:

- (NSString *) platform{
    size_t size;
    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
    char *machine = malloc(size);
    sysctlbyname("hw.machine", machine, &size, NULL, 0);
    NSString *platform = [NSString stringWithUTF8String:machine];
    free(machine);
    return platform;
}

- (NSString *) platformString{
    NSString *platform = [self platform];
    if ([platform isEqualToString:@"iPhone1,1"])    return @"iPhone 1G";
    if ([platform isEqualToString:@"iPhone1,2"])    return @"iPhone 3G";
    if ([platform isEqualToString:@"iPhone2,1"])    return @"iPhone 3GS";
    if ([platform isEqualToString:@"iPhone3,1"])    return @"iPhone 4";
    if ([platform isEqualToString:@"iPhone3,3"])    return @"Verizon iPhone 4";
    if ([platform isEqualToString:@"iPhone4,1"])    return @"iPhone 4S";
    if ([platform isEqualToString:@"iPhone5,1"])    return @"iPhone 5 (GSM)";
    if ([platform isEqualToString:@"iPhone5,2"])    return @"iPhone 5 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPhone5,3"])    return @"iPhone 5c (GSM)";
    if ([platform isEqualToString:@"iPhone5,4"])    return @"iPhone 5c (GSM+CDMA)";
    if ([platform isEqualToString:@"iPhone6,1"])    return @"iPhone 5s (GSM)";
    if ([platform isEqualToString:@"iPhone6,2"])    return @"iPhone 5s (GSM+CDMA)";
    if ([platform isEqualToString:@"iPod1,1"])      return @"iPod Touch 1G";
    if ([platform isEqualToString:@"iPod2,1"])      return @"iPod Touch 2G";
    if ([platform isEqualToString:@"iPod3,1"])      return @"iPod Touch 3G";
    if ([platform isEqualToString:@"iPod4,1"])      return @"iPod Touch 4G";
    if ([platform isEqualToString:@"iPod5,1"])      return @"iPod Touch 5G";
    if ([platform isEqualToString:@"iPad1,1"])      return @"iPad";
    if ([platform isEqualToString:@"iPad2,1"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,2"])      return @"iPad 2 (GSM)";
    if ([platform isEqualToString:@"iPad2,3"])      return @"iPad 2 (CDMA)";
    if ([platform isEqualToString:@"iPad2,4"])      return @"iPad 2 (WiFi)";
    if ([platform isEqualToString:@"iPad2,5"])      return @"iPad Mini (WiFi)";
    if ([platform isEqualToString:@"iPad2,6"])      return @"iPad Mini (GSM)";
    if ([platform isEqualToString:@"iPad2,7"])      return @"iPad Mini (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,1"])      return @"iPad 3 (WiFi)";
    if ([platform isEqualToString:@"iPad3,2"])      return @"iPad 3 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad3,3"])      return @"iPad 3 (GSM)";
    if ([platform isEqualToString:@"iPad3,4"])      return @"iPad 4 (WiFi)";
    if ([platform isEqualToString:@"iPad3,5"])      return @"iPad 4 (GSM)";
    if ([platform isEqualToString:@"iPad3,6"])      return @"iPad 4 (GSM+CDMA)";
    if ([platform isEqualToString:@"iPad4,1"])      return @"iPad Air (WiFi)";
    if ([platform isEqualToString:@"iPad4,2"])      return @"iPad Air (Cellular)";
    if ([platform isEqualToString:@"iPad4,4"])      return @"iPad mini 2G (WiFi)";
    if ([platform isEqualToString:@"iPad4,5"])      return @"iPad mini 2G (Cellular)";
    if ([platform isEqualToString:@"i386"])         return @"Simulator";
    if ([platform isEqualToString:@"x86_64"])       return @"Simulator";
    return platform;
}

Как таковые, следует ли предположить, что iPhone7,1 и iPhone7,2 являются iPhone 6, а iPhone7,3 и iPhone7.4 являются плюсами? Если у кого-то есть более конкретный способ сказать, что это будет здорово, спасибо.!

Ответ 1

Первым экраном будет экран устройства. Обратите внимание, что перед отправкой необходимо добавить изображения запуска для новых телефонов, иначе приложение будет запущено в Zoomed Mode для более старых приложений: Вот код, который я использовал, чтобы проверить это. Примечание. Это работает только с версией iOS 8 и выше:

UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
          NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale);

Код для обнаружения iPhone 6 Plus:

#define IS_PAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_PHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)

-(BOOL)iPhone6PlusDevice{
    if (!IS_PHONE) return NO;
    if ([UIScreen mainScreen].scale > 2.9) return YES;   // Scale is only 3 when not in scaled mode for iPhone 6 Plus
    return NO;
}

или

-(BOOL) iPhone6PlusUnZoomed{
    if ([self iPhone6PlusDevice]){
        if ([UIScreen mainScreen].bounds.size.height > 720.0) return YES;  // Height is 736, but 667 when zoomed.
    }
    return NO;
}

Примечание. Если вы проверяете iPhone 6 Plus, чтобы настроить пользовательский интерфейс, тогда не полагайтесь на .nativeScale, потому что имитатор и фактическое устройство дают разные результаты. Из-за комментария ниже. Масштаб - это CGFloat, и поэтому код не должен проверять равенство, поскольку некоторые значения float никогда не могут быть равны.


После добавления загрузочных изображений для нового iPhone6 ​​ и 6Plus размеры меняются. Они масштабируют старые приложения, чтобы они соответствовали экрану.

Размер для iPhone 6 Plus и iPhone 6S Plus с масштабированием @3x (название Apple: Retina HD 5.5), пространство координат: < сильные > 414 x 736 и 1242 x 2208 пикселей, 401 точек на дюйм, физический размер экрана 2,7 x 4,8 дюйма или 68 x 122 мм:

Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; 
mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000

Размер для iPhone 6 и iPhone 6S с масштабированием @2x (название Apple: Retina HD 4.7), пространство координат: 375 x 667 и 750 x 1334 пикселей, 326 точек на дюйм, физический размер экрана - 2,3 x 4,1 дюйма или 58 x 104 мм:

Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; 
mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

И iPhone 5 для сравнения - 640 x 1136, iPhone 4 640 x 960.

Примечание. Загрузите LaunchImages, иначе приложение будет запускаться с масштабированием и не отображать правильное масштабирование или размеры экрана.

Comparing iPhone 6 and 6 Plus

Ответ 2

Если вы предпочитаете макросы, это те, которые вы можете использовать, чтобы различать модели iPhone. Они основаны на значениях точек.

#define IS_IPHONE_4 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)480) < DBL_EPSILON)
#define IS_IPHONE_5 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE_6 (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)667) < DBL_EPSILON)
#define IS_IPHONE_6_PLUS (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)736) < DBL_EPSILON)

Ответ 3

Я использую следующий код, чтобы определить, какое устройство работает (оно немного быстро и грязно, но оно делает трюк)

if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone ){

    CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height;
    CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
    if( screenHeight < screenWidth ){
        screenHeight = screenWidth;
    }

    if( screenHeight > 480 && screenHeight < 667 ){
        NSLog(@"iPhone 5/5s");
    } else if ( screenHeight > 480 && screenHeight < 736 ){
        NSLog(@"iPhone 6");
    } else if ( screenHeight > 480 ){
        NSLog(@"iPhone 6 Plus");
    } else {
        NSLog(@"iPhone 4/4s");
    }
}

(Это работает только тогда, когда iPhone 6/6 Plus включен, добавив соответствующие заставки)

Ответ 4

На физическом устройстве основные ограничения экрана iPhone 6 Plus - 2208x1242, а nativeBounds - 1920x1080. Существует аппаратное масштабирование для изменения размера на физический дисплей.

В симуляторе основные ограничения экрана iPhone 6 Plus и nativeBounds - это 2208x1242.

Другими словами... Видео, OpenGL и другие вещи, основанные на CALayers, которые имеют дело с пикселями, будут иметь дело с реальным фреймбуфером 1920x1080 на устройстве (или 2208x1242 на симе). Вещи, касающиеся точек в UIKit, будут иметь дело с границами 2208x1242 (x3) и масштабироваться по мере необходимости на устройстве.

Симулятор не имеет доступа к тому же оборудованию, которое делает масштабирование на устройстве, и нет никакой пользы для имитации его в программном обеспечении, поскольку они будут давать разные результаты, чем аппаратное обеспечение. Таким образом, имеет смысл установить для nativeBounds основного экрана имитируемого устройства границы основного экрана физического устройства.

iOS 8 добавил API в UIScreen (nativeScale и nativeBounds), чтобы разработчик смог определить разрешение CAD файла, соответствующего UIScreen.

Ответ 5

Проверьте обновленный список wiki, там я получил 7,2 для iPhone 6 и 7,1 для iPhone 6 плюс.

Ответ 6

Вы можете обнаружить iPhone 6 Plus на основе собственного масштаба, используя этот макрос:

#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_6PLUS (IS_IPHONE && [[UIScreen mainScreen] nativeScale] == 3.0f)

Ответ 7

Ответ Ханнес Сверриссон почти правильный. Система координат iPhone 6 на самом деле больше, чем 5 секунд. Используя его код:

UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
      NSStringFromCGRect(mainScreen.bounds), mainScreen.coordinateSpace, mainScreen.scale, mainScreen.nativeScale);

Система координат для приложений, обеспечивающих правильные изображения запуска:

Размер для iPhone 6 (Retina HD 4.7) с масштабированием @2x, пространство координат: 375 x 667 и 750 x 1334 фактических точек:

Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fa01b5182d0; bounds = {{0, 0}, {375, 667}}; 
mode = <UIScreenMode: 0x7fa01b711760; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

Размер для iPhone 6 Plus (Retina HD 5.5) с масштабированием @3x, пространство координат: 414 x 736 и 1242 x 2208 фактических точек:

Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f97fad330b0; bounds = {{0, 0}, {414, 736}}; 
mode = <UIScreenMode: 0x7f97fae1ce00; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000

Ответ 8

Это то, что я использую в своем приложении с iOS 8:

window=[[[UIApplication sharedApplication] windows] firstObject];

NSLog(@"screenHeight=%f width=%f",window.frame.size.height,window.frame.size.width);

if (window.frame.size.height == 480) {

        do stuff here... 
    }

До Xcode6/iOS 8 я использовал это, но границы экрана не работают должным образом с изменяемым по размеру симулятором или, по крайней мере, в бета-версиях Xcode6...

CGRect screenBounds=[[UIScreen mainScreen] bounds];

if (screenBounds.size.height >= 568) {

do stuff here...

}

Ответ 9

Мне пришлось обнаружить iPhone 6 Plus в приложении, построенном на iOS 7. Поскольку nativeScale недоступен на [UIScreen mainScreen], я попытался использовать масштаб [UIScreen mainScreen]], но это только что вернуло 2.0. Поэтому я придумал это решение для обнаружения iPhone 6 Plus на iOS 7 (также должен работать на iOS 8):

-(BOOL)iPhone6Plus{
BOOL isiPhone6Plus = NO;
SEL selector = NSSelectorFromString(@"scale");
if ([[UIScreen mainScreen] respondsToSelector:selector]) {
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]];
    [invocation setSelector:selector];
    [invocation setTarget:[UIScreen mainScreen]];
    [invocation invoke];
    float returnValue;
    [invocation getReturnValue:&returnValue];
    if (returnValue == 3.0) {
        isiPhone6Plus = YES;
    }
    NSLog(@"ScaleFactor %1.2f", returnValue);
}
return isiPhone6Plus;

}

Интересной частью этого кода является то, что если я использую NSInvocation, возвращаемое значение селектора шкалы будет равно 3.0. Вызов этого метода непосредственно на iOS 7 возвращает 2.0.

Ответ 10

Все три устройства имеют (в значительной степени) одинаковое количество точек на дюйм. Таким образом, ваши изображения будут автоматически иметь одинаковый физический размер.

Используйте [[UIScreen mainScreen] bounds], чтобы получить общее количество точек на экране. Разделите на 163, чтобы получить приблизительный размер в дюймах, если вы действительно этого хотите.

Обратите внимание, что 6+ не возвращает 1080p, потому что он не отображает буфер 1080p. Он обеспечивает такое, чтобы выход составлял примерно 160 точек на дюйм, используя активы @3x.

Не нужно догадываться.

например. если вы напишете этот код:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 163, 163)];
view.backgroundColor = [UIColor redColor];
[self.view addSubview:view];

Вы получите представление, которое примерно такое же физическое значение - один квадратный дюйм - на всех устройствах iOS.

Apple уже проделала тяжелую работу, поэтому вам не нужно.

Ответ 11

для меня это работает для меня

if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
    UIStoryboard *storyBoard;

    CGSize result = [[UIScreen mainScreen] bounds].size;
    CGFloat scale = [UIScreen mainScreen].scale;
    result = CGSizeMake(result.width * scale, result.height * scale);

    if(result.height == 1136){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_5" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    } else if(result.height == 1334){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    } else if(result.height == 2208){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_6_plus" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    } else if(result.height == 960){
        storyBoard = [UIStoryboard storyboardWithName:@"Main_iPhone_4" bundle:nil];
        UIViewController *initViewController = [storyBoard instantiateInitialViewController];
        [self.window setRootViewController:initViewController];

    }

} else {

    UIStoryboard *storyBoard;

    storyBoard = [UIStoryboard storyboardWithName:@"Main_iPad" bundle:nil];
    UIViewController *initViewController = [storyBoard instantiateInitialViewController];
    [self.window setRootViewController:initViewController];

}

Ответ 12

Вот обновленный исходный код, который вы используете this.

Добавлены модели iPhone 6 и iPhone 6 Plus.

Ответ 13

это гарантировано скомпилировать в xcode 5 (xocde 6 на этом этапе по-прежнему нечеткий, и вы не можете отправить ipa для подключения itunes для утверждения магазина приложения с помощью бета-версии программного обеспечения, которое теперь имеет xcode 6)

вещь xcode 5 не распознает селектор nativeScale.. так вы можете сделать это во время выполнения:

+ (BOOL)isIphone6Plus
{
    SEL selector = NSSelectorFromString(@"nativeScale");
    if ([[UIScreen mainScreen] respondsToSelector:selector]) {
            NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                        [[[UIScreen mainScreen] class] instanceMethodSignatureForSelector:selector]];
            [invocation setSelector:selector];
            [invocation setTarget:[UIScreen mainScreen]];
            [invocation invoke];
            float returnValue;
            [invocation getReturnValue:&returnValue];
            NSLog(@"::: this is native scale %f", returnValue);
            return (returnValue == 3.0f);
    } else {
        // iphone 6 plus come prepackaged with iOS8.. 
        // so if the phone doesn't know what nativeScale means
        // it not an iphone6plus phone
        return NO;
    }
}

Ответ 14

Интересная вещь, которую следует помнить при чтении размеров экрана на моем iPhone 6 Plus, заключалась в том, что когда у вас установлен режим "Zoomed", она будет отображаться как высота iPhone 6 (667), и когда вы установите ее на "Стандарт" будет отображаться как (736). Не имеет значения, но если вы специально хотели узнать тип устройства по какой-либо причине (возможно, Reporting), это может вас обмануть.

См. this.

Ответ 15

Одна из основных причин, по которым вышеприведенные ответы не учитываются, заключается в том, что в iOS7 и ниже, когда вы проверяете [[UIScreen mainScreen] bounds] для границ экрана, она всегда отображает ширину и высоту как то же самое независимо от того, какая ориентация телефона дюйм. Так что если это iPhone5 в ландшафтном режиме, он все равно будет отображать ширину 320 и высоту как 568. В iOS8 это изменилось, теперь, если тот же iPhone5 находится в ландшафте, он отобразит ширину как 568 и высоту, как 320. Ниже приведены методы, которые объясняют это:

+ (BOOL) deviceHasFourInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:568.0];
}

+ (BOOL) deviceHasFourPointSevenInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:2.0 height:667.0];
}

+ (BOOL) deviceHasFivePointFiveInchScreen
{
    return [DeviceType deviceHasScreenWithIdiom:UIUserInterfaceIdiomPhone scale:3.0 height:736.0];
}

+ (BOOL) deviceHasScreenWithIdiom:(UIUserInterfaceIdiom)userInterfaceIdiom scale:(CGFloat)scale height:(CGFloat)height
{
    CGRect mainScreenBounds = [[UIScreen mainScreen] bounds];
    CGFloat mainScreenHeight;

    if ([OperatingSystemVersion operatingSystemVersionLessThan:@"8.0"])
    {
        mainScreenHeight = mainScreenBounds.size.height;
    }
    else
    {
        mainScreenHeight = (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) ? mainScreenBounds.size.width : mainScreenBounds.size.height;
    }

    if ([[UIDevice currentDevice] userInterfaceIdiom] == userInterfaceIdiom && [[UIScreen mainScreen] scale] == scale && mainScreenHeight == height)
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

Также приведены следующие методы класса OperatingSystem:

+ (NSString *) currentOperatingSystemVersion
{
    return [[UIDevice currentDevice] systemVersion];
}
+ (BOOL) operatingSystemVersionLessThanOrEqualTo:(NSString *) operatingSystemVersionToCompare
{
    return ([[self currentOperatingSystemVersion] compare: operatingSystemVersionToCompare options:NSNumericSearch] != NSOrderedDescending);    
}

Ответ 16

Swift 4

if(kSize.width == 320){
             //iphone se
}else if(kSize.width == 375 && kSize.height == 667){
             //iphone 7 / 8
}else if(kSize.width == 375){
            //iphone x
}else if(kSize.width == 414){
           //iphone 7 plus/ 8 plus
}

kSize - экран CGSize

let kSize = UIScreen.main.bounds.size