2015年2月6日金曜日

SizeClassesの基本

SizeClassesは簡単に言えば、解像度や縦横比がいろいろ違うiPhone、iPadなどのデバイスの画面レイアウトを、一つのStoryboardで扱えるようにしようというもの。
Xcode6から導入された…んだよな、たしか?

WYSIWYGだったそれまでのStoryboardと違い、iOSのプレビュー画面を見ながらレイアウトしていく必要があり、ちょっととっつきにくいと思う。
(ちなみにプレビュー表示は確実じゃないこともあるようなので、最後はちゃんとシミュレーターか実機で確認した方がいい)
Xcodeのプレビュー画面表示(右側)


AutoLayoutは併用必須なので、そっちは覚えること。

んで基本は、
「全部の画面サイズで“一応表示できる”ものを作って、その後細かな画面サイズ向けに直す」
ということ。
「iPhoneでは画面が狭いから表示できないボタンを、iPadでだけ表示させる」なんてこともできるし、ポートレイト表示とランドスケープ表示で大きくレイアウトを変えるなんてこともできる。

画面下の表示が「wAny hAny」になってれば、全部のデバイス向けのレイアウト画面。
「Base Values、For all layouts」と書いてあるとおり、ここで全デバイス共通のレイアウトをする。
どう考えても縦長(ポートレイト表示)か横長(ランドスケープ表示)のiOSデバイスであるが、前述のとおりなぜかレイアウト画面は正方形。イラっとするけど我慢。
(追記:レイアウト画面をそれぞれのデバイスの大きさにする方法がわかった! 一番最後に書いたよ)
この「wAny hAny」の画面がすべての基本になるので、ここに配置したUI部品が全てのSizeClassに表示される。


とりあえずレイアウトができたら(AutoLayoutはそんな簡単じゃないんだけどさ)、今度は下のwAny hAnyの部分をクリックして出た水色の四角を以下のようにwCompact hAnyとかにする。(ポートレイト表示の場合)
今度はiPhoneっぽい縦長の画面になる。
ここにもやはりBase Values、そして3.5-inch, 4-inchi and 4.7-inch iPhonesとかなんとか書いてあるとおり、iPhoneできれいに表示されるように調整する。
ここで調整したレイアウトは、この画面に対応したSizeClass(3.5〜4.7インチのiPhone)でのみ有効になり、他のSizeClass(iPadやAppleWatchなど)には影響がないし、「wAny hAny」画面に戻れば「wAny hAny」画面は変更されていないのがわかる。
縦長のくせにランドスケープ表示も対応してるらしいのがよくわかんないけど、さらっと無視。


同様にiPad用にwAny hRegularとか、Base ValuesになってるSizeClassで、望んだレイアウトで表示されるように調整する。


wAny hRegularだとiPhoneのポートレイトとiPadのポートレイト、ランドスケープ全てに共通するSizeClassのようなので、iPhoneとiPadで完全に分けるなら、iPadは直接Final Valuesと書かれたwRegular hRegularでやっちゃったほうがいいのかもしんない。


レイアウト画面ごとのconstraintsの設定は、constraintsを選んだ状態で画面右のここ↓でも確認、変更することができる。
Constantの値54がwAny hAnyで設定した共通の値。それをwCompact hAnyでは0にしてるということね。
一番下にあるwC hAny ✔️InstalledはwCompact hAnyの設定でこの値が有効になってるということ。
その上の何も書いてないとこのInstalledのチェックが外れてるのは、wAny hAnyの画面で有効にしてないっつーことですな。wAny hAny画面に戻ってもさっきのConstantの54が適用されてないよと。(別のやり方でAutoLayoutを設定してるんでこうなってる)


Labelなどのフォントサイズは、インスペクタのFont横の「+」を押すことでRegularとかAnyとかの情報を追加できるので、SizeClassごとに変更することができる。
最初できないのかと思ってコード中で変えてたんだけど、やっぱりできたんだ。


まあだいたいこんなところ。
基本(Base)画面で設定して、デバイスと画面の向き(ポートレイトかランドスケープか)別に変更が必要なところだけ最終(Final)画面で調整するってわけだ。

iPadはいいけど、画面縦横比がそれぞれ異なるiPhoneでのレイアウト画面がざっくりとしか分かれてないのが気になる。
iPhone 4sとiPhone 6Plusで変更したい場合とかどうするのかな? 何か方法があるかもしれないので、各自調べること。まだわかんないことも多いし。

レイアウト画面を各デバイスの縦横比で表示する方法

ViewControllerを選んでからAttribute InspectorのSimulated MetricsのSize、Orientationを変更すればいい。
SizeClassのwAny hAnyだけでうまく表示されるように作ってない場合は、当然SizeClassも変更してやればいい。
これでいちいちプレビューを表示しなくても良くなる。
まあプレビューはプレビューで複数の画面サイズを一度に確認できるから便利だけどね。

