投稿

2012の投稿を表示しています

iOS6 deprecated

iOS6より画面切り替え系のメソッドでdeprecatedになったものがあります。

- (void)dismissModalViewControllerAnimated:(BOOL)animated
- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
です。以下のものに置き換えます。
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion

supportedInterfaceOrientations

iOS6から画面の回転に関する処理が変わりました。
ViewControllerに2つのメソッド、
(BOOL)shouldAutorotate
(NSUInteger)supportedInterfaceOrientations
を追加します。
これらのメソッドの大まかな説明は省きます。

この(NSUInteger)supportedInterfaceOrientationsの戻り値ですが、
UIInterfaceOrientationMaskPortraitのような
〜Mask〜
というものを指定します。
これは各ビットがそれぞれの方向に対応しており、どの方向に対応するかを一つの変数で表せます。
Portrait基本形のみ対応する場合でもUIInterfaceOrientationMaskPortraitというMask付きのものを指定します。単一指定ならMaskがついてなくても値は同じだろうと早とちりしてしまいUIInterfaceOrientationPortrait(Maskが付かないやつ)を指定してしまうと、
Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES
という実行時エラーが出ます。

定義を調べると以下のようになっています。
typedefが少し独特ですが、どこかで#defineされているんでしょう。

typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
UIDeviceOrientationUnknown,
UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom
UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top
UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right
UI…

AudioUnit細かいことまとめ

AudioUnitに出てくる細かいことについて


void *
int *と同じようにポインタですが、int *との違いはポインタの指す先です。int *の場合はintですが、void *の場合はどのような型でもよいです。使用するときには状況に応じてキャストすることもある。



関数ポインタ
関数ポインタは検索すると説明しているページがたくさん出てきます。関数へのポインタなのですが、AudioUnitでは関数の引数として関数を渡すときに使います。
関数ポインタの中でもtypedefを使った宣言の理解が難しい。
普通のtypedefは
typedef int abc;
で「abcをintとして扱う」「abcにintと同じ役割を与える」というような意味になります。「何を」と「何として」がスペースを挟んで書かれています。
関数ポインタのtypedefは
typedef int (*abcd)(int a,int b);
というようになります。
これに対し、同じように「何を」と「何として」をスペースを挟んで解釈しようとすると混乱します。
関数ポインタの場合は
「何を」abcd
「何として」int (*)(int a,int b) 引数をintで2つ持つ、戻り値がintの関数のポインタ
という変則的な読み方をします。



AudioUnitSampleTypeとAudioSampleType
iOS5.xだと実機でもシミュレータでもIntのほうが定義されています。
/*!
@typedef AudioSampleType
@abstract The canonical audio sample type used by the various CoreAudio APIs
*/
#if !CA_PREFER_FIXED_POINT
typedef Float32 AudioSampleType;
typedef Float32 AudioUnitSampleType;
#else
typedef SInt16 AudioSampleType;
typedef SInt32 AudioUnitSampleType;
#define kAudioUnitSampleFractionBits 24
#endif

ちなみにCA_PREF…

finished running

Xcode4.2で新規プロジェクトを作り、iPod touch 3rd 8G(iPhone 3Gに相当)でiOS3.1.3の実機で動かそうとすると、すぐに起動が終わってしまい
finished running 〇〇
というのがXcodeに表示される。
原因はiPod touch 3rd 8GのCPUがarmv6であるため。
対応は
〇〇info.plistでrequired device capavilitiesのarmv7を削除するのとBuildSettingのArchitecturesをarmv6を追加すること。
下記参照。〇〇info.plistの方は見落としがちなので注意。
stackoverflow.com

タッチイベント動作の名前

ボタンなどのUI部品へのタッチ動作をメソッドに結びつける際、どのタッチ動作かを指定します。タッチしたとか指を離したとかドラッグしたとか。
この動作の中に
TouchDragEnter
TouchDragExit
TouchDragInside
TouchDragOutside
の4つがありますが、TouchDragEnterとTouchDragInside、TouchDragExitとTouchDragOutsideの違いがわかりませんでした。

