iPhoneアプリ開発の勉強の順番のススメ

ドキュメントは絶対読むべき。
そして読む順番はこう。

1、http://developer.apple.com/jp/iphone/library/documentation/Miscellaneous/Conceptual/iPhoneOSTechOverview/IPhoneOSOverview/IPhoneOSOverview.html#//apple_ref/doc/uid/TP40007898-CH4-SW1
2、http://developer.apple.com/jp/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ApplicationEnvironment/ApplicationEnvironment.html#//apple_ref/doc/uid/TP40007072-CH7-SW1
3、日本語ドキュメント - Apple Developer


適宜サンプルアプリを触ってみる。
http://developer.apple.com/iphone/library/navigation/index.html?section=Resource+Types&topic=Sample+C#section=Resource%20Types&topic=Sample%20Code


オススメ本はこれ

Amazon CAPTCHA※訳は直訳、超微妙
http://www.amazon.co.jp/iPhone%E3%82%A2%E3%83%97%E3%83%AA%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-GPS%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E6%A9%8B%E6%9C%AC-%E4%BD%B3%E5%B9%B8/dp/4798024244


都度APIリファレンスを読む。

※ちなみにAPIリファレンス日本語版たち
http://profo.jp/wiki/index.php?%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9
Foundation Framework - Cocoaリファレンス日本語化計画 - アットウィキ

以上!


もうそろそろ勉強を始めてから1ヶ月になります。
が、いまだにうまく理解できない。
なぜだ!?

こいつを読んでいないのが原因でした。

http://developer.apple.com/jp/iphone/library/documentation/Miscellaneous/Conceptual/iPhoneOSTechOverview/IPhoneOSOverview/IPhoneOSOverview.html#//apple_ref/doc/uid/TP40007898-CH4-SW1


そうMacで開発すんの始めてなんです。
だから、全然勝手が分からない。
ついでに組み込みアプリも初めてで。
だから、ハードのスクリーンの大きさからウィンドウの大きさを取得するなんて概念が理解できず。
Screenて何?とか言ってました。
Windowと何が違うの?と。


php始めたときはドキュメントなんてひとつも読まなくて問題なかった。
だからドキュメントを軽視していました。
(※あと紙媒体じゃないから読みづらくて、読まなかった;)

今回唯一読んだのは
日本語ドキュメント - Apple Developer


あれー、順番違う;
道理でわからんハズ;
順番間違えるとやる気失くしますw

だからこんなエントリーも書いてしまう。
堅っ苦しくて分かりづらいね。Objective-C 2.0プログラミング言語 ドキュメント - プログラミング日記でした

ドキュメントを読む順番は絶対こうだった。

1、http://developer.apple.com/jp/iphone/library/documentation/Miscellaneous/Conceptual/iPhoneOSTechOverview/IPhoneOSOverview/IPhoneOSOverview.html#//apple_ref/doc/uid/TP40007898-CH4-SW1
2、http://developer.apple.com/jp/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ApplicationEnvironment/ApplicationEnvironment.html#//apple_ref/doc/uid/TP40007072-CH7-SW1
3、日本語ドキュメント - Apple Developer


初めて見るクラスとかメソッドとか。
全部1から調べなきゃで。
頭に似たようなプレフィクスついてんなと思いつつ。
スルーして、また1から調べる。
そして端から忘れていくわけです。。。
覚えたことひとつひとつが記憶の中で独立してて、
他と結びつかないから記憶に定着しないんですよ;


でもちゃんと必須ドキュメント読んでれば、
覚えたことがひとつひとつつながっていく。
だから忘れない。
だから応用が出来るようになる。

以上、
ドキュメントのススメでしたー。

iPhone API とかまとめ

※英語は残念な感じです。
C言語は使ったことがないObjective-C勉強中の者です。
※間違っているところあったら教えていただけると助かります。

class_copyPropertyList
要はクラスのプロパティ情報の一覧を取得する

 objc_property_t * class_copyPropertyList(Class cls, unsigned int *outCount)

cls 調査したいクラス
outCount 返ってきた配列の長さ、NULLが返ってきたら、長さは返さない

戻り値
クラスによって宣言されたプロパティである、objc_property_t型のポインタの配列。
サブクラスによって宣言されたプロパティは含まない。
返り値である配列はNULLターミネーター(?)に従う*outCountポインターを含む
返り値は必ずfree()で解放すること。

initWithCapacity

 - (id)initWithCapacity:(NSUInteger)numItems

numItems 新しい配列の大きさの初期値

戻り値
numItemsオブジェクトを保持するのに十分なメモリを確保して初期化された配列。
返り値のオブジェクトはオリジナルのものとは違うものになるかもしれない?
※変更可能な配列の場合は必要以上に(確保メモリが?)増大する。
numItemsは簡単にオブジェクトの容量を確立するだけなのだ。

NSMutableDictionary
要は連想配列用クラス。
関連:NSDictionary,NSArray,NSMutableArray

配列とループ処理を理解しよう (3/4):Cocoaの素、Objective-Cを知ろう(5) - @IT

property_getName
プロパティ名を返す

const char *property_getName(objc_property_t property)

戻り値
プロパティ名を表すCstring型文字列

initWithCString
Cstring型文字列のエンコーディングをする
関連:stringWithCString,stringWithCharacters,etc...
[参考]
文字列(string)
oomori.com - このウェブサイトは販売用です! -&nbspoomori リソースおよび情報

C言語には文字列型という型はない。文字列は,char 型の配列で表される。ただし,単なる配列ではなく,「文字列の最後には終端を表す文字 '\0'(ヌル文字)がついている」という約束の下に取り扱われる文字配列である。文字列の最後に付けられたヌル文字を終端文字と呼ぶ。

stringWithFormat:
要はPHPでいうsprintf

oomori.com - このウェブサイトは販売用です! -&nbspoomori リソースおよび情報

NSMutableString:
可変文字列。NSStringのサブクラス。
NSStringは変更不可能。
[参考]変数のデータ型や文字列の扱いを理解しよう (3/3):Cocoaの素、Objective-Cを知ろう(4) - @IT

処理後の文字列を新たなオブジェクトとして返しているのに対し、NSMutableStringのメソッドでは、その主体となるインスタンスそのものに変更が加えられていることが分かります。


initWithContentsOfURL:
引数のURLからXMLコンテンツを取得する。

  • (id)initWithContentsOfURL:(NSURL *)url
url NSURLオブジェクト

Xcodeでタブエディターが使えます


http://macromates.com/

設定方法チュートリアル動画
http://macdevelopertips.com/wp-content/uploads/2008/06/xcode-textmate-final.mov

1、TextMateをダウンロードします。
2、Xcodeの設定→Fileタイプを開き、file→text→sourcecodeと選択
3、sourcecodeで右クリック、外部エディターのTextmateに設定する。
4、タブエディターで開きたいフォルダを、Textmateのアイコンにドラッグ&ドロップ
5、Textmateを使って編集できます。保存をすればXcodeに反映される

※英語しか入力できないみたいです。詳しくは
http://d.hatena.ne.jp/hetima/20061102/1162435711

TCPDFでスペースがたまに改行になるバグ

※tcpdf ver4.8
TCPDFでPDFを表示する時、
たまにスペースが改行になったり、スペースの後のテキストが全て表示されなくなるケースがあった。

条件が定かでなく、環境によって改行されたりされなかったり・・・
どこにも解決策が見当たらなかったんで、自力で調査。


多分これでOK


これを

tcpdf.phpの4419行目
if (($l > $wmax) OR ($shy AND (($l + $tmp_shy_replacement_width) > $wmax)) ) {
}


こうする。

if (($l > $wmax) OR ($shy AND (($l + $tmp_shy_replacement_width) > $wmax)) ) {
}else{
	$sep = -1;
}

色々調べてみると、他のテキストではループが終わるころには
全部「$sep = -1」となっているのに、
スペースの時はそうなっていなかった。

