Xcode 4.5 GM にアップグレードしたところ、ストーリーボードのビュー コントローラーに「4" Retina」サイズを適用できるようになりました。
ここで、iPhone 4 と 5 の両方で動作するアプリケーションを作成したい場合、もちろんすべてのウィンドウを 2 回ビルドする必要がありますが、ユーザーが 3.5 インチまたは 4 インチの画面の iPhone を持っているかどうかを検出して、見る。
どうすればいいですか?
Xcode 4.5 GM にアップグレードしたところ、ストーリーボードのビュー コントローラーに「4" Retina」サイズを適用できるようになりました。
ここで、iPhone 4 と 5 の両方で動作するアプリケーションを作成したい場合、もちろんすべてのウィンドウを 2 回ビルドする必要がありますが、ユーザーが 3.5 インチまたは 4 インチの画面の iPhone を持っているかどうかを検出して、見る。
どうすればいいですか?
まず第一に、新しい画面に合わせてすべてのビューを再構築したり、異なる画面サイズに異なるビューを使用したりしないでください。
iOS の自動サイズ変更機能を使用して、ビューを調整し、任意の画面サイズに適応できるようにします。
それはそれほど難しいことではありません。それに関するドキュメントを読んでください。時間を大幅に節約できます。
iOS 6 では、これに関する新機能も提供されています。Apple Developer Web サイトのiOS 6 API 変更ログ
を
必ずお読みください。
そして、iOS 6 の新しいAutoLayout機能を確認してください。
そうは言っても、本当に iPhone 5 を検出する必要がある場合は、単純に画面サイズに頼ることができます。
[ [ UIScreen mainScreen ] bounds ].size.height
iPhone 5 の画面の高さは 568
です。これらすべてを単純化するためにマクロを想像できます。
#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
fabs
H2CO3 のコメントで指摘されているように、浮動小数点を比較するときに、イプシロンでの使用は精度エラーを防ぐためにここにあります。
したがって、これからは標準の if/else ステートメントで使用できます。
if( IS_IPHONE_5 )
{}
else
{}
編集 - より良い検出
一部の人々が述べているように、これはワイドスクリーンのみを検出し、実際の iPhone 5 は検出しません。
iPod touch の次期バージョンにもこのような画面が搭載される可能性があるため、別のマクロ セットを使用する可能性があります。
元のマクロの名前を変更しましょうIS_WIDESCREEN
:
#define IS_WIDESCREEN ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
そして、モデル検出マクロを追加しましょう:
#define IS_IPHONE ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPhone" ] )
#define IS_IPOD ( [ [ [ UIDevice currentDevice ] model ] isEqualToString: @"iPod touch" ] )
このようにして、iPhone モデルとワイドスクリーンがあることを確認しIS_IPHONE_5
、マクロを再定義できます。
#define IS_IPHONE_5 ( IS_IPHONE && IS_WIDESCREEN )
また、@LearnCocos2D で述べられているように、アプリケーションが iPhone 5 画面用に最適化されていない場合 (Default-568h@2x.png 画像がない場合)、このマクロは機能しないことに注意してください。ケース。
最適化されていないアプリで iPhone 5 を検出する理由がわからないため、これが問題になるとは思いません。
重要 - iOS 8 のサポート
iOS 8 では、クラスのbounds
プロパティがデバイスの向きUIScreen
を反映するようになりました。
したがって、明らかに、前のコードはそのままでは機能しません。
これを修正するには、向きによって変化せず、縦向きモードに基づいているため、 のnativeBounds
代わりに新しいプロパティを使用するだけです。
の寸法はピクセル単位で測定されるため、iPhone 5 の場合、高さは 568 ではなく1136になります。bounds
nativeBounds
iOS 7 以下もターゲットにしている場合は、nativeBounds
iOS 8 より前に呼び出すとアプリがクラッシュするため、必ず機能検出を使用してください。
if( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] )
{
/* Detect using nativeBounds - iOS 8 and greater */
}
else
{
/* Detect using bounds - iOS 7 and lower */
}
以前のマクロを次の方法で適応させることができます。
#define IS_WIDESCREEN_IOS7 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )
#define IS_WIDESCREEN_IOS8 ( fabs( ( double )[ [ UIScreen mainScreen ] nativeBounds ].size.height - ( double )1136 ) < DBL_EPSILON )
#define IS_WIDESCREEN ( ( [ [ UIScreen mainScreen ] respondsToSelector: @selector( nativeBounds ) ] ) ? IS_WIDESCREEN_IOS8 : IS_WIDESCREEN_IOS7 )
もちろん、iPhone 6 または 6 Plus を検出する必要がある場合は、対応する画面サイズを使用してください。
SDK と OS の任意の組み合わせに対してテストおよび設計されています。
iPadの種類を追加。iPad 2 および iPad mini は非 Retina iPad です。iPad Mini 2 以降、iPad 3、4、iPad Air、Air 2、Air 3、iPad Pro 9.7 の論理解像度は同じ 1024 です。iPad Pro の maxLength は 1366 です 。
import UIKit
public enum DisplayType {
case unknown
case iphone4
case iphone5
case iphone6
case iphone6plus
case iPadNonRetina
case iPad
case iPadProBig
static let iphone7 = iphone6
static let iphone7plus = iphone6plus
}
public final class Display {
class var width:CGFloat { return UIScreen.main.bounds.size.width }
class var height:CGFloat { return UIScreen.main.bounds.size.height }
class var maxLength:CGFloat { return max(width, height) }
class var minLength:CGFloat { return min(width, height) }
class var zoomed:Bool { return UIScreen.main.nativeScale >= UIScreen.main.scale }
class var retina:Bool { return UIScreen.main.scale >= 2.0 }
class var phone:Bool { return UIDevice.current.userInterfaceIdiom == .phone }
class var pad:Bool { return UIDevice.current.userInterfaceIdiom == .pad }
class var carplay:Bool { return UIDevice.current.userInterfaceIdiom == .carPlay }
class var tv:Bool { return UIDevice.current.userInterfaceIdiom == .tv }
class var typeIsLike:DisplayType {
if phone && maxLength < 568 {
return .iphone4
}
else if phone && maxLength == 568 {
return .iphone5
}
else if phone && maxLength == 667 {
return .iphone6
}
else if phone && maxLength == 736 {
return .iphone6plus
}
else if pad && !retina {
return .iPadNonRetina
}
else if pad && retina && maxLength == 1024 {
return .iPad
}
else if pad && maxLength == 1366 {
return .iPadProBig
}
return .unknown
}
}
実際に見て ください https://gist.github.com/hfossli/bc93d924649de881ee2882457f14e346
注: たとえば、iPhone 6 がズーム モードの場合、UI は iPhone 5 のズームアップ バージョンです。これらの関数はデバイス タイプを決定するのではなく、表示モードを決定するため、この例では iPhone 5 が望ましい結果となります。
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0)
#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)
#define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT))
#define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT))
#define IS_ZOOMED (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
#define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0)
#define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0)
#define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0)
使用法: http://pastie.org/9687735
注: たとえば、iPhone 6 がズーム モードの場合、UI は iPhone 5 のズームアップ バージョンです。これらの関数はデバイス タイプを決定するのではなく、表示モードを決定するため、この例では iPhone 5 が望ましい結果となります。
本当に簡単な解決策
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
// iPhone Classic
}
if(result.height == 568)
{
// iPhone 5
}
}
ここで、iPhone 6 および 6Plus の画面サイズを考慮する必要があります。ここに更新された回答があります
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
//its iPhone. Find out which one?
CGSize result = [[UIScreen mainScreen] bounds].size;
if(result.height == 480)
{
// iPhone Classic
}
else if(result.height == 568)
{
// iPhone 5
}
else if(result.height == 667)
{
// iPhone 6
}
else if(result.height == 736)
{
// iPhone 6 Plus
}
}
else
{
//its iPad
}
役立つ情報
iPhone 6 Plus 736x414 points 2208x1242 pixels 3x scale 1920x1080 physical pixels 401 physical ppi 5.5"
iPhone 6 667x375 points 1334x750 pixels 2x scale 1334x750 physical pixels 326 physical ppi 4.7"
iPhone 5 568x320 points 1136x640 pixels 2x scale 1136x640 physical pixels 326 physical ppi 4.0"
iPhone 4 480x320 points 960x640 pixels 2x scale 960x640 physical pixels 326 physical ppi 3.5"
iPhone 3GS 480x320 points 480x320 pixels 1x scale 480x320 physical pixels 163 physical ppi 3.5"
私は自由にMacmadeのマクロをC関数に入れ、ワイドスクリーンの可用性を検出し、必ずしもiPhone 5を検出するわけではないので、適切な名前を付けました。
プロジェクトにDefault-568h@2x.pngが含まれていない場合、マクロはiPhone5での実行も検出しません。新しいデフォルトの画像がない場合、iPhone 5は通常の480x320の画面サイズ(ポイント単位)を報告します。したがって、チェックはワイドスクリーンの可用性だけでなく、ワイドスクリーンモードが有効になっていることも確認します。
BOOL isWidescreenEnabled()
{
return (BOOL)(fabs((double)[UIScreen mainScreen].bounds.size.height -
(double)568) < DBL_EPSILON);
}
これは私の cocos2d プロジェクトのマクロです。他のアプリでも同じはずです。
#define WIDTH_IPAD 1024
#define WIDTH_IPHONE_5 568
#define WIDTH_IPHONE_4 480
#define HEIGHT_IPAD 768
#define HEIGHT_IPHONE 320
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
//width is height!
#define IS_IPHONE_5 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_5 )
#define IS_IPHONE_4 ( [ [ UIScreen mainScreen ] bounds ].size.height == WIDTH_IPHONE_4 )
#define cp_ph4(__X__, __Y__) ccp(cx_ph4(__X__), cy_ph4(__Y__))
#define cx_ph4(__X__) (IS_IPAD ? (__X__ * WIDTH_IPAD / WIDTH_IPHONE_4) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPHONE_4) : (__X__)))
#define cy_ph4(__Y__) (IS_IPAD ? (__Y__ * HEIGHT_IPAD / HEIGHT_IPHONE) : (__Y__))
#define cp_pad(__X__, __Y__) ccp(cx_pad(__X__), cy_pad(__Y__))
#define cx_pad(__X__) (IS_IPAD ? (__X__) : (IS_IPHONE_5 ? (__X__ * WIDTH_IPHONE_5 / WIDTH_IPAD) : (__X__ * WIDTH_IPHONE_4 / WIDTH_IPAD)))
#define cy_pad(__Y__) (IS_IPAD ? (__Y__) : (__Y__ * HEIGHT_IPHONE / HEIGHT_IPAD))
if ((int)[[UIScreen mainScreen] bounds].size.height == 568)
{
// This is iPhone 5 screen
} else {
// This is iPhone 4 screen
}
Swift では、次のような拡張機能を作成するのが好きな iOS 8+ プロジェクトUIScreen
:
extension UIScreen {
var isPhone4: Bool {
return self.nativeBounds.size.height == 960;
}
var isPhone5: Bool {
return self.nativeBounds.size.height == 1136;
}
var isPhone6: Bool {
return self.nativeBounds.size.height == 1334;
}
var isPhone6Plus: Bool {
return self.nativeBounds.size.height == 2208;
}
}
(注:nativeBounds
ピクセル単位です)。
そして、コードは次のようになります。
if UIScreen.mainScreen().isPhone4 {
// do smth on the smallest screen
}
したがって、コードは、これがデバイス モデルではなく、メイン画面のチェックであることを明確にしています。
Samrat Mazumdarの回答から借りて、デバイスの画面サイズを推定する簡単な方法を次に示します。最新のデバイスで動作しますが、将来のデバイスでは失敗する可能性があります(推測のすべての方法がそうであるように)。また、デバイスがミラーリングされている場合も混乱します(ミラーリングされた画面サイズではなく、デバイスの画面サイズを返します)
#define SCREEN_SIZE_IPHONE_CLASSIC 3.5
#define SCREEN_SIZE_IPHONE_TALL 4.0
#define SCREEN_SIZE_IPAD_CLASSIC 9.7
+ (CGFloat)screenPhysicalSize
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
CGSize result = [[UIScreen mainScreen] bounds].size;
if (result.height < 500)
return SCREEN_SIZE_IPHONE_CLASSIC; // iPhone 4S / 4th Gen iPod Touch or earlier
else
return SCREEN_SIZE_IPHONE_TALL; // iPhone 5
}
else
{
return SCREEN_SIZE_IPAD_CLASSIC; // iPad
}
}
+(BOOL)isDeviceiPhone5
{
BOOL iPhone5 = FALSE;
CGRect screenBounds = [[UIScreen mainScreen] bounds];
if (screenBounds.size.height == 568)
{
// code for 4-inch screen
iPhone5 = TRUE;
}
else
{
iPhone5 = FALSE;
// code for 3.5-inch screen
}
return iPhone5;
}
これは何百回も回答されていますが、このソリューションは私にとって最もうまく機能し、新しいデバイスが導入され、サイズが定義されていないときに問題に対処するのに役立ちました.
Swift 5 ヘルパー:
extension UIScreen {
func phoneSizeInInches() -> CGFloat {
switch (self.nativeBounds.size.height) {
case 960, 480:
return 3.5 //iPhone 4
case 1136:
return 4 //iPhone 5
case 1334:
return 4.7 //iPhone 6
case 2208:
return 5.5 //iPhone 6 Plus
case 2436:
return 5.8 //iPhone X
case 1792:
return 6.1 //iPhone XR
case 2688:
return 6.5 //iPhone XS Max
default:
let scale = self.scale
let ppi = scale * 163
let width = self.bounds.size.width * scale
let height = self.bounds.size.height * scale
let horizontal = width / ppi, vertical = height / ppi
let diagonal = sqrt(pow(horizontal, 2) + pow(vertical, 2))
return diagonal
}
}
}
これは、「5.5 インチ」や「4.7 インチ」などのデバイスのインチ サイズを覚えるのは簡単ですが、正確なピクセル サイズを覚えるのは難しいためです。
if UIScreen.main.phoneSizeInInches() == 4 {
//do something with only 4 inch iPhones
}
これにより、次のようなことを行う機会も得られます。
if UIScreen.main.phoneSizeInInches() < 5.5 {
//do something on all iPhones smaller than the plus
}
デフォルト:画面サイズとスケールを使用して対角インチを計算しようとします。これは、新しいデバイス サイズが表示された場合に備えて、最後の例のようなコードを決定するために最善を尽くします。
このマクロがデバイスとシミュレータで動作するのであれば良いと思います。以下に解決策を示します。
#define IS_WIDESCREEN (fabs((double)[[UIScreen mainScreen]bounds].size.height - (double)568) < DBL_EPSILON)
#define IS_IPHONE (([[[UIDevice currentDevice] model] isEqualToString:@"iPhone"]) || ([[[UIDevice currentDevice] model] isEqualToString: @"iPhone Simulator"]))
#define IS_IPOD ([[[UIDevice currentDevice]model] isEqualToString:@"iPod touch"])
#define IS_IPHONE_5 ((IS_IPHONE || IS_IPOD) && IS_WIDESCREEN)
サイズに依存することは、非常に多くのレベルで間違っています。システムに聞いてみませんか?
- (NSString *) getDeviceModel
{
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
ハードウェアの種類を検出する最良の方法、iPhone4 または iPhone5? から取得 、edzio27回答。
CGFloat height = [UIScreen mainScreen].bounds.size.height;
NSLog(@"screen soze is %f",height);
if (height>550) {
// 4" screen-do some thing
}
else if (height<500) {
// 3.5 " screen- do some thing
}
このようにして、デバイス ファミリを検出できます。
#import <sys/utsname.h>
NSString* deviceName()
{
struct utsname systemInformation;
uname(&systemInformation);
NSString *result = [NSString stringWithCString:systemInformation.machine
encoding:NSUTF8StringEncoding];
return result;
}
#define isIPhone5 [deviceName() rangeOfString:@"iPhone5,"].location != NSNotFound
#define isIPhone5S [deviceName() rangeOfString:@"iPhone6,"].location != NSNotFound
「新しいSwiftファイル」を追加->AppDelegateEx.swift
に拡張子を追加するAppDelegate
import UIKit
extension AppDelegate {
class func isIPhone5 () -> Bool{
return max(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) == 568.0
}
class func isIPhone6 () -> Bool {
return max(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) == 667.0
}
class func isIPhone6Plus () -> Bool {
return max(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) == 736.0
}
}
利用方法:
if AppDelegate.isIPhone5() {
collectionViewTopConstraint.constant = 2
}else if AppDelegate.isIPhone6() {
collectionViewTopConstraint.constant = 20
}
これは、向きに依存しない、デバイスの正しいテストです。
- (BOOL)isIPhone5
{
CGSize size = [[UIScreen mainScreen] bounds].size;
if (MIN(size.width,size.height) == 320 && MAX(size.width,size.height == 568)) {
return YES;
}
return NO;
}
次のコードを使用します。
CGFloat screenScale = [[UIScreen mainScreen] scale];
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale, screenBounds.size.height * screenScale);
if (screenSize.height==1136.000000)
{
// Here iPhone 5 View
// Eg: Nextview~iPhone5.Xib
} else {
// Previous Phones
// Eg : Nextview.xib
}
すべてのバージョンの iPhone および iPad デバイスを検出するために使用されます。
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
#define IS_IPHONE_5 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 568.0)
#define IS_IPHONE_6 (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 667.0)
#define IS_IPHONE_6_PLUS (IS_IPHONE && [[UIScreen mainScreen] bounds].size.height == 736.0)
#define IS_RETINA ([[UIScreen mainScreen] scale] == 2.0)