調べてみると
TouchDragEnter ドラッグで部品外の領域から中に入ってきた(ただしTouchDownは部品内で行われ、一度外に出てから入ってきた場合)
TouchDragExit ドラッグで部品内の領域から外に出た
TouchDragInside 部品内の領域でドラッグ
TouchDragOutside 部品外の領域でドラッグ(ただしTouchDownは部品内で行われ、外に出た場合)
とのことでした。
注意点としてはEnterとOutsideは、これらのイベントをトリガーにしてメソッドを呼び出したい時、Downは部品内に行われてタッチイベント監視権のようなものを部品が持つ必要があるようです。

const char *argv[]

iOSプログラミングでmain関数ってあまりじっくり見る機会がないんだけどよく見ると
const char *argv[]
っていう引数が結構難解。
文法通りの結果になるような私なりの解釈を書いてみる。これは人によって違いがあると思う。

まずchar *argv[]の解釈だが、そのまえにポインタと配列の宣言の分析をする。
int *abc;
これは、*をつけてアクセスしたものはint型(つまりintへのポインタ)で、名前はabcというものを宣言。
int abc[];
これは各要素はintである配列で、名前はabcというものを宣言。

これをふまえてchar *argv[]を考えると
*よりも[]のほうが優先順位が高いのでこの順番で解釈し、
ある配列がある。その各要素は*をつけてアクセスするとcharになるもで、その名前(配列の名前)はargv。と解釈し、argv[]はchar型へのポインタの配列で、argvと配列名だけで使用するとその先頭要素を指す。配列の要素のargv[0]はchar型へのポインタ。

また優先順位を意図的に変えたchar (*argv)[]だと、こちらのページが詳しく書いてある。
今こそ再考察! C言語ポインタ徹底解説
「配列へのポインタ」と「2次元配列(配列の配列)」の関係
http://news.mynavi.jp/articles/2008/04/18/pointer/003.html
4ページあるうちの4ページ目です。1ページ目から内容が良いので読むことをおすすめします。
この(*argv)の部分だが「配列の名前が先頭要素へのポインタだから、さらにそれを指すポインタ」と解釈したら間違いらしい。argvはポインタだが指す先は配列の先頭要素。だとすると、*をつけたときとつけないときで何が違うか、というのを疑問に思うが、それも上のページに詳しく書いてある。*をつけるとポインタ加算命令に対して配列ひとつ分進むらしい。なので宣言時に配列の要素数は必須。上のchar (*argv)[]はXcodeのコンパイラだとポインタ演算のところでエラー。
ちなみに配列の名前はポインタと近いが微妙な違いがある。

char *argv[]の間違った解釈としては
char型の配列があってその先頭要素を指すポインタをさらに指したポインタがargv。
という解釈がある。初め…

用語

Targeted Device Family
iPadアプリか、iPhone/iPod touchアプリか、両方か

Project名
.projectファイルの名前

Product name
一体何か?

Bundle name
実行ファイルのトップのフォルダに付けられる名前

Executable name
実行ファイル名?

Target名
ターゲットの名前

Schime名
スキームの名前

iPhone Core Audioプログラミング

iPhone Core Audioプログラミングという本の感想。

iOSで音を出すやりかたは4パターンほどあります。それぞれ、作りやすさ、機能、理解しやすさなどが違います。全部を網羅しようとすると結構大変なのですが日本語で書かれたiPhone Core Audioプログラミングという良書がありますので助かります。
最初本屋でぱらぱらと見た感じではかなり難しそうな印象があります。特にC言語による部分はObjective-Cに慣れた目には完全に別言語に見えます。
しかし、何度も読んでいくうちにだんだんとCore Audioのパターンが見えてきます。その山を超えるとわりと楽に読めるようになります。