それにしてもこんなんよほど調べなきゃわからんよなあ。英語の解説には書いてあるのかもしれないけど。

2015年2月5日木曜日

iAdの超簡単な表示方法

iOS7からiAdの単純な表示が簡単になっている。


iAdのFrameworkをインストールさせ、

#import <iAd/iAd.h>
importした上で、

self.canDisplayBannerAds = YES;
とするだけで画面下部にiAdバナー広告が勝手に表示されてくれる。

Delegateによって広告表示成功時、失敗時の処理をさせたり、AdMobなど他の広告と切り替えたりするには、以下のような従来からの方法が必要だろう。

まずはDelegateを使うための手続きを書くのをお忘れなく。
@interface ViewController : UIViewController <ADBannerViewDelegate>


StoryboardのiAd Banner ViewからのOutletを作り、それのdelegateプロパティに対してselfを指定してやることも。iAdBanner.delegate = self


#pragma mark -
#pragma mark iAd関連delegate
//iAd広告が表示に成功した場合
- (void)bannerViewDidLoadAd:(ADBannerView *)banner
{
    NSLog(@"iAd表示成功");
    _iAdView.hidden = NO; //iAd表示
    adMobBanner.hidden = YES; //AdMob非表示
}

//iAdの表示に失敗したらAdMobを表示
- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
    NSLog(@"iAd表示不可 %@\nAdMob表示",[error localizedDescription]);
    _iAdView.hidden = YES; //iAd非表示
    adMobBanner.hidden = NO; //AdMob表示
}

2015年2月4日水曜日

Rectの最大、最小、中間の位置などを得る

Objective-CでもSwiftでもほぼ一緒。

UIViewの左端とか右端とか真ん中とかに何かを表示させる…などの時に便利な関数
CGFloat x0 = CGRectGetMaxX(self.view.frame); //frameのX座標の最大値
CGFloat x1 = CGRectGetMinX(self.view.frame); //frameのX座標の最小値
CGFloat x2 = CGRectGetMidX(self.view.frame); //frameのX座標の中間値
これのY座標版もある。

Width、Height版
CGFloat x3 = CGRectGetWidth(self.view.frame); //frameのWidth

CGFloat x4 = CGRectGetHeight(self.view.frame); //frameのHeight

2015年2月3日火曜日

当たり判定検出

UIどうしが重なっているかどうかの当たり判定の方法。
返り値は全てBOOL。

xxxxx.frameの中にimageViewのcenterがあるか否か
if (CGRectContainsPoint(xxxxx.frame, imageView.center)) {

         }

xxxxx.frameの中にimageViewのframeが含まれているか否か
if (CGRectContainsRect(xxxxx.frame, imageView.frame)) {

         }

xxxxx.frameとimageViewが一部でも重なっているか否か
if (CGRectIntersectsRect(xxxxx.frame, imageView.frame)) {

         }

他にも数種類ある。

参考:ふぁのれこそは半角カタカナで

2015年1月30日金曜日

iPhoneかiPadかの判定

UIUserInterfaceIdiomPhoneがiPhoneを、UIUserInterfaceIdiomPadがiPadを示す。
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone) {
        //iPhoneの時の処理;

    }


[UIDevice currentDevice].userInterfaceIdiomはUI_USER_INTERFACE_IDIOM()でも置き換えられる。こっちのほうが簡単だわな。


BOOL isPad = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    isPad = YES;
} else {
    isPad = NO;
}

NSLog(@"iPad? :%@",isPad == YES ? @"Pad" : @"Phone");

2015年1月19日月曜日

UIWebViewの画面をクリアする

UIWebViewで、画面移動時などに前に表示していたサイトが見えていると、見栄えが良くない。
あらかじめNSURLの値に@"about:blank"を入れてやるとWebViewの画面がクリアされて白くなってくれる。

[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];
[_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.hogehoge.jp"]]];

2015年1月7日水曜日

シミュレータでソフトウェアキーボードが出なくなったら

デバッグ中に何をやったかしらないが、シミュレータでUITextFieldとかをタップしてソフトウェアキーボードを出そうとしても、出なくなり(Macのキーボードから直接値は入力できる)

2015-01-07 23:48:31.018 SkyReporter[40746:1649582] Can't find keyplane that supports type 4 for keyboard iPhone-Portrait-NumberPad; using 3876877096_Portrait_iPhone-Simple-Pad_Default

上記のようなメッセージが表示されてしまった。
調べたところ、何かのはずみでiOSシミュレータの設定が切り替わってしまったようで、
iOSシミュレータのメニューの
Hardware/Keyboard/Connect Hardware Keyboardのチェックを外してやれば、ソフトウェアキーボードが再び表示されるようになる。

ただし、なぜかメッセージは消えてくれないようだ。
消えなくてもiOSシミュレータだけの問題のようなので、そのままAppStoreの審査を通った人がいるようなので、気持ち悪いけど気にしなくていいようだ。

参考: