iPhone/memo_ama

Last-modified: 2010-12-20 (月) 19:36:17

開発手法が複数ある

  • Interface Builderと呼ばれるRADツールを用いる手法
  • ネイティブコードを使って、ゼロから記述していく手法

※ちなみに、インターフェースビルダ関連のファイルは以下の拡張子
 .xib = Xcode Interface Builder
 .nib = NeXT Interface Builderの略

検索するときも、どちらの開発手法であるかを念頭に置いて、調べるべし。

書籍関連

もし購入するならば、『iPhone SDK アプリケーション開発ガイド』
(Jonathan Zdziarski著、近藤誠監訳、武舎広幸+武舎るみ訳、
オライリージャパン、書籍版3,570円、PDF版2,856円)が良い。

他のiPhone SDKの本がInterface Builder を多用しているのに対し、
この本は、ネイティブコードを使用して開発しているため。

ただし、・中上級者向け ・Objective-C自体に関する解説は皆無
とのこと。

解像度

  ・iPhone 3GS 480×320ピクセル、 解像度163ppi
  ・iPhone 4 960×640ピクセル、 解像度326ppi
  ・iPad    1024×768ピクセル、解像度132 ppi

iPadのアプリケーションサイズを実測

幅:768、高さ:1004、x:0、y:20であり、ステータスバーの大きさは、iPhoneと同じであることがわかった

メモリサイズ

http://ipodtouchlab.com/2009/06/iphone-3g-s600mhz256mb.html
によると、iPhone3GSのメモリは256MBであることがわかった。

SDKに関して

 ・iPhone SDKは、現在、公式的には3.2~しか公開されていない。
 ・iPhone SDK 3.2以降は、Mac OS X 10.6でないと動かない
 ・iPhone SDK 3.1は、リンクが消されている
  ⇒ただし、SDK 3.1.3がサーバーには残っており、ダウンロード可能
 ・iPhone SDK3.1.2以前は、完全に削除されてしまった
 ・iPhone SDK 3.1.3は、Mac OS X 10.5で動作する最後のバージョン
 ・とはいえ、iPadやiPhone4の開発に対応しているのは3.2以降なので、もうこちらを使わざるを得ないだろう。

(上記に関連して)Mac OSのアップデートに関して

 ・Mac OS X 10.5.8 ⇒ 10.6へのアップグレード価格は3300円
  ⇒メジャーバージョンアップになるので、有償になってしまう
   アップグレードパッケージの公式サイトから、CPUとOSを入力して、どのパッケージを購入すべきか、
   チェックできるので、チェックしてから購入するべし。
   http://store.apple.com/jp/product/MC573J/A

 ・古いデータを外付けのHDDにとっておく際、Time Machineで初期化してもよいものかを確認しておく。
  初期化されたくなければ、外付けHDDを接続したときに聞かれる「Time Machineを使うか?」
  といったウィンドウに対しては、NOで答えること。

各種基本的な処理のコーディングなら、ここは絶対に参考すべし

http://www.saturn.dti.ne.jp/~npaka/iphone/

アプリケーションを終了したときのデリゲートが

iPhone3とiPhone4で違うようなので、注意

環境の立ち上げ関連

 (1)Mac OS Xにkey chainとして証明書を登録する
 (2)登録したkey chainをXcodeに反映させる
 (3)iPhone側の期限の切れたプロビジョニングプロファイルを削除

  ⇒これをしないと、コンパイルエラーがでます。

Symbol(s) not found

AudioToolboxを使うと Symbol(s) not foundというエラーが出る。
これは、そんな関数ないよというエラー。
明らかに存在するはずなのに、このエラーが出たときは、
プロジェクトに既存のフレームワークを追加してあげないとだめ。
プロジェクト名を右クリックして追加を選び。既存のフレームワーク」を選択し、AudioToolBoxを追加するとエラーが消えた
http://d.hatena.ne.jp/etopirika5/20100522/1274551917

配列より大きい部分にアクセスすると原因不明のバグが起こる

 パス名を保持する配列を確保している数が足りないときに、
 とんでもないエラーが起きたことがあった。
  
 Objective-Cはメモリ違反に対する監視が甘いのか、
 特に実行エラーも起きず、一見普通に動作する。
 
 関係のない文字列変数に他の場所に入っているはずの文字列が入っている、
 変えたはずのないビューのサイズが変わっている
 などの現象が起きた場合は、今後、これを疑うようにする。
 
 iPhoneはシミュレータ含め、メモリ違反に対する挙動が特殊である。