chapter 1 System Sound Service
効果音用のAPIの説明。初めのchapterにしては結構いろんなことが詰め込んである。読むペースをつかむ前に次から次へと話題が変わるので注意。コールバックというのが理解できない場合はchapter 2 AVFoundationを検討するのもいいと思います。

chapter 2 AVFoundation
音を出すAPIの中でこのAPIが一番わかりやすい。ARCならreleaseも必要なし。

chapter 3
項目が多いがひとつひとつは単純な知識。
オーディオフォーマットの情報とパケットの情報を混乱しないようにする。
iOSアプリからプログラムを始めた人は、取得したいデータのアドレスを関数の引数として渡すやり方がイメージしにくいかもしれない。このやり方はCoreAudioではすごくよく使う。

chapter 4 AudioSessionの基礎
ここはどんなアプリを作る場合でも目を通しておいたほうがよいでしょう。
ユーザーの使用状況に応じて音の出力の挙動を変化させること方法が書いてあります。
内容は主に2つ、カテゴリ(アプリは音の扱いをどうするか、マナーモード?に従うとか)の設定と割り込み(電話受信など)への対応。
この割り込みへの対応に2つのやり方が紹介されている。一つは直接AudioSessionを扱うやり方、もうひとつはAVAudioPlayerの機能を使うやり方。
AVAudioPlayerはサウンドの扱いを簡単にするために割と後から出来たもの。ソースから想像するにAVAudioPlayerの中にAudioSe…

clearsContextBeforeDrawing

これはdrawRect実行前に領域を塗り潰すかどうかのパラメータですが、調べれば調べるほど他にもいろいろな設定項目が出てくる、代表的な芋づるパラメータです。
他に出てくるパラーメタはopaque(不透明)とbackgroundColorの2つで、 clearsContextBeforeDrawingが2通り opaqueが2通り backgroundColorがnil、transparent(alphaが1未満)、opaque(alphaが1)の3通りありますので 合計12パターンの設定があります。
ややこしいですが、各パラメータの説明のまえに王道をいうと 何かの色で塗りつぶすなら、backgroundColorにベース色を指定します。 透明にしたいならview.backgroundColor = [UIColor clearColor]に指定します。 ただしパフォーマンスを上げたい場合や、仕組みが気になる場合は、各パラメータの意味を理解して対応することになります。 drawRectメソッドの内で領域をすべて塗る場合には効果があります。[UIColor clearColor]は色値とアルファ値が全部0.0のUIColorインスタンス。いわゆる透明な黒というやつである。

詳しく見ていくと
backgroundColorが指定され、alphaが1.0の時
その色で塗る
opaqueとclearsContextBeforeDrawingの設定による違いはない その色で塗られているので下の画像が塗られているかと前もって領域が透明な黒でクリアされているかは見た目ではわからないがリファレンスによるとクリアされているようだ。

backgroundColorが指定され、alphaが0.0<=alpha<1.0の時
その色を塗りながら下の画像を表示
opaqueとclearsContextBeforeDrawingの設定による違いはない 下の画像が塗られているのでopaqueの設定が無視されるようだ 前もって領域が透明な黒でクリアされているかは見た目からはわからないがこれもリファレンスによるとクリアされているようだ。
上で出した[UIColor clearColor]の場合、全部0.0であろうと指定されているということで、その色(というかデータ)で塗るようで…

storyboard細かいことまとめ

自分が作成するアプリの中でわかった細かいこと

segueをソースコードから実行することが出来ます。そのためのsegueをあらかじめstoryboardで作成しておくのですが、viewからはSegueが引けない。ViewControllerからは引ける。ViewControllerから引くやり方はステータスバーからcontrol + ドラッグ。あるいはfile's owner立方体アイコンからドラッグ。

segueの強制実行は
[self performSegueWithIdentifier:@"segueの名前" sender:self];
で出来ます。

