web-dev-qa-db-ja.com

どのようにしてUI_USER_INTERFACE_IDIOM()を取得してiPhone OS SDK <3.2で動作させることができますか

Appleは、次のコードを使用して、iPadまたはiPhone/iPod Touchで実行されているかどうかを検出することをお勧めします。

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
  // The device is an iPad running iPhone 3.2 or later.
  // [for example, load appropriate iPad nib file]
}
else {
  // The device is an iPhone or iPod touch.
  // [for example, load appropriate iPhone nib file]
}

問題は、UI_USER_INTERFACE_IDIOM()およびUIUserInterfaceIdiomPadが3.2より前のSDKで定義されていないことです。これはそのような機能の目的を完全に無効にするようです。これらは、コンパイルしてiPhone OS 3.2でのみ実行できます(iPhone OS 3.2はiPadでのみ実行できます)。したがって、UI_USER_INTERFACE_IDIOM()を使用できる場合、結果は常にiPadを示すことになります。

IPhoneにバインドされたユニバーサルアプリのコードをテストするためにこのコードとターゲットOS 3.1.3(最新のiPhone/iPod Touch OS)を含めると、シンボルが3.1.3以前で定義されていないため、コンパイラエラーが発生します。 、iPhoneシミュレータ3.1.3用にコンパイルする場合。

これがランタイムデバイス検出へのApple推奨のアプローチである場合、何が問題ですか?この方法でデバイスを検出することに成功した人はいますか?

32
drootang

コードを3.1.3と3.2の両方でコンパイルするためにこれを行います。

BOOL iPad = NO;
#ifdef UI_USER_INTERFACE_IDIOM
iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#endif
if (iPad) {
// iPad specific code here
} else {
// iPhone/iPod specific code here
}

私もここで簡単なブログ投稿を書きました: http://www.programbles.com/2010/04/03/compiling-conditional-code-in-universal-iphone-ipad-applications/

24
Sangraal

これは私が使用するものです:

- (BOOL) amIAnIPad {
    #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)
        if ([[UIDevice currentDevice] respondsToSelector: @selector(userInterfaceIdiom)])
            return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
    #endif
    return NO;
}

これは条件付きでコンパイルされるため、3.0 sim用にビルドできます。次に、UIDeviceクラスがセレクターに応答するかどうかを確認します。これらのいずれかが失敗した場合、それはiPadではありません。

14
Ben Gottlieb

これがruntimeデバイス検出へのApple推奨のアプローチである場合、何が間違っていますか?この方法でデバイスを検出することに成功した人はいますか?

これはruntime検出のソリューションです:

#define isIPhone (![[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] || [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)

その後、コード内の任意の場所で簡単にテストできます。

if (isIPhone) { ... }

これと#if/#ifdefの使用の違いは、これはランタイムテストであるのに対し、#ifはコンパイル時テストです。

この場合、どのOSバージョンでも正確なものを使用できるので、ランタイムテストの方が良いと思います。コンパイル時チェックを使用する場合は、OSバージョンごとに異なる実行可能ファイルを作成する必要があります。

問題がコンパイル時のエラーである場合は、SDKの最新バージョンに対してコンパイルする必要があります( iOSで弱リンクフレームワークにアクセスする方法 も参照)。

7
Mike Keskinov

私が使用するコンパイラベースのものの代わりに:

- (BOOL)deviceIsAnIPad {
if ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)])
    //We can test if it's an iPad. Running iOS3.2+
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
        return YES; //is an iPad
    else 
        return NO; //is an iPhone
else 
    return NO; //does not respond to selector, therefore must be < iOS3.2, therefore is an iPhone
}
5
MattyG

答えは、iPhoneでコードを実行しないでくださいsimulator 3.1.3以前。常に3.2 SDKでコンパイルします。 iPhoneシミュレーター3.2を使用すると、iPadシミュレーターを入手できます。または、iPhoneデバイス3.2用にコンパイルして、アプリを電話に置いてテストします。

3.2 SDKに対してコンパイルして3.1.3以前のシミュレータを使用する方法はありません。

5
drootang

これを使用して宣言する

#ifdef UI_USER_INTERFACE_IDIOM
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
#else
#define IS_IPAD false
#endif

次に、以下のようにチェックを使用します

#define DetailLabel_PosX (IS_IPAD ? 200 : 160)

Iphone 5をチェックするための定義もあります

#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)
#define IOS_OLDER_THAN_6 ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0 )
#define IOS_NEWER_OR_EQUAL_TO_6 ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0 )
2
sinh99

UI_USER_INTERFACE_IDIOM()およびUIUserInterfaceIdiomPadはiOS3.2以降で使用できます。重要な部分は「上向き」です。承知しました。 iOS3.2はiPad専用ですが、iOS4.0以降はiPhoneとiPadの両方で動作するため、このチェックは思ったほど無意味ではありません。

0
occulus

これはそのような機能の目的を完全に無効にするようです。これらは、コンパイルしてiPhone OS 3.2でのみ実行できます(iPhone OS 3.2はiPadでのみ実行できます)。したがって、UI_USER_INTERFACE_IDIOM()を使用できる場合、結果は常にiPadを示すことになります。

これは完全に間違っています。 3.2のベースSDKではcompiledにすることができますが、デプロイメントターゲットを適切に設定すれば、どのOSでもrunにすることができます。

0
user102008