通し番号の扱い方

NSString *name=[NSString stringWithFormat:@"card%02d%d.png", 8 , 3];

単純に"card%d%d"だとcard83になっちゃうけど、%0を付けてあげることで、頭に0がついた通し番号を扱える。
上の例なら、“card083.png”としてnameに代入されます。

iPhoneの文字列操作

http://ft-lab.ne.jp/cgi-bin/wiki.cgi?page=%CA%B8%BB%FA%CE%F3%A4%CE%B4%C9%CD%FD(NSString)_mac

substringWithRangeは、全角であろうと、半角であろうと、1文字は1文字としてカウントしてくれる

NSStringの文字列検索

http://goer.geo.jp/archives/51

Cのstrtok・HSPのstrmidをobjective-Cでやるとこうなる

http://kak419.blogspot.com/2009/04/objective-c.html

NSString* lines = [text componentsSeparatedByString:@"\n"];
NSArray* items = [[lines objectAtIndex:index] componentsSeparatedByString:@","];

iPhoneのsystem soundの制約

基本的には30秒以下のwavと考えてよさそう
http://bugzero.shooti.jp/sitehead/http%3A%2F%2Fblog.livedoor.jp%2Fsecond_flush%2Farchives%2F51141751.html

ToolBarへのUIBarButtonItemの追加方法

ただ、ここで使われているメソッドが、XCodeのリファレンスで引っかからないのだが、
レギュレーション違反にならないか心配である。
http://perso.ovh.net/~detailsf/iPhone/2010/ajouter-une-barre-doutils-uitoolbar/
 
http://hmdt.jp/hpdt/navigation/item.html
ここにもナビゲーションアイテムを追加する方法が載っているが、
サイト自体がかなり古いので、正式なAPIであるかはわからない。

HTTP通信に関するあれこれ

テキストの取得は成功するけど、普通のサイトの取得は、nullになってしまう。
エンコーディング前のデータは入ってるから、エンコーディングがおかしい?
http://www.saturn.dti.ne.jp/~npaka/iphone/HttpEx/index.html

あまり精読していないもの。参考になるかはわからない。

ソケットプログラミング参考
http://codezine.jp/article/detail/4936
Mac OS XのクラスをiPhone用にしてしまうという荒業もあるが、購読には登録が必要。
http://codezine.jp/article/detail/4936
ここも詳しい。
http://d.hatena.ne.jp/It_lives_vainly/20090312/1236855251

ASIHTTPRequest

POSTデータを送る方法が上記サイトにはないけど、
ASIHTTPRequestを使うと、簡単に送ることができる。
導入方法:
http://xcatsan.blogspot.com/2010/03/keychain-services-22-twitpic-asi-http.html

//これだけでPOSTデータが送れる。
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:@"oreore" forKey:@"username"];

 
ASIHTTPRequestは、GETを使うこともできる。

URLエンコーディングについて

 ASIHTTPRequestを使う場合も、上記の通常のHTTPリクエストを
 用いた場合(iPhone付属のNSURLRequestクラス)も同じなのだが、
 
 http://www.google.co.jp
 のようなURLならば、通常にHTMLファイルを取得することができる
 
 しかし、
 http://www.google.co.jp/search?q=(秋葉原)
 のようにパラメータを付けると、接続エラーになることがわかった。
 
 この現象はASIHTTPRequestだけでなく、iPhone付属のNSURLRequestクラスを
 使用した場合も同様であることがわかった。
 
 これは、日本語がパラメータに入っているためである。
(日本語でなければ、通常にパラメータを渡せる)

 URLエンコードとは以下のようなもの
 例)秋葉原 ⇒ %8fH%97t%8c%b4
 
 http://iphone-dev.ensites.net/archives/573
 を参考にした。

 さらに、上記サイトは、 
 stringByAddingPercentEscapesUsingEncodingというメソッドの使用に加えて
 エスケープする文字をケアしている。
 具体的には$とか、なにか悪さできるポストを禁止している。
 が、「?」とか「&」とかまでエスケープしてしまっているので、
 丸々、アドレスを渡すと、エスケープされて、変なアドレスになってしまうので注意。

 

時刻の引き算