segue実行時に新しいViewControllerに値を渡したいときは、実行時に走るメソッドの
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ }
をオーバーライドします。その中で
SecondViewController *secondViewController=(SecondViewController *)[segue destinationViewController];
secondViewController.*** = ***;
のようにすればよい
ただしpushとmodalの違いがあるようである。
上に書いてあるのはmodalでの仕様。pushはまだよくわからない。

また、新しいViewControllerのviewにUIKit部品を置いてある(storyboardで作成してある)場合、UIKitがインスタンス化されるタイミングに気を付ける必要がある。
prepareForSegueの中では、新しいViewControllerにあるインスタンスは生成されているが、UIKit部品はnil状態なのでアクセスできない。
”おそらく”実行の順番は
1 performSegueWithIdentifier開始
2 新しいViewControllerのインスタンス化(initなど)
3 prepareForSegue開始
4 prepareForSegue終了
5 UIKitのインスタンス化、画面回転メソッドの呼び出し、viewDidLoadなど
6 performSegueWithIdentifier終了
もしビューコントロー…

Xcode4でのアプリの多言語化

多言語化に関するメモ

多言語化の概要
iOSアプリのローカライズは、ファイル単位で行う。この項目をローカライズしたい時はこのファイル、あの項目をローカライズしたい時はあのファイル、というようにローカライズしたい項目に該当するファイルを多言語化させる。
ファイルをローカライズさせると、言語数の分だけ同じ内容のファイルが出来ます。後は各言語毎にファイルを編集します。
はじめにデフォルトを1つ作って(だいたいの場合は英語)それを複製し、それぞれの言語に対応させることがほとんどかと思います。
ローカライズされたファイルはそれぞれの言語フォルダの中に入れられます。

ソースが置いてあるところ/en.lproj/Localizable.strings
ソースが置いてあるところ/ja.lproj/Localizable.strings

注意点
ファイルのローカライズ状態には、どうも
1,ローカライズされてない
2,ローカライズされているが、en(英語)のみに対応している
3,ローカライズされていて、複数の言語に対応している
の3パターンあるようです。1と2の違いに気づきにくい。1から2への変更の場合、何か操作して何も反応がないように見える場合がよくあります。

具体的なやり方
ローカライズしたいファイルを選択し、ファイルインスペクタ(XCodeの右のほうにあるやつ)でLocalizationを行います。
ローカライズすることが多いであろうファイルは
storyboardIcon.pngInfoPlist.strings
アイコンの下に表示するアプリ名Localizable.strings
ソースコード内のNSStringインスタンス
など。
プロジェクトの設定のLocalizationsより言語を追加すると一気に複数のファイルを多言語化します。
すると、iPhone用、iPad用それぞれのstoryboard、それからInfoPlist.strings、Icon.pngなど多言語化されます。なにが多言語化されるかはそのときの構成によって違うようです。多言語化出来るものが見つかればそれを多言語化するような感じです。

Xcode4.2でプロジェクトの設定のLocalizationsで多言語化するものは
storyboard
icon
InfoPlist.strings(デフォルトで存在していてLocalizationsされているがen…

FindSpeed申請

FindSpeedを申請した。
日本名が「速度の計算」。
小学校の算数で習う、速度、時間、距離の問題を出すアプリ。
3つのうち2つが与えられて残りの1つを計算で求める。
車が走るアニメーションが問題を解くヒントになる。

Default.pngとスクリーンショット

Default.png

iPhone
ステータスバー領域含む
縦のみ
横320 たて480
横640 たて920 ratinaは@2xを付ける
縦長iPhoneの568対応は横640 たて1136 Default-568h@2x.png

iPad
iOS6まではステータスバー含めない。名前決まっている。(「含める」に変更になった? 2014/3)
横748 たて1024
横1004 たて768
iOS7からはステータスバー領域を含むようになった。名前はなんでもいい。

スクリーンショット

ステータスバーは含めても含めなくても可。含めないときは-20px(ratinaは-40)のものを用意する
縦横どちらでも可
各言語毎に設定する

iPhone iPad両対応ユニバーサルアプリ

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad

} else {
// iPhone or iPod touch(iPhone OS バージョン3.2以上)

}
#else
// iPhone or iPod touch(iPhone OS バージョン3.2未満)

#endif

CGContextDrawPathに与えるパラメータについて

イメージ
CGContextDrawPathに与える2つめの引数について調べました。
2つの角丸四角形のパスを書いてからCGContextDrawPathを実行してます。

名前に出てくるEOというのはEven-Oddの略です。Even-Oddというのは偶数・奇数のことです。重なった部分はいくつのパスが囲っているかを調べ、奇数の時は塗る、偶数の時は塗りません。

kCGPathFill
内部を塗ります。



kCGPathStroke
輪郭を書きます。



kCGPathFillStroke
内部を塗って、輪郭を書きます。



kCGPathEOFill
内部を塗るが重なった所は奇数遇数ルールに従う。



kCGPathEOFillStroke
内部を塗って、輪郭を書くが、重なった所は輪郭は書いて内部は奇数遇数ルールに従う。

(追記)
SwiftではCGPathDrawingModeになりました。

UIFontのretainCount

[[UIFontsystemFontOfSize:50] retainCount]が1をすっとばして2になる。
誰かが初めの1をしている。

状況を勝手にイメージすると
UIFontクラス内ですでに全てのサイズごとのインスタンスが用意されていて、それらはすでにretainCountが1。で、自作ソース内で使おうとすると、インスタンスを生成するのではなくてすでにあるものへの参照が渡され、retainCountを+1すると2になるような感じ。
あくまで勝手なイメージなので実際はこれとは誤差があると思います。

調べます。

調査プログラム
NSLog(@"%d",[[UIFontsystemFontOfSize:50] retainCount]); NSLog(@"%d",[[UIFontsystemFontOfSize:50] retainCount]); NSLog(@"%d",[[UIFontsystemFontOfSize:50] retainCount]); NSLog(@"%d",[[UIFontsystemFontOfSize:50] retainCount]); NSLog(@"%d",[[UIFontsystemFontOfSize:50] retainCount]); とやると 2 3 4 5 6 と出てきます。どうやらインスタンス(と呼ぶのかどうかわかりませんが)を使い回ししてます。


ちなみに
NSLog(@"%d",[[NSStringstringWithFormat:@"abc"] retainCount]);
NSLog(@"%d",[[NSStringstringWithFormat:@"abc"] retainCount]);
NSLog(@"%d",[[NSStringstringWithFormat:@"abc"] retainCount]);
NSLog(@"%d",[[NSStringstringWithFormat:@"abc"] retainCount]);
NSLog(@"%d",[[NSString…

WebViewでの画像の扱い

画像を100px x 100pxで作成し、
htmlにwidth = "50px"と書いて表示すると

ratinaデバイス 100px x 100pxで元の画像通りに表示
非ratinaデバイス 50px x 50pxで滲んで表示

アプリ内に置いたHTMLファイルを表示

アプリ内に置いたHTMLファイル(index.html)を表示する。

NSString *address = [[NSBundlemainBundle] pathForResource:@"index" ofType:@"html"]; NSFileHandle *readHandle = [NSFileHandlefileHandleForReadingAtPath:address]; NSString *htmlString = [[NSStringalloc] initWithData:  [readHandle readDataToEndOfFile] encoding:NSUTF8StringEncoding]; [htmlViewloadHTMLString:htmlString baseURL:[NSURLfileURLWithPath:address]]; [htmlString release];

自動解放を伴うメソッドのretain counter

stringWith〜などは自動的にauto release poolに入って、自動的にreleaseが送られるけど、一連の流れの中でretain counterがどうなるかはなかなか書いているものがない。インスタンスが作成されるときに1となって自動release時に-1されるようである。