上記if文で弾かれて、そのまま
「$sep = -1」が設定されないのが原因。

それで、次の文字がこの条件に当てはまらないとき、

行4394
if (($c != 160) AND (($c == 173) OR preg_match($this->re_spaces, $this->unichr($c)))) {
行4421
if ($sep == -1) {
}else{
...
}

上記のelseの中に入り込んで、表示がおかしくなる、
という現象のよう。
つまり正確には改行ではなく、
「次の文字が先頭から始まる」
ってことみたい


※副作用がないかどうかは、現在検証中です。




【追記】
[else]を使うのではなく、

行4395
// update last blank space position
//$sep = $i;
//日本語の場合以降の自動改行処理をする必要がないため、[-1]固定。
//(英語はスペース部分でないと改行が出来ないため、pdfの幅を超えないよう、スペースで改行処理を行う必要がある。)
$sep = -1;

こうすることで、自動改行を無効にするほうが良さそう。

この部分でスペースの場所を記憶して、
以降の部分で、
スペースだったら残りの文字数数えて、
幅よりも長かったら自動的に改行するという計算をしていた。

「-1」ならスペースじゃないから自動改行しなくていいよ、
と認識してくれる。

英語だとスペースのところでないと改行できない(?)ためこの処理を行っているが、
(htmlでアルファベットが続くと改行されずにテーブルはみだしていく現象がそれ)
日本語なら、どこでも改行可能なので、
幅と残りの文字数を計算してスペース部分で改行する必要がない。
逆にそれをされると、文字数が幅より多いと、スペース部分で勝手に改行されてしまう。

堅っ苦しくて分かりづらいね。Objective-C 2.0プログラミング言語 ドキュメント

サンプルプログラムに一通り手をつけて、さて今度こそ、
ということでもう一度読み直しました。
日本語ドキュメント - Apple Developer

プロパティ @dynamic
動的にアクセサメソッドを追加するための文法
[参考]http://journal.mycom.co.jp/column/objc/102/index.html

実際にソースコードを書いてみると、@synthesizeを使うと比較的丁寧にエラーや警告を出してくれる。対応するインスタンス変数のチェックや、属性が適切かどうかなどを判断してくれる。だが@dynamicを使うと、動的に確認することになるので、コンパイル時のチェックはほとんどすっ飛ばされることになる。これでは台なしのような気もするが、Objective-Cらしいと言えば、その通りだろう。

retain,nonatomicの使用セオリー
[参考]iPhoneアプリケーション開発: Objective-Cのプロパティについて

iPhoneアプリケーションの場合、普通の変数についてはnonatomicとassignを、 自分で使うビューやラベル、配列、ディクショナリーなどにはnonatomicとretainを、文字列やデータなどにはnonatomicとcopyを設定するようです。

アトミック・非アトミック
iPhoneの場合アトミックにするとロックを使用するためパフォーマンスに影響あり。
よって基本的にnonatomicを使う(?)

メッセージ=「通信」
[参考]http://www16.ocn.ne.jp/~maccocoa/objective_c/primer/primer1_non_ie.html

C++というオブジェクト指向言語では「メンバ関数の呼び出し」と呼びます。
C++の関数呼び出しの場合は、プログラムの実行前から呼び出す関数が間違いなく存在しているかどうかチェックされます。そしてもし存在していなければプログラムは元から完成されません。ですが、Objective-Cのメッセージの場合は、そのメッセージを受けるオブジェクトに、対応する処理や操作(Objective-Cの場合にはこれをメソッドと呼びます)が存在するかどうかはチェックされていません。
プログラム実行時にメッセージを受けたオブジェクトに対応するメソッドが存在しない場合は、そのプラグラムは強制終了してしまいます。


[参考]http://journal.mycom.co.jp/column/objc/023/index.html

まず、受信オブジェクト、つまりobjc_msgSendの第一引数として渡ってきたオブジェクトが、nilかどうかをチェックする。nilの場合は、 LMsgSendNilSlefというラベルに飛び、nilを返して実行は終了する。

nilではない場合は、LMsgSendReceiverOkというラベルに進む。メッセージを送信するためにIMPを探すのだが、まずここでキャッシュから探す事になる。キャッシュは、第一引数のオブジェクトから得られる。この検索を行うのが、CacheLookupというマクロだ。

無事にIMPが見つかれば、呼び出しを行う。見つからない場合、つまりキャッシュミスが起こった場合は、次に進む。LMsgSendCacheMissというラベルだ。ここでは、メソッドテーブルからIMPの検索を行うために、MethodTableLookupというマクロを呼び出す。ここが、いちばん時間のかかる処理になるだろう。

そして、IMPを無事見つける事ができたら、それをキャッシュしておき、最後にIMPを実行する。これで、メッセージ送信の完了だ。

allocとallocWithZone
alloc=allocWithZone:NULL
アロケートは「確保する」の意味。メモリを確保すること。
[参考]oomori.com - このウェブサイトは販売用です! -&nbspoomori リソースおよび情報
http://homepage.mac.com/mkino2////////spec/optimize/allocation.html

alloc っていうのは allocWithZone:NULL といっしょなんだ。

ポインタ
なるほど、シンプルでわかりやすかった!
[参照]ポインタ

isa変数
isa変数はポインタ・・・じゃあポインタでいいじゃん;
表現にも世界標準を作ってくれないものだろうか。
[参照]Objective-C

isa変数は作成されたオブジェクトのクラス構造情報へのポインタである.クラス構造情報とは,クラス内のインスタンス変数の型と名前を持つと当時にメソッドの実装をも持つ.さらに,クラス構造情報には親クラスのクラス構造情報へのポインタも持つ.

[参照]http://journal.mycom.co.jp/column/objc/016/index.html

isaの意味は、「このオブジェクトの定義となるオブジェクト」ということになる。たとえば、オブジェクトAのisaがオブジェクトBである場合、オブジェクトAの定義はオブジェクトB。つまり、"ObjectA is an ObjectB"と、考えればいい。

File's Owner
[参照]http://journal.mycom.co.jp/column/objc/011/index.html

File's Ownerと呼ばれるインスタンスを含む。これは、nibファイル上のオブジェクトと、外部のオブジェクトをつなぐ、窓口となるものだ。

デリゲート
[参照]http://journal.mycom.co.jp/column/objc/010/index.html

あるクラスの動作の「判断」を、外部のオブジェクトにゆだねるための機構だ

プロトコル
[参照]http://journal.mycom.co.jp/column/objc/009/index.html

カテゴリ
[参照]http://journal.mycom.co.jp/column/objc/008/index.html

メタ
[参照]メタとは - IT用語辞典 e-Words

id型
[参照]http://journal.mycom.co.jp/column/objc/017/index.html

id型とは、構造体objc_objectのポインタ型であることが分かる。この構造体は、フィールドを1つだけ持っている。class型であるisa だ。
--中略--
「クラスもオブジェクトである」というObjective-Cの言語仕様は、「id型も、Class型も、クラス定義であるisaで始まる」と、実装面からも確認できるということだ。ちなみに、クラスオブジェクトにはクラス変数は存在しないので、objc_class構造体に変数用の可変長領域は必要ない。

では、構造体で先頭にisaがあれば、何でもオブジェクトなのか? まさに、その通りである。たとえば、C言語で構造体を作り、その先頭にisaとしてクラス定義へのポインタを置けば、それでもうObjective-Cのオブジェクトになる。

メソッド、セレクタ、ソッドの実装
[参照]http://journal.mycom.co.jp/column/objc/018/index.html

--前略--
メソッドとは、methodAに関する情報を管理する構造体だと考えて欲しい。クラスはメソッドの集合を管理する。
メソッドの名前となるのが、セレクタだ。セレクタ自体は、文字列と考えてしまって問題ない。
--中略--
int i; for (i = 0; ...) といったコードをコンパイルしたものは、バイトコードとして、メソッドとは別のところに置かれる。これが、メソッドの実装だ。メソッドは、メソッドの実装を、C言語関数のポインタとして持っている。

self
[参照]http://journal.mycom.co.jp/column/objc/022/index.html

Objective-Cでは、selfはメソッドに渡される局所変数にすぎない

インスタンスメソッドとクラスメソッド
[参照]Objective-Cのクラス定義を理解しよう (2/3):Cocoaの素、Objective-Cを知ろう(3) - @IT

 先頭に-(マイナス)が付加されたメソッドは、クラスのインスタンスがあって初めて実行できるメソッドで、「インスタンスメソッド」と呼ばれます。通常、ほとんどのメソッドはインスタンスメソッドとして定義することになります。

 一方、先頭の記号が「+(プラス)」となるメソッドもあります。これは、クラスのインスタンスを生成せずに、クラスの型から直接実行することが可能な「クラスメソッド」と呼ばれるメソッドです。

Eclipse CPU利用率95%、メモリ316M = Freeze my PC and my work

最近、Eclipseの処理がおっつかなくなる現象が多発します。
ので色々調べてみました。


[参考]http://hogebar.seesaa.net/article/33589453.html


結論としては
eclipse.iniで

  • XX:MaxPermSize=256m

と設定せよとのこと。

[参考]http://www.atmarkit.co.jp/fjava/rensai3/devedge06/devedge06_2.html

なるほど確かにやたらとクラスを参照してるんですよね。
Ctrl+左クリックで固まることが多かったのも納得です。

これでもだめなら、JSEclipse削除するしかないですかね。
[参考]http://d.hatena.ne.jp/kaiseh/20071126/1196079673



と、最後に余談。
freezeの使い方あってるかなーとググッたら、
「Freezer VS …」の文字が。
フリーザ様って英語だとやっぱFreezer(冷蔵庫)になっちゃうんですねw
英語が母国語の人は楽しめるんだろうか?w
http://www.youtube.com/watch?v=HdUPHXNPVR4

現状「規格1」「規格2」の2つまでしか使用できないですが、商品にそれ以上の項目を持たせたいときのTips

※「規格」のDBは使わずに、直接商品情報のDBにデータを追加します。

【出来ること】

  • 商品詳細画面でセレクトボックスなどを利用して、ユーザーに情報を入力してもらう
  • 追加項目に必須チェックをかける
  • 入力した情報をカート画面で確認できる
  • 入力した情報を注文確認画面で確認できる
  • 入力した情報を注文確認メールに記載する
  • 入力した情報を管理画面で確認できる
  • 入力した情報を管理画面の通知メールに記載できる
  • 管理画面の商品編集画面で、表示したい追加項目を選択できる


※追加項目を表示するか否かを判別するフラグ「add_flg」
※追加項目「add_field」


【商品詳細画面】
[eccube]/data/Smarty/templates/default/detail.tpl
([eccube]/html/user_data/packages/default/detail.tpl)

       <!--{if $arrProduct.add_flg == 1}-->
        <dl>
          <dt>
			追加項目
          </dt>
          <dd>
          	<input type="text" name="add_field" class="box54" value="<!--{$add_field}-->"  style="<!--{$arrErr.add_field|sfGetErrorColor}-->" />
          </dd>
        </dl>
        <!--{/if}-->


[eccube]/data/class/pages/products/LC_Page_Products_Detail.php

	function process() {
		case 'cart':
			$this->add_field 		= false;
			if($this->arrCartProduct["add_flg"] == 1) {
				$this->add_field = true;
			}
			if(count($this->arrErr) == 0) {
				$add_field 			= $_POST['add_field'];
				if(!$this->add_field) {
					$add_field = '0';
				}
				$objCartSess->addProduct(array($_POST['product_id'], $classcategory_id1, $classcategory_id2, $add_field), $this->objFormParam->getValue('quantity'));
			}

	}

	function lfInitParam() {
		$this->objFormParam->addParam("追加項目", "add_field", INT_LEN, "n", array("NUM_CHECK", "MAX_LENGTH_CHECK"));
	}

	function lfCheckError() {
		if($this->alcohol) {
			$objErr->doFunc(array("追加項目", "add_field"), array("EXIST_CHECK"));
		}
	}

[eccube]/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php

viewToSubQuery関数内のSELECT文に以下を追加
dtb_products.add_flg,
return vw_products_nonclassに以下を追加
T1.add_flg,


[eccube]/data/class/pages/shopping/LC_Page_Shopping_Confirm.php

process()関数内
$arrCart = $objCartSess->getCartList();
$max = count($arrCart);

foreach($arrCart as $i => $row){
$this->arrProductsDetails[$i]['add_field'] = $arrCart[$i]['id'][3];
}

[eccube]/data/class/pages/shopping/LC_Page_Shopping_Complete.php

lfRegistOrderDetail関数内
// 存在する商品のみ表示する。
if($arrData != "") {
$sqlval['add_field'] = $arrCart[$i]['id'][3];
array_splice($arrCart[$i]['id'],3);
}

【管理画面】
[eccube]/data/Smarty/templates/default/admin/products/product.tpl

<!--フラグ設定-->
	<tr class="fs12n">
	    <td bgcolor="#f2f1ec" width="160">フラグ設定</td>
	    <td bgcolor="#ffffff" width="557">
	         <label><input type="checkbox" name="add_flg" value="1" <!--{if $arrForm.add_flg == 1}-->checked="checked"<!--{/if}--> />追加項目</label>
	    </td>
	</tr>
<!--ここまで--> 


[eccube]/data/Smarty/templates/default/admin/products/confirm.tpl

<tr>
	<td bgcolor="#f2f1ec" width="160" class="fs12n">フラグ設定</td>
	<td bgcolor="#ffffff" width="557" class="fs12n">
		[追加項目]<!--{$arrDISP[$arrForm.add_flg]}--><br />
	</td>
</tr>


[eccube]/data/class/pages/admin/products/LC_Page_Admin_Products_Product.php

lfRegistProduct関数内
// 配列の添字を定義
$checkArray配列に"add_flg"を追加
// INSERTする値を作成する。
$sqlval['add_flg'] 		= $arrList['add_flg'];		//追加

lfConvertParam関数内
// スポット商品
$arrConvList['add_flg'] 	= "n";     //追加


【注文完了メール】
[eccube]/data/Smarty/templates/default/mail_templates/order_mail.tpl

ご注文商品明細の下
<!--{section name=cnt loop=$arrOrderDetail}-->
<!--{/section}-->
の中に以下を追加
<!--{if $arrOrderDetail[cnt].add_field!="" }-->
追加項目: <!--{$arrOrderDetail[cnt].add_field}-->
<!--{/if}-->

【DB】
dtb_products.add_flg 追加
dtb_order_detail.add_field追加


【カート】
[eccube]/data/Smarty/templates/default/cart/index.tpl

           <!--{ if $arrProductsDetails[cnt].add_field!="" }-->
           		追加項目:<!--{$arrProductsDetails[cnt].add_field}--><br />
           	<!--{/if}-->


[eccube]/data/class/pages/cart/LC_Page_Cart.php

			$this->arrProductsDetails[$i]['add_field'] = $arrCart[$i]['id'][3];

【受注】
/var/www/html/okurimono/data/Smarty/templates/default/shopping/confirm.tpl

	           <!--{ if $arrProductsDetails[cnt].add_field!="" }-->
	           		追加項目:<!--{$arrProductsDetails[cnt].add_field}--><br />
	           	<!--{/if}-->

[eccube]/data/Smarty/templates/default/admin/order/edit.tpl

                                    <!--{if $arrForm.product_add_field.value[$key] !="" }-->
                                    	[追加項目]<!--{$arrForm.product_add_field.value[$key]|escape}--><br />
	                                <!--{/if}-->


[eccube]/data/class/pages/admin/order/LC_Page_Admin_Order_Edit.php

        $this->objFormParam->addParam("追加項目", "product_add_field");
lfGetOrderDetail
$col = "add_fieldas product_add_field

見づらい・・・。
いつか書き直すかもしれません;