http://d.hatena.ne.jp/nakamura001/20100609/1276101689

	//時刻保存用
	_date[DATE_NOW]   = [NSDate date];
	NSTimeInterval since;

	// dateBとdateAの時間の間隔を取得(dateB - dateAなイメージ)
	since = [_date[DATE_NOW] timeIntervalSinceDate: _date[DATE_START]];

	int hour;
	int minute;
	int second;

	hour    = (int)since/(60*60);
	since  -= hour*3600;
	minute  = (int)since/60;
	since  -= minute*60;
	second  = since;

	_label[LABEL_TIME].text = [NSString stringWithFormat:@"TIME %02d:%02d:%02d", hour, minute, second];
	_label[LABEL_TIME_SHADOW].text = [NSString stringWithFormat:@"TIME %02d:%02d:%02d", hour, minute, second];

TableViewの使用法あれこれ

tableViewController.tableView.dataSource = self;

のように、dataSourceを設定してあげないと、
何も表示されない。

普通は、IBでやる部分なので、乗っていないことが多い注意。

もう1つIBでやるのは、tableViewController.tableView.delegate = self;
であると思われる。

参考資料

エリカ本のほとんど内容同じ。
エリカ本はTableViewの説明がよくわからないのでここは参考までに。
http://d.hatena.ne.jp/CLSmooth/20090302

 
説明自体は
http://japan.internet.com/developer/20100112/26.html
のほうがわかりやすい。
ボタンの追加や画像の追加なども説明されている。
 
ただし、IBを使用しているので、注意せよ。
 
さらに、複数行表示する方法を見つけた。
http://afunishi.blog69.fc2.com/?no=598

 
TableViewを更新するときは、
[tableview reloadData]というのをやらないとだめ。
TableViewControllerのときは、
[tvc.tableView reloadData];
http://d.hatena.ne.jp/paella/20090130/123
 

リソースファイルのデータは書き換え不可

テキストファイルなどをリソースに読み込んで、書き変えようとしたりしてはダメ。

新しいXcodeを動作させる方法

 ●iPhoneのソースをiPadに対応させる際、
  「現在のターゲットをiPad用にアップグレード」を使用するが、
  これを実行する前に、設定画面で「iPad」または「iPhone/iPad」を選択しているとこのコマンドが実行できない
  ⇒最初は、iPhoneにしておき、コマンド実行後、「iPhone/iPad」にする必要がある

 ●リソースを登録する際、パスを追加する方法と、現物をそのまま追加する方法がある。
  フォルダなどを追加する場合に、パスを追加するほうが便利なので、追加時にポップアップするウィンドウに注意

 ●リソースの削除は、左のカラムでできない場合、右上のペインで削除できる

 ●iPhoneとiPadでリソースのフォルダは異なるが、この中に入れるフォルダの名前は同一にしてはいけない。
  最終的には、.app直下のフォルダとして1つに統合されることがある
  ⇒なぜか画像が貼られなかったり、アプリケーションが落ちてしまう原因にもなる

 ●iPadはiOS4にはまだ対応していない(2010年の秋に対応するとのこと)
  したがって、iOS3.2の設定で転送する必要がある

iPhoneがサスペンドする際に呼ばれるメソッドなど

http://kamonama.blogspot.com/2007/12/iphoneipod-touch_31.html

ロック中にバックグラウンドで処理を行うと、ステータスバーが点滅する状態になる

 (電話割り込みの例ではあるが、公式のApplication Programming Guideにも
  同じようにステータスバーが大きくなるという記述がみられる)

 下記pdfの35ページ
 http://developer.apple.com/jp/iphone/library/documentation/iPhoneAppProgrammingGuide.pdf

iPhoneの4.0でiTunesのアプリ同期を使うのは危険?

いくつかインストール済みのアプリを消してしまった。
  

App Storeに登録したアプリが落ちる事例

iOS3のはずが、iOS4用にコンフィギュレーションした場合、iOS3でダウンロードすると、アプリが起動せずに落ちる。

defineは\では、改行回避できない。

アップルの¥は、バックスラッシュ(option + \)を使わないとだめ。

タッチに関するあれこれ

順序

タッチは、基本的に、ビューは上に乗っているものが反応するが、
もし、上に乗っているビューにUserInteractionEnable = noが入っている場合、
下のビューが代わりに反応する。

 
上下関係は、基本的に後からaddsubviewしたものが上になるけど、
bringSubViewToFrontメソッドを使うと上下を入れ替えることができる。
.hidden = YESで隠しちゃうのも手
 
タッチとか使うときは、
ビュー.frame.size.とか、ビュー.frame.originを使うと便利。
基本的に、frame.orginは0,0なので、frame.sizeを使えばOK
 
