2015年2月12日木曜日

UI部品の重なる順番を変更する

viewにコード内からaddSubviewすると、新しいUI部品が最前面に配置される。
しかしStoryboardなどで配置したボタンなどは、常に最前面に出ていてほしいもの。

以下のようにすれば、UI部品の重なりを最前面および最背面に変更することができる。
[self.view bringSubviewToFront:_button1];
[self.view sendSubviewToBack:_button1];

それぞれbring〜、send〜と違うので注意。

また、UI部品に対してのメソッドに
[_button1 exchangeSubviewAtIndex:1 withSubviewAtIndex:3];

があり、これも順番を何番目から何番目に変更するというものだが、部品の重なる順番を把握しておく必要があるので、柔軟性は低い。

一番柔軟性のありそうな、「順番を一個前に」、「一個後に」…というメソッドはないようだ。

指定できるのはUIViewのサブクラスなので、ImageViewとかLabelとかほとんどのUI部品が対応している。

2015年2月9日月曜日

デベロッパープログラムの実機証明書更新

XcodeでiPad実機にビルドしようとしたら
「The identity used to sign the executable is no longer valid. 〜〜」
というダイアログが出てビルドできなかった。
要するにiOSデベロッパープログラムの更新期限をまたいだために、実機テストするためのCertificates(証明書)が有効期限切れになったぞというわけだ。
iOSデベロッパープログラムに登録して実機確認始めてもう1年たったのね。早いもんだ。

すでにiOSデベロッパープログラム自体の更新はお金払って済ませてあるので、実機の証明書の更新だけなのだね。めんどくさいがしょうがない。
(ちなみにデベロッパープログラムの年間料金が円安の影響を受けてだろう、8,900円から11,800円に上がりやがった。今回は上る前に更新出来たけど、2,900円も一気に上げるこたぁねぇわな┐(´д`)┌ヤレヤレ)

Xcode6でのやり方。
うまく行かないケースもあるようだけど、XcodeのPreferencesのAccountsを開き…まあ要は↑の画面を出して左下の更新ボタンをポチっとするだけ。

参考:Certificatesの期限が切れたので更新する in Xcode6(上のやり方でうまくいかない場合にキーチェーンアクセス.appから証明書を発行する方法も書かれてる)

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); //frameX座標の最大値
CGFloat x1 = CGRectGetMinX(self.view.frame); //frameX座標の最小値
CGFloat x2 = CGRectGetMidX(self.view.frame); //frameX座標の中間値
これのY座標版もある。

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

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

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)) {

         }

他にも数種類ある。

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