ただ、タッチに関しては、locationInViewを使ってローカルに変換してあげないとだめ。

タッチが反応しないとき

initWithFrameを使って初期化したか?

 おそらく、こいつのスーパークラスには、initWithFrameで受け取ったRECTに対して、あたり判定を設定する仕組みが備わっているのだろう

_object_getClassName( object )でオブジェクトのクラス名を取得することができる。

サブクラス内にtouchBeganを定義したのではないか?(デリゲートが違う)

たとえば、画像は画像用のクラスでtouchesBeganを使用すると、
メインのwindowでtouchBeganを使っても、その画像には反応しなくなる。

特定のビューに対するタッチ

[event touchesForView: ビューのインスタンス]を使うと、
特定のビューに対するタッチがあったかをboolean?でとれる。

タッチオブジェクトを判別しつつ、かつ、タップ回数も取得したいときのコード

//画面がタッチされたときに、いつでも呼び出されるメソッド
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	NSSet* touchForView = [event touchesForView:_iView[IMAGE_BALOON] ];
	UITouch* touch = [touchForView anyObject];
	if( touchForView ){
		NSLog(@"バルーン画像がタップされました%d", touch.tapCount);
	}

	//below code didn't work
	//		id touchedObj = [touches anyObject];
	//		if( touchedObj == _iView[IMAGE_BALOON] ){
	//			NSLog(@"バルーン画像がタップされました");
	//		}
}

タッチの取得作法

上記、特定のビューに対するタッチを使わない場合は、
タッチは、[touches allObject]で、ゲットしたものを.count分、ループしてゲットする。

iPad回転対応について

回転対応の必要性

http://developer.apple.com/iphone/library/documentation/General/Conceptual/iPadHIG/iPadHIG.pdf
⇒日本語版:http://developer.apple.com/jp/iphone/library/documentation/iPadHIG.pdf
 
http://developer.apple.com/iphone/library/qa/qa2010/qa1588.html
http://developer.apple.com/iphone/library/qa/qa2010/qa1689.html

【要約】
でかいんだから、回転に対応したほうがいいっしょ。

回転対応のためのコード

-(BOOL)shouldAutorotateToInterfaceOrientation
 :(UIInterfaceOrientation)interfaceOrientation
{
  return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}

return文を削除すると、すべての方向に対応可能だが、
自動では拡大縮小は実行されず、その大きさのまま回転する
拡大縮小は、あらかじめ、ビューの属性を変えておく必要がある。

iPad回転時、縦用画面を自動で横画面用に調整してくれるようなAPIがないか

 http://profo.jp/wiki/index.php?UIView
 に示されているプロパティを見ながら、修正を試みるが、うまい修正はできず。

  self.view.autoresizesSubviews = NO;

 とすると、768x1024の画面をそのままの大きさで回転することに成功した。
 横幅の余った部分は、灰色の空白が表示された状態になる。
 
 横方向のスクロールに関してはうまくいく。
 しかし、回転後の768の縦幅に1024の画面を入れるので、画面下部がはみ出て見えなくなってしまう。
 また、縦方向はスクロール(できないはずが)できてしまう。

調査完了

エリカ本の回転対応よりもっと簡単にできる。

	imageView.autoresizingMask=
	UIViewAutoresizingFlexibleWidth|
	UIViewAutoresizingFlexibleHeight|
	UIViewAutoresizingFlexibleLeftMargin|
	UIViewAutoresizingFlexibleRightMargin|
	UIViewAutoresizingFlexibleTopMargin|
	UIViewAutoresizingFlexibleBottomMargin;

上記は、imageViewに対して適用しているけれど、各ビューに対して適用すればOk

webViewでは、以下のようにして、ビューにフィットさせる。

webView.scalesPageToFit = YES;
webView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
shouldAutorotateToInterfaceOrientation で return YES;// true

 
参考:
http://www.inazumatv.com/contents/archives/2335

IB関連の留意点

(1)インターフェースビルダーで作成したオブジェクトは、インスタンスを生成する必要はない。
(2)XIBにインスタンスとして存在するので、結びつけるだけでよい
   ⇒プログラムからみると、インスタンスされてないように見えるので注意
    IBOutletとついていたら、インスタンスが生成されていないはず
(3)IBActionはvoidだが、IBOutletは型名の前につけるものなので注意
(4)Interface BuilderでOutletとビューを結びつけておけば、後はオブジェクトの代入までやってくれる