<?xml version="1.0" encoding="UTF-8" ?>
	<rss version = "2.0"  xmlns:blogChannel="http://backend.userland.com/blogChannelModule" >
		<channel>
			<title>Born Neet</title>
			<description>- The Emotional Programmer -</description>
			<link>http://blog.bornneet.com/</link>
			<language>ja</language>
			<copyright>Copyright (C) 2005-2008 SAMURAI-FACTORY ALL RIGHTS RESERVED.</copyright>

		<item>
			<title>IB不使用＆オープンソースなiPadアプリ（テキストエディタ）を作る 第5回：Undo・Redoボタン</title>
			<description>
			<![CDATA[<p>
続けざまに第5回。<br />
簡単そうな課題が残ってたを思い出したので。<br />
<br />
</p>
<h3>参考</h3>
<p>今回は、参考サイトはありません。<br />
参考書籍は<a href="http://blog.bornneet.com/Entry/287/">第1回</a>をご参照下さい。<br />
</p>
<h3>素材</h3>
<p>引き続き、<a href="http://snow.if.tv/" class="external" target="_blank" title="新しいウィンドウで開きます">Soft * Accessory</a>様の素材をお借りしています。</p>
<h3>1. Undo/Redoボタンの追加</h3>
<p>まずはボタンの追加です。<br />
といっても既に新規ファイル・フォルダでやったのと同じ手順です。<br />
今回は、DetailViewControllerのinitに実装します。
</p>
<pre class="source syntax brush-clang"><code>		// targetとactionをnilにしたら勝手にundo,redoしてくれるっぽいけど保証されるかわからんのでやめとく
		UIBarButtonItem *undoButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemUndo target:self action:@selector(undoDidPush)];
		UIBarButtonItem *redoButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRedo target:self action:@selector(redoDidPush)];
		NSArray *items = [NSArray arrayWithObjects:undoButton, redoButton, nil];
		[toolbar setItems:items];</code></pre>

<h3>2. Undo/Redo機能の実装</h3>
<p>NSUndoManagerを使って行ないます。<br />
こいつはUIResponderのundoManagerプロパティから取得できます。<br />
TextViewもUIResponderのsubclassの為、もちろんこのプロパティを持っています。<br />
今回はTextViewから取得したundoMangerに対して、undo/redoメソッドを呼び出しています。</p>
<pre class="source syntax brush-clang"><code>- (void)undoDidPush {
	[[textView_ undoManager] undo];
}

- (void)redoDidPush {
	[[textView_ undoManager] redo];	
}
</code></pre>
<p>
[1.]のコメントにも書きましたが、<br />
実はUIBarButtonSystemItemUndo・Redoのボタンを作るとき、<br />
selfとactionをnilにしておけば勝手にやってくれるようです。<br />
※ ドキュメントに記載が見当たらなかったので使うのは止めてます。
</p>

<h3>[完成]</h3>
<p>できました！<br />
<img src="http://file.blog.bornneet.com/ipad5_undoredo.png" alt="Undo/Redoボタンの実装" />
</p>

<h3>[まとめ]</h3>
<p>
これでおしまいです。<br />
そんなに苦労しないだろうと思ってましたが、<br />
予想を上回る簡単さでした。
</p>

<h3>[コード]</h3>
<p>今回のコードは「Edhita5.zip」に入っています。<br />
GitHubのdownloadページからダウンロードして下さい。<br />
<br />
<a href="http://github.com/tnantoka/Edhita/downloads" class="external" target="_blank" title="新しいウィンドウで開きます">Downloads for tnantoka's Edhita - GitHub</a></p>]]>
			</description>
			<link>http://blog.bornneet.com/Entry/291/</link>
			<pubDate>Sun, 29 Aug 2010 07:46:10 GMT</pubDate>
		</item>
		<item>
			<title>IB不使用＆オープンソースなiPadアプリ（テキストエディタ）を作る 第4回：Settings.bundleと色・サイズ・フォント変更</title>
			<description>
			<![CDATA[<p>
第4回。<br />
<br />
今回は予定を変更して設定変更を実装します。<br />
あまりにも文字が小さくて見づらいので。<br />
<br />
超簡単なのでちゃっちゃと終わらせまーす。
</p>
<h3>参考</h3>
<p>今回は、constの使い方について以下のサイトで勉強させていただきました。<br />
結局使わなかったけど…。<br />
<a href="http://blog.svartalfheim.jp/?p=147" class="external" target="_blank" title="新しいウィンドウで開きます">svartalfheim.jp - Objective-Cについて</a>
<br />
<br />
参考書籍は<a href="http://blog.bornneet.com/Entry/287/">第1回</a>をご参照下さい。<br />
</p>
<h3>素材</h3>
<p>引き続き、<a href="http://snow.if.tv/" class="external" target="_blank" title="新しいウィンドウで開きます">Soft * Accessory</a>様の素材をお借りしています。</p>
<h3>1. 設定画面の追加</h3>
<p>設定画面はアプリ独自で持つこともできるのですが、<br />
アップル的にはデフォルトの設定アプリの方に統一したいらしいので、<br />
ここではそれに従います。<br />
<br />
手順は以下のとおり。<br />
XMLファイルを作るだけで画面作ってくれて非常に簡単です。
</p>
<h4>(1) 設定ファイルの作成</h4>
<p>グループとファイルのResourcesを右クリック。<br />
追加 → 新規ファイル → iPhone OS → Resouce → Settings Bundleを選択。<br />
デフォルトのまま次へ進めば完了。<br />
<img src="http://file.blog.bornneet.com/ipad4_settings.png" alt="設定ファイルの作成" />
</p>
<h4>(2) 設定項目の作成</h4>
<p>
Resources内のRoot.plistを編集します。<br />
今回はフォントや色・サイズを選択させるので、PSMultiValueSpecifierを使います。<br />
<br />
完成したファイルがこちら。<br />
※ fontはとりあえず使えるやつ全部を一覧化。<br />
　sizeは10から50まで2刻みで用意してます。
</p>
<pre class="source syntax brush-xml"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;StringsTable&lt;/key&gt;
	&lt;string&gt;Root&lt;/string&gt;
	&lt;key&gt;PreferenceSpecifiers&lt;/key&gt;
	&lt;array&gt;
		&lt;dict&gt;
			&lt;key&gt;Type&lt;/key&gt;
			&lt;string&gt;PSGroupSpecifier&lt;/string&gt;
			&lt;key&gt;Title&lt;/key&gt;
			&lt;string&gt;Color&lt;/string&gt;
		&lt;/dict&gt;
		&lt;dict&gt;
			&lt;key&gt;Type&lt;/key&gt;
			&lt;string&gt;PSMultiValueSpecifier&lt;/string&gt;
			&lt;key&gt;Title&lt;/key&gt;
			&lt;string&gt;Text Color&lt;/string&gt;
			&lt;key&gt;Key&lt;/key&gt;
			&lt;string&gt;textColor&lt;/string&gt;
			&lt;key&gt;DefaultValue&lt;/key&gt;
			&lt;integer&gt;0&lt;/integer&gt;
			&lt;key&gt;Values&lt;/key&gt;
			&lt;array&gt;
				&lt;integer&gt;0&lt;/integer&gt;
				&lt;integer&gt;1&lt;/integer&gt;
				&lt;integer&gt;2&lt;/integer&gt;
				&lt;integer&gt;3&lt;/integer&gt;
				&lt;integer&gt;4&lt;/integer&gt;
				&lt;integer&gt;5&lt;/integer&gt;
				&lt;integer&gt;6&lt;/integer&gt;
				&lt;integer&gt;7&lt;/integer&gt;
				&lt;integer&gt;8&lt;/integer&gt;
				&lt;integer&gt;9&lt;/integer&gt;
				&lt;integer&gt;10&lt;/integer&gt;
				&lt;integer&gt;11&lt;/integer&gt;
				&lt;integer&gt;12&lt;/integer&gt;
				&lt;integer&gt;13&lt;/integer&gt;
			&lt;/array&gt;
			&lt;key&gt;Titles&lt;/key&gt;
			&lt;array&gt;
				&lt;string&gt;Black&lt;/string&gt;
				&lt;string&gt;DarkGray&lt;/string&gt;
				&lt;string&gt;LightGray&lt;/string&gt;
				&lt;string&gt;White&lt;/string&gt;
				&lt;string&gt;Gray&lt;/string&gt;
				&lt;string&gt;Red&lt;/string&gt;
				&lt;string&gt;Green&lt;/string&gt;
				&lt;string&gt;Blue&lt;/string&gt;
				&lt;string&gt;Cyan&lt;/string&gt;
				&lt;string&gt;Yellow&lt;/string&gt;
				&lt;string&gt;Magenta&lt;/string&gt;
				&lt;string&gt;Orange&lt;/string&gt;
				&lt;string&gt;Purple&lt;/string&gt;
				&lt;string&gt;Brown&lt;/string&gt;
			&lt;/array&gt;
		&lt;/dict&gt;
		&lt;dict&gt;
			&lt;key&gt;Type&lt;/key&gt;
			&lt;string&gt;PSMultiValueSpecifier&lt;/string&gt;
			&lt;key&gt;Title&lt;/key&gt;
			&lt;string&gt;Background Color&lt;/string&gt;
			&lt;key&gt;Key&lt;/key&gt;
			&lt;string&gt;backgroundColor&lt;/string&gt;
			&lt;key&gt;DefaultValue&lt;/key&gt;
			&lt;integer&gt;3&lt;/integer&gt;
			&lt;key&gt;Values&lt;/key&gt;
			&lt;array&gt;
				&lt;integer&gt;0&lt;/integer&gt;
				&lt;integer&gt;1&lt;/integer&gt;
				&lt;integer&gt;2&lt;/integer&gt;
				&lt;integer&gt;3&lt;/integer&gt;
				&lt;integer&gt;4&lt;/integer&gt;
				&lt;integer&gt;5&lt;/integer&gt;
				&lt;integer&gt;6&lt;/integer&gt;
				&lt;integer&gt;7&lt;/integer&gt;
				&lt;integer&gt;8&lt;/integer&gt;
				&lt;integer&gt;9&lt;/integer&gt;
				&lt;integer&gt;10&lt;/integer&gt;
				&lt;integer&gt;11&lt;/integer&gt;
				&lt;integer&gt;12&lt;/integer&gt;
				&lt;integer&gt;13&lt;/integer&gt;
			&lt;/array&gt;
			&lt;key&gt;Titles&lt;/key&gt;
			&lt;array&gt;
				&lt;string&gt;Black&lt;/string&gt;
				&lt;string&gt;DarkGray&lt;/string&gt;
				&lt;string&gt;LightGray&lt;/string&gt;
				&lt;string&gt;White&lt;/string&gt;
				&lt;string&gt;Gray&lt;/string&gt;
				&lt;string&gt;Red&lt;/string&gt;
				&lt;string&gt;Green&lt;/string&gt;
				&lt;string&gt;Blue&lt;/string&gt;
				&lt;string&gt;Cyan&lt;/string&gt;
				&lt;string&gt;Yellow&lt;/string&gt;
				&lt;string&gt;Magenta&lt;/string&gt;
				&lt;string&gt;Orange&lt;/string&gt;
				&lt;string&gt;Purple&lt;/string&gt;
				&lt;string&gt;Brown&lt;/string&gt;
			&lt;/array&gt;
		&lt;/dict&gt;
		&lt;dict&gt;
			&lt;key&gt;Type&lt;/key&gt;
			&lt;string&gt;PSGroupSpecifier&lt;/string&gt;
			&lt;key&gt;Title&lt;/key&gt;
			&lt;string&gt;Font&lt;/string&gt;
		&lt;/dict&gt;
		&lt;dict&gt;
			&lt;key&gt;Type&lt;/key&gt;
			&lt;string&gt;PSMultiValueSpecifier&lt;/string&gt;
			&lt;key&gt;Title&lt;/key&gt;
			&lt;string&gt;Font Name&lt;/string&gt;
			&lt;key&gt;Key&lt;/key&gt;
			&lt;string&gt;fontName&lt;/string&gt;
			&lt;key&gt;DefaultValue&lt;/key&gt;
			&lt;string&gt;Helvetica&lt;/string&gt;
			&lt;key&gt;Values&lt;/key&gt;
			&lt;array&gt;
				&lt;string&gt;AcademyEngravedLetPlain&lt;/string&gt;
				&lt;string&gt;AmericanTypewriter&lt;/string&gt;
				&lt;string&gt;AmericanTypewriter-Bold&lt;/string&gt;
				&lt;string&gt;AppleGothic&lt;/string&gt;
				&lt;string&gt;Arial-BoldItalicMT&lt;/string&gt;
				&lt;string&gt;Arial-BoldMT&lt;/string&gt;
				&lt;string&gt;Arial-ItalicMT&lt;/string&gt;
				&lt;string&gt;ArialHebrew&lt;/string&gt;
				&lt;string&gt;ArialHebrew-Bold&lt;/string&gt;
				&lt;string&gt;ArialMT&lt;/string&gt;
				&lt;string&gt;ArialRoundedMTBold&lt;/string&gt;
				&lt;string&gt;Baskerville&lt;/string&gt;
				&lt;string&gt;Baskerville-Bold&lt;/string&gt;
				&lt;string&gt;Baskerville-BoldItalic&lt;/string&gt;
				&lt;string&gt;Baskerville-Italic&lt;/string&gt;
				&lt;string&gt;BodoniOrnamentsITCTT&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoITCTT-Bold&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoITCTT-Book&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoITCTT-BookIta&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoOSITCTT-Bold&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoOSITCTT-Book&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoOSITCTT-BookIt&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoSCITCTT-Book&lt;/string&gt;
				&lt;string&gt;BradleyHandITCTT-Bold&lt;/string&gt;
				&lt;string&gt;Chalkduster&lt;/string&gt;
				&lt;string&gt;Cochin&lt;/string&gt;
				&lt;string&gt;Cochin-Bold&lt;/string&gt;
				&lt;string&gt;Cochin-BoldItalic&lt;/string&gt;
				&lt;string&gt;Cochin-Italic&lt;/string&gt;
				&lt;string&gt;Copperplate&lt;/string&gt;
				&lt;string&gt;Copperplate-Bold&lt;/string&gt;
				&lt;string&gt;Courier&lt;/string&gt;
				&lt;string&gt;Courier-Bold&lt;/string&gt;
				&lt;string&gt;Courier-BoldOblique&lt;/string&gt;
				&lt;string&gt;Courier-Oblique&lt;/string&gt;
				&lt;string&gt;CourierNewPS-BoldItalicMT&lt;/string&gt;
				&lt;string&gt;CourierNewPS-BoldMT&lt;/string&gt;
				&lt;string&gt;CourierNewPS-ItalicMT&lt;/string&gt;
				&lt;string&gt;CourierNewPSMT&lt;/string&gt;
				&lt;string&gt;DBLCDTempBlack&lt;/string&gt;
				&lt;string&gt;Didot&lt;/string&gt;
				&lt;string&gt;Didot-Bold&lt;/string&gt;
				&lt;string&gt;Didot-Italic&lt;/string&gt;
				&lt;string&gt;Futura-CondensedExtraBold&lt;/string&gt;
				&lt;string&gt;Futura-Medium&lt;/string&gt;
				&lt;string&gt;Futura-MediumItalic&lt;/string&gt;
				&lt;string&gt;GeezaPro&lt;/string&gt;
				&lt;string&gt;GeezaPro-Bold&lt;/string&gt;
				&lt;string&gt;Georgia&lt;/string&gt;
				&lt;string&gt;Georgia-Bold&lt;/string&gt;
				&lt;string&gt;Georgia-BoldItalic&lt;/string&gt;
				&lt;string&gt;Georgia-Italic&lt;/string&gt;
				&lt;string&gt;GillSans&lt;/string&gt;
				&lt;string&gt;GillSans-Bold&lt;/string&gt;
				&lt;string&gt;GillSans-BoldItalic&lt;/string&gt;
				&lt;string&gt;GillSans-Italic&lt;/string&gt;
				&lt;string&gt;Helvetica&lt;/string&gt;
				&lt;string&gt;Helvetica-Bold&lt;/string&gt;
				&lt;string&gt;Helvetica-BoldOblique&lt;/string&gt;
				&lt;string&gt;Helvetica-Oblique&lt;/string&gt;
				&lt;string&gt;HelveticaNeue&lt;/string&gt;
				&lt;string&gt;HelveticaNeue-Bold&lt;/string&gt;
				&lt;string&gt;HelveticaNeue-BoldItalic&lt;/string&gt;
				&lt;string&gt;HelveticaNeue-Italic&lt;/string&gt;
				&lt;string&gt;HiraKakuProN-W3&lt;/string&gt;
				&lt;string&gt;HiraKakuProN-W6&lt;/string&gt;
				&lt;string&gt;HiraMinProN-W3&lt;/string&gt;
				&lt;string&gt;HiraMinProN-W6&lt;/string&gt;
				&lt;string&gt;HoeflerText-Black&lt;/string&gt;
				&lt;string&gt;HoeflerText-BlackItalic&lt;/string&gt;
				&lt;string&gt;HoeflerText-Italic&lt;/string&gt;
				&lt;string&gt;HoeflerText-Regular&lt;/string&gt;
				&lt;string&gt;MarkerFelt-Thin&lt;/string&gt;
				&lt;string&gt;MarkerFelt-Wide&lt;/string&gt;
				&lt;string&gt;Optima-Bold&lt;/string&gt;
				&lt;string&gt;Optima-BoldItalic&lt;/string&gt;
				&lt;string&gt;Optima-Italic&lt;/string&gt;
				&lt;string&gt;Optima-Regular&lt;/string&gt;
				&lt;string&gt;Palatino-Bold&lt;/string&gt;
				&lt;string&gt;Palatino-BoldItalic&lt;/string&gt;
				&lt;string&gt;Palatino-Italic&lt;/string&gt;
				&lt;string&gt;Palatino-Roman&lt;/string&gt;
				&lt;string&gt;Papyrus&lt;/string&gt;
				&lt;string&gt;PartyLetPlain&lt;/string&gt;
				&lt;string&gt;STHeitiJ-Light&lt;/string&gt;
				&lt;string&gt;STHeitiJ-Medium&lt;/string&gt;
				&lt;string&gt;STHeitiK-Light&lt;/string&gt;
				&lt;string&gt;STHeitiK-Medium&lt;/string&gt;
				&lt;string&gt;STHeitiSC-Light&lt;/string&gt;
				&lt;string&gt;STHeitiSC-Medium&lt;/string&gt;
				&lt;string&gt;STHeitiTC-Light&lt;/string&gt;
				&lt;string&gt;STHeitiTC-Medium&lt;/string&gt;
				&lt;string&gt;SnellRoundhand&lt;/string&gt;
				&lt;string&gt;SnellRoundhand-Bold&lt;/string&gt;
				&lt;string&gt;Thonburi&lt;/string&gt;
				&lt;string&gt;Thonburi-Bold&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPS-BoldItalicMT&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPS-BoldMT&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPS-ItalicMT&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPSMT&lt;/string&gt;
				&lt;string&gt;Trebuchet-BoldItalic&lt;/string&gt;
				&lt;string&gt;TrebuchetMS&lt;/string&gt;
				&lt;string&gt;TrebuchetMS-Bold&lt;/string&gt;
				&lt;string&gt;TrebuchetMS-Italic&lt;/string&gt;
				&lt;string&gt;Verdana&lt;/string&gt;
				&lt;string&gt;Verdana-Bold&lt;/string&gt;
				&lt;string&gt;Verdana-BoldItalic&lt;/string&gt;
				&lt;string&gt;Verdana-Italic&lt;/string&gt;
				&lt;string&gt;ZapfDingbatsITC&lt;/string&gt;
				&lt;string&gt;Zapfino&lt;/string&gt;
			&lt;/array&gt;
			&lt;key&gt;Titles&lt;/key&gt;
			&lt;array&gt;
				&lt;string&gt;AcademyEngravedLetPlain&lt;/string&gt;
				&lt;string&gt;AmericanTypewriter&lt;/string&gt;
				&lt;string&gt;AmericanTypewriter-Bold&lt;/string&gt;
				&lt;string&gt;AppleGothic&lt;/string&gt;
				&lt;string&gt;Arial-BoldItalicMT&lt;/string&gt;
				&lt;string&gt;Arial-BoldMT&lt;/string&gt;
				&lt;string&gt;Arial-ItalicMT&lt;/string&gt;
				&lt;string&gt;ArialHebrew&lt;/string&gt;
				&lt;string&gt;ArialHebrew-Bold&lt;/string&gt;
				&lt;string&gt;ArialMT&lt;/string&gt;
				&lt;string&gt;ArialRoundedMTBold&lt;/string&gt;
				&lt;string&gt;Baskerville&lt;/string&gt;
				&lt;string&gt;Baskerville-Bold&lt;/string&gt;
				&lt;string&gt;Baskerville-BoldItalic&lt;/string&gt;
				&lt;string&gt;Baskerville-Italic&lt;/string&gt;
				&lt;string&gt;BodoniOrnamentsITCTT&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoITCTT-Bold&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoITCTT-Book&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoITCTT-BookIta&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoOSITCTT-Bold&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoOSITCTT-Book&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoOSITCTT-BookIt&lt;/string&gt;
				&lt;string&gt;BodoniSvtyTwoSCITCTT-Book&lt;/string&gt;
				&lt;string&gt;BradleyHandITCTT-Bold&lt;/string&gt;
				&lt;string&gt;Chalkduster&lt;/string&gt;
				&lt;string&gt;Cochin&lt;/string&gt;
				&lt;string&gt;Cochin-Bold&lt;/string&gt;
				&lt;string&gt;Cochin-BoldItalic&lt;/string&gt;
				&lt;string&gt;Cochin-Italic&lt;/string&gt;
				&lt;string&gt;Copperplate&lt;/string&gt;
				&lt;string&gt;Copperplate-Bold&lt;/string&gt;
				&lt;string&gt;Courier&lt;/string&gt;
				&lt;string&gt;Courier-Bold&lt;/string&gt;
				&lt;string&gt;Courier-BoldOblique&lt;/string&gt;
				&lt;string&gt;Courier-Oblique&lt;/string&gt;
				&lt;string&gt;CourierNewPS-BoldItalicMT&lt;/string&gt;
				&lt;string&gt;CourierNewPS-BoldMT&lt;/string&gt;
				&lt;string&gt;CourierNewPS-ItalicMT&lt;/string&gt;
				&lt;string&gt;CourierNewPSMT&lt;/string&gt;
				&lt;string&gt;DBLCDTempBlack&lt;/string&gt;
				&lt;string&gt;Didot&lt;/string&gt;
				&lt;string&gt;Didot-Bold&lt;/string&gt;
				&lt;string&gt;Didot-Italic&lt;/string&gt;
				&lt;string&gt;Futura-CondensedExtraBold&lt;/string&gt;
				&lt;string&gt;Futura-Medium&lt;/string&gt;
				&lt;string&gt;Futura-MediumItalic&lt;/string&gt;
				&lt;string&gt;GeezaPro&lt;/string&gt;
				&lt;string&gt;GeezaPro-Bold&lt;/string&gt;
				&lt;string&gt;Georgia&lt;/string&gt;
				&lt;string&gt;Georgia-Bold&lt;/string&gt;
				&lt;string&gt;Georgia-BoldItalic&lt;/string&gt;
				&lt;string&gt;Georgia-Italic&lt;/string&gt;
				&lt;string&gt;GillSans&lt;/string&gt;
				&lt;string&gt;GillSans-Bold&lt;/string&gt;
				&lt;string&gt;GillSans-BoldItalic&lt;/string&gt;
				&lt;string&gt;GillSans-Italic&lt;/string&gt;
				&lt;string&gt;Helvetica&lt;/string&gt;
				&lt;string&gt;Helvetica-Bold&lt;/string&gt;
				&lt;string&gt;Helvetica-BoldOblique&lt;/string&gt;
				&lt;string&gt;Helvetica-Oblique&lt;/string&gt;
				&lt;string&gt;HelveticaNeue&lt;/string&gt;
				&lt;string&gt;HelveticaNeue-Bold&lt;/string&gt;
				&lt;string&gt;HelveticaNeue-BoldItalic&lt;/string&gt;
				&lt;string&gt;HelveticaNeue-Italic&lt;/string&gt;
				&lt;string&gt;HiraKakuProN-W3&lt;/string&gt;
				&lt;string&gt;HiraKakuProN-W6&lt;/string&gt;
				&lt;string&gt;HiraMinProN-W3&lt;/string&gt;
				&lt;string&gt;HiraMinProN-W6&lt;/string&gt;
				&lt;string&gt;HoeflerText-Black&lt;/string&gt;
				&lt;string&gt;HoeflerText-BlackItalic&lt;/string&gt;
				&lt;string&gt;HoeflerText-Italic&lt;/string&gt;
				&lt;string&gt;HoeflerText-Regular&lt;/string&gt;
				&lt;string&gt;MarkerFelt-Thin&lt;/string&gt;
				&lt;string&gt;MarkerFelt-Wide&lt;/string&gt;
				&lt;string&gt;Optima-Bold&lt;/string&gt;
				&lt;string&gt;Optima-BoldItalic&lt;/string&gt;
				&lt;string&gt;Optima-Italic&lt;/string&gt;
				&lt;string&gt;Optima-Regular&lt;/string&gt;
				&lt;string&gt;Palatino-Bold&lt;/string&gt;
				&lt;string&gt;Palatino-BoldItalic&lt;/string&gt;
				&lt;string&gt;Palatino-Italic&lt;/string&gt;
				&lt;string&gt;Palatino-Roman&lt;/string&gt;
				&lt;string&gt;Papyrus&lt;/string&gt;
				&lt;string&gt;PartyLetPlain&lt;/string&gt;
				&lt;string&gt;STHeitiJ-Light&lt;/string&gt;
				&lt;string&gt;STHeitiJ-Medium&lt;/string&gt;
				&lt;string&gt;STHeitiK-Light&lt;/string&gt;
				&lt;string&gt;STHeitiK-Medium&lt;/string&gt;
				&lt;string&gt;STHeitiSC-Light&lt;/string&gt;
				&lt;string&gt;STHeitiSC-Medium&lt;/string&gt;
				&lt;string&gt;STHeitiTC-Light&lt;/string&gt;
				&lt;string&gt;STHeitiTC-Medium&lt;/string&gt;
				&lt;string&gt;SnellRoundhand&lt;/string&gt;
				&lt;string&gt;SnellRoundhand-Bold&lt;/string&gt;
				&lt;string&gt;Thonburi&lt;/string&gt;
				&lt;string&gt;Thonburi-Bold&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPS-BoldItalicMT&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPS-BoldMT&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPS-ItalicMT&lt;/string&gt;
				&lt;string&gt;TimesNewRomanPSMT&lt;/string&gt;
				&lt;string&gt;Trebuchet-BoldItalic&lt;/string&gt;
				&lt;string&gt;TrebuchetMS&lt;/string&gt;
				&lt;string&gt;TrebuchetMS-Bold&lt;/string&gt;
				&lt;string&gt;TrebuchetMS-Italic&lt;/string&gt;
				&lt;string&gt;Verdana&lt;/string&gt;
				&lt;string&gt;Verdana-Bold&lt;/string&gt;
				&lt;string&gt;Verdana-BoldItalic&lt;/string&gt;
				&lt;string&gt;Verdana-Italic&lt;/string&gt;
				&lt;string&gt;ZapfDingbatsITC&lt;/string&gt;
				&lt;string&gt;Zapfino&lt;/string&gt;
			&lt;/array&gt;
		&lt;/dict&gt;
		&lt;dict&gt;
			&lt;key&gt;Type&lt;/key&gt;
			&lt;string&gt;PSMultiValueSpecifier&lt;/string&gt;
			&lt;key&gt;Title&lt;/key&gt;
			&lt;string&gt;Font Size&lt;/string&gt;
			&lt;key&gt;Key&lt;/key&gt;
			&lt;string&gt;fontSize&lt;/string&gt;
			&lt;key&gt;DefaultValue&lt;/key&gt;
			&lt;integer&gt;16&lt;/integer&gt;
			&lt;key&gt;Values&lt;/key&gt;
			&lt;array&gt;
				&lt;integer&gt;10&lt;/integer&gt;
				&lt;integer&gt;12&lt;/integer&gt;
				&lt;integer&gt;14&lt;/integer&gt;
				&lt;integer&gt;16&lt;/integer&gt;
				&lt;integer&gt;18&lt;/integer&gt;
				&lt;integer&gt;20&lt;/integer&gt;
				&lt;integer&gt;22&lt;/integer&gt;
				&lt;integer&gt;24&lt;/integer&gt;
				&lt;integer&gt;26&lt;/integer&gt;
				&lt;integer&gt;28&lt;/integer&gt;
				&lt;integer&gt;30&lt;/integer&gt;
				&lt;integer&gt;32&lt;/integer&gt;
				&lt;integer&gt;34&lt;/integer&gt;
				&lt;integer&gt;36&lt;/integer&gt;
				&lt;integer&gt;38&lt;/integer&gt;
				&lt;integer&gt;40&lt;/integer&gt;
				&lt;integer&gt;42&lt;/integer&gt;
				&lt;integer&gt;44&lt;/integer&gt;
				&lt;integer&gt;46&lt;/integer&gt;
				&lt;integer&gt;48&lt;/integer&gt;
				&lt;integer&gt;50&lt;/integer&gt;
			&lt;/array&gt;
			&lt;key&gt;Titles&lt;/key&gt;
			&lt;array&gt;
				&lt;string&gt;10&lt;/string&gt;
				&lt;string&gt;12&lt;/string&gt;
				&lt;string&gt;14&lt;/string&gt;
				&lt;string&gt;16&lt;/string&gt;
				&lt;string&gt;18&lt;/string&gt;
				&lt;string&gt;20&lt;/string&gt;
				&lt;string&gt;22&lt;/string&gt;
				&lt;string&gt;24&lt;/string&gt;
				&lt;string&gt;26&lt;/string&gt;
				&lt;string&gt;28&lt;/string&gt;
				&lt;string&gt;30&lt;/string&gt;
				&lt;string&gt;32&lt;/string&gt;
				&lt;string&gt;34&lt;/string&gt;
				&lt;string&gt;36&lt;/string&gt;
				&lt;string&gt;38&lt;/string&gt;
				&lt;string&gt;40&lt;/string&gt;
				&lt;string&gt;42&lt;/string&gt;
				&lt;string&gt;44&lt;/string&gt;
				&lt;string&gt;46&lt;/string&gt;
				&lt;string&gt;48&lt;/string&gt;
				&lt;string&gt;50&lt;/string&gt;
			&lt;/array&gt;
		&lt;/dict&gt;
	&lt;/array&gt;
&lt;/dict&gt;
&lt;/plist&gt;</code></pre>
<p>ここまでで自動的に設定画面ができちゃいます。<br />
<img src="http://file.blog.bornneet.com/ipad4_settingview.png" alt="設定画面" />
</p>

<h3>2. 設定変更の実装</h3>
<p>さっき作った画面で設定した内容をアプリに反映させます。<br />
今回の設定は全てTextViewに関するものなので、<br />
DetailControllerのinit内で以下のように読み込み・設定しています。</p>
<pre class="source syntax brush-clang"><code>		NSUserDefaults* settings = [NSUserDefaults standardUserDefaults];

		// defaultを設定してもnullが返ってくるので、0やNOがdefaultじゃない場合処理が必要。
		NSInteger textColor = [settings integerForKey:@"textColor"];
		NSInteger backgroundColor = [settings objectForKey: @"backgroundColor"] != NULL ? [settings integerForKey:@"backgroundColor"] : 3;
		NSString *fontName = [settings objectForKey: @"fontName"] != NULL ? [settings stringForKey:@"fontName"] : @"Helvetica";
		NSInteger fontSize = [settings objectForKey: @"fontSize"] != NULL ? [settings integerForKey:@"fontSize"] : 16;
				
		textView_.font = [UIFont fontWithName:fontName size:fontSize];
		textView_.textColor = [self getColorWithIndex:textColor];
		textView_.backgroundColor = [self getColorWithIndex:backgroundColor];</code></pre>

<h3>[完成]</h3>
<p>できました。<br />
<img src="http://file.blog.bornneet.com/ipad4_setted.png" alt="設定反映後" />
</p>

<h3>[まとめ]</h3>
<p>
これで目を凝らして小さい字を読まなくても良くなりました。<br />
今回は簡単だったので、次はもうちょっとプログラミングらしいことをやろうと思います。</p>

<h3>[コード]</h3>
<p>今回のコードは「Edhita4.zip」に入っています。<br />
GitHubのdownloadページからダウンロードして下さい。<br />
<br />
<a href="http://github.com/tnantoka/Edhita/downloads" class="external" target="_blank" title="新しいウィンドウで開きます">Downloads for tnantoka's Edhita - GitHub</a></p>
]]>
			</description>
			<link>http://blog.bornneet.com/Entry/290/</link>
			<pubDate>Sun, 29 Aug 2010 06:14:08 GMT</pubDate>
		</item>
		<item>
			<title>IB不使用＆オープンソースなiPadアプリ（テキストエディタ）を作る 第3回：ファイル操作とNavigationController、TableView</title>
			<description>
			<![CDATA[<p>
第3回。
今回はTableVIew＆NavigationControllerでのファイル操作、<br />
TextViewでの内容表示などなどを実装します。<br />
ようやくテキストエディタな機能がつくわけですね。<br />
<br />
それでは早速始めます。<br />
<br />
ちょっと規模も大きくなってきたのでソースをベタ貼りするのはやめて、<br />
ポイントだけに絞ってます。<br />
また、<a href="http://www.oriontransfer.co.nz/software/jquery-syntax/index.en" class="external" target="_blank" title="新しいウィンドウで開きます">jQuery.Syntax</a>を使ってコードを見やすくしてみました。
</p>
<h3>参考</h3>
<p>今回は結構いじったので、参考にさせていただいたサイトもたくさんあります。<br />
ありがとうございました。<br />
なお、参考書籍は<a href="http://blog.bornneet.com/Entry/287/">第1回</a>をご参照下さい。<br />
</p>
<ul>
	<li><a href="http://blog.dataich.com/2010/04/06/dont-want-hide-uitextview-behind-keyboard/" class="external" target="_blank" title="新しいウィンドウで開きます">画面いっぱいのUITextViewがキーボードに隠れないようにする</a><br />
iphoneの時やってた方法が非推奨になったので。<br />
そろそろkeyboard表示時のサイズ変更はデフォルトで提供して欲しいなぁ。<br />
（どうやらPopOverはそうなってるみたいだから期待できそうだけど。）</li>
	<li><a href="http://blog.livedoor.jp/faulist/archives/1511657.html" class="external" target="_blank" title="新しいウィンドウで開きます">iPadでキーボードの表示に合わせたViewのサイズ変更 - As Sloth As Possible</a><br />
日本語キーボードは変換候補表示領域があるのでますますややこしい。</li>
	<li><a href="http://fukuoka-m.g.hatena.ne.jp/m-hashimoto/20100209/1265733213" class="external" target="_blank" title="新しいウィンドウで開きます">UITableViewStyleGroupedなUITableViewControllerで設定画面 - hashimoto.m - fukuoka.m</a><br />
ファイル情報表示の際に大いに参考にさせていただきました。</li>
</ul>
<h3>素材</h3>
<p>今回から、フォルダとファイルの画像を使用しています。<br />
この素材はいつもお世話になっている、<a href="http://snow.if.tv/" class="external" target="_blank" title="新しいウィンドウで開きます">Soft * Accessory</a>様にお借りしました。<br />
ハイクオリティな上に非常に緩い使用条件で素晴らしいです。</p>
<h3>1. ファイル・ディレクトリの作成・削除</h3>
<p>NavigationControllerのToolbarにボタンを表示して、<br />
ファイル・ディレクトリの作成機能を付けます。<br />
また、削除はTableViewの編集機能で行ないます。</p>
<h4>Toolbarの表示（EdhitaNavigationController.m）</h4>
<p>NavigationControllerのサブクラス、EdhitaNavigationControllerで行ないます。<br />
※ TableViewController側でやるとうまくいきませんでした。<br />
initでtoolbarHiddenを設定するだけです。</p>
<pre class="source syntax brush-clang"><code>- (id)init {
	if (self = [super init]) {
		self.toolbarHidden = NO;
		// sizeToFitしないとportraitで起動したとき、popover内で表示されない。
		[self.toolbar sizeToFit];
	}
	return self;
}</code></pre>
<h4>作成・編集ボタンの表示（RootViewController.m）</h4>
<p>先程表示したToolbarにファイル・ディレクトリ作成ボタンを追加します。<br />
これはTableViewのサブクラスであるRootViewControllerのinitで設定します。<br />
※ NavigationControllerでやってもうまくいきません。<br />
<br />
また編集ボタンはNavigationBarの右に表示します。<br />
この仕組みは標準で提供されており、<br />
rightButtonItemにeditButtonItemを設定するだけです。</p>
<pre class="source syntax brush-clang"><code>		// 画像ボタンを2個作って、それぞれファイル・ディレクトリの作成用のボタンとする
		UIImage* fileImage = [UIImage imageNamed:@"file.png"];
		UIImage* dirImage = [UIImage imageNamed:@"dir.png"];
		images_ = [[NSArray arrayWithObjects:fileImage, dirImage, nil] retain];

		// 右寄せ
		UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
		
		UIBarButtonItem *newFile  = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"file_new.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(newFileDidPush)];
		UIBarButtonItem *newDir  = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"dir_new.png"] style:UIBarButtonItemStyleBordered target:self action:@selector(newDirDidPush)];

		NSArray *items = [NSArray arrayWithObjects:space, newFile, newDir, nil];
		[self setToolbarItems:items];

		// 編集ボタンの表示（selfのeditButtonを設定してやるだけでいい）
		self.navigationItem.rightBarButtonItem = [self editButtonItem];
</code></pre>
<p>
こうなります。<br />
<img src="http://file.blog.bornneet.com/ipad3_button.png" alt="ボタンの表示" />
</p>
<h4>作成・削除処理（RootViewController.m）</h4>
<p>Toolbarに追加したbuttonのactionに指定したメソッドでファイル・ディレクトリの作成を行ないます。<br />
<br />
これはMSFileManagerの機能を使います。<br />
削除は、呼び出しがボタン押下時ではなく、<br />
TableViewを編集モードにしてCellが削除された時になります。</p>
<pre class="source syntax brush-clang"><code>// 新しいファイルの作成
- (void)newFileDidPush {
	
	NSError *error;

	// 連番のファイル名を取得
	NSString *fileName = [self nextFileName:@"untitled file"];
	NSString *fileContents = @"testあいうえお";

	NSString *filePath = [path_ stringByAppendingPathComponent:fileName];
	[fileContents writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];

	[items_ addObject:fileName];
	[self.tableView reloadData];
}

// 新しいディレクトリの作成
- (void)newDirDidPush {

	NSError *error;
	
	// 連番のディレクトリ名を取得
	NSString *dirName = [self nextFileName:@"untitled folder"];

	NSString *dirPath = [path_ stringByAppendingPathComponent:dirName];
	[[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:NO attributes:nil error:&error];
	
	[items_ addObject:dirName];
	[self.tableView reloadData];
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    
	// Cellが削除された時、ファイルとitemsからも削除する
    if (editingStyle == UITableViewCellEditingStyleDelete) {
		
		NSString *path = [path_ stringByAppendingPathComponent:[items_ objectAtIndex:indexPath.row]];
		NSError* error;
		
		[[NSFileManager defaultManager] removeItemAtPath:path error:&error];
		
		// 配列からも消さないと落ちる
		[items_ removeObjectAtIndex:indexPath.row];
		
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
/*
	else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }
*/
}</code></pre>
<h3>2. ファイルブラウジング</h3>
<p>新規作成したディレクトリをTableViewからアクセスして、<br />
ファイルをDetailViewControllerに追加したTextViewで表示します。</p>
<h4>ディレクトリ アクセス</h4>
<p>Cell選択時にディレクトリだった場合、新たにRootViewControllerを作成し、<br />
NavigationControllerにPushします。</p>
<pre class="source syntax brush-clang"><code>- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    /*
     When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
     */
 //   detailViewController.detailItem = [NSString stringWithFormat:@"Row %d", indexPath.row];
	
	NSString *path = [path_ stringByAppendingPathComponent:[items_ objectAtIndex:indexPath.row]];

	BOOL isDir;

	[[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDir];

	// ディレクトリだった場合、そのPathを設定したRootViewControllerを作成
	if (isDir) {		
		RootViewController *rootViewController = [[RootViewController alloc] initWithPath:path];
		// detailはrootがもつ必要ないんじゃ？（navあたりに持たせればいい）
		rootViewController.detailViewController = self.detailViewController;
		[self.navigationController pushViewController:rootViewController animated:YES];
	}</code></pre>
<h4>ファイル表示（RootViewController.m, DetailViewController.m）</h4>
<p>選択されたのがファイルだった場合は、DetailViewControllerに追加したTextViewに表示します。</p>
<pre class="source syntax brush-clang"><code>// RootViewController.m

	// ファイルだった場合はDetailに内容を表示
	else {
		detailViewController.path = path;		
	}
</code></pre>
<pre class="source syntax brush-clang"><code>// DetailViewController.m

// pathプロパティが変化した時にTextViewの内容を変更する
- (void)setPath:(NSString *)path {
	
	[self saveContents];

	path_ = [path retain];
	NSError *error;
	textView_.text = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
}</code></pre>

<p>こうなります。<br />
説明は省略しましたが、アイコンもつけています。<br />
<img src="http://file.blog.bornneet.com/ipad3_browse.png" alt="ファイルブラウズ" /></p>
<h3>3. ファイル情報の表示・名前の変更</h3>
<p>最後におまけ的な機能ですが、ファイル更新日・サイズの表示と、<br />
ファイル名変更機能を追加します。<br />
<h4>ファイル情報画面の呼び出し（RootViewController.m）</h4>
<p>ファイル情報画面の表示はCellのアクセサリボタンのタップで行ないます。</p>
<pre class="source syntax brush-clang"><code>// アクセサリボタンがタップされた時はファイル情報表示画面に遷移する
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {

	NSString *path = [path_ stringByAppendingPathComponent: [items_ objectAtIndex:indexPath.row]];
	EdhitaTableViewController *tableViewController = [[EdhitaTableViewController alloc] initWithPath:path];
	[self.navigationController pushViewController:tableViewController animated:YES];
	[tableViewController release];	
}</code></pre>
<h4>ファイル情報表示・名前変更（EdhitaTableViewController.m）</h4>
<p>情報の表示とファイル名の変更は新たに作成した、<br />
EdhitaTableViewControllerで実装します。<br />
RenameはMSFileManagerのMove機能を使います。</p>
<pre class="source syntax brush-clang"><code>// ファイル情報をCellに表示する。
// かなり汚いのでリファクタリング必要
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
		cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
		cell.selectionStyle = UITableViewCellSelectionStyleNone;
    }

	// Configure the cell...
	cell.textLabel.text = [items_ objectAtIndex:indexPath.row];
	
	
	NSError *error;
	NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path_ error:&error];
	
	// switch内では変数宣言できないからif文の方が楽。
    if (indexPath.row == 0) {
		textField_ = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.size.width * 0.3, 0, cell.frame.size.width * 0.6, cell.frame.size.height)];
		textField_.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
		textField_.textAlignment = UITextAlignmentRight;
		textField_.delegate = self;
		textField_.text = [path_ lastPathComponent];
		textField_.returnKeyType = UIReturnKeyDone;
		textField_.clearButtonMode = UITextFieldViewModeWhileEditing;
		[textField_ becomeFirstResponder];		
		[cell.contentView addSubview:textField_];
	}
	else {
		UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(cell.frame.size.width * 0.3, 0, cell.frame.size.width * 0.6, cell.frame.size.height)];
		label.textAlignment = UITextAlignmentRight;
		label.backgroundColor = [UIColor clearColor];
		[cell.contentView addSubview:label];

		if(indexPath.row == 1) {
// timezoneが入ってくるので却下
//			textField.text = [[attributes objectForKey:NSFileModificationDate] description];
//			textField.text = [[attributes objectForKey:NSFileModificationDate] descriptionWithLocale:nil];

// documentに載ってるくせに。
//			textField.text = [[attributes objectForKey:NSFileModificationDate] descriptionWithCalendarFormat:@"%Y-%m-%d %H:%M:%S" timeZone:nil locale:nil];

			NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
			[dateFormatter setDateFormat:@"Y-MM-dd HH:mm:ss"];
			label.text = [dateFormatter stringFromDate:[attributes objectForKey:NSFileModificationDate]];						
		}
		else if(indexPath.row == 2) {
			label.text = [NSString stringWithFormat:@"%@ bytes", [attributes objectForKey:NSFileSize]];
		}
	}

    return cell;
}


// ファイル名変更（textField編集完了時と、Viewの非表示化の際に呼ばれる）
- (void)renameFile {
	NSError *error;
	NSString *dstPath = [[path_ stringByDeletingLastPathComponent] stringByAppendingPathComponent:textField_.text];
	[[NSFileManager defaultManager] moveItemAtPath:path_ toPath:dstPath error:&error];
}</code></pre>

<h3>完成</h3>
<p>
できました。
<img src="http://file.blog.bornneet.com/ipad3_info.png" alt="ファイル情報" />
<br />
</p>

<h3>[まとめ]</h3>
<p>
これで最低限のテキストエディタ機能はできました。<br />
次回はいよいよSyntax Highlightです。<br />
（まだどうやればいいか、検討もついてませんが。）<br />
<br />
その前に、細かいバグ潰しをやらないとなぁ…。
</p>

<h3>[コード]</h3>
<p>今回のコードは「Edhita3.zip」に入っています。<br />
GitHubのdownloadページからダウンロードして下さい。<br />
<br />
<a href="http://github.com/tnantoka/Edhita/downloads" class="external" target="_blank" title="新しいウィンドウで開きます">Downloads for tnantoka's Edhita - GitHub</a></p>]]>
			</description>
			<link>http://blog.bornneet.com/Entry/289/</link>
			<pubDate>Sun, 22 Aug 2010 15:51:32 GMT</pubDate>
		</item>
		<item>
			<title>IB不使用＆オープンソースなiPadアプリ（テキストエディタ）を作る 第2回：SplitView</title>
			<description>
			<![CDATA[<p>
第2回です。<br />
<br />
今回はSplitViewを作ります。iPadアプリなUIといえばこれですね。<br />
※ ちなみに、IBを使えば新規プロジェクトでSplitVIew basedを選ぶだけで終わりです。<br />
<br />
作るのは2ペインの単純なアプリ。<br />
左ペインで選んだ文字列を、右ペインに表示するだけです。<br />
（Portraitモードの時は1ペインにして、代わりにPopViewを使用します）<br />
まだテキストエディタとしての機能はありません。<br />
<br />
それでは早速始めます。
</p>
<h3>[参考文献]</h3>
<p>今回の参考サイトは以下のとおり。<br />
参考書籍は<a href="http://blog.bornneet.com/Entry/287/">第1回</a>をご参照下さい。<br />
<br />
<a href="http://clsmooth.wordpress.com/2010/07/04/ipad%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9Fuisplitview%E3%82%92%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/" class="external" target="_blank" title="新しいウィンドウで開きます">iPadで追加されたUISplitViewを試してみる « CLSmooth BLOG…</a></p>


<h3>RootViewController</h3>
<p>まずはleft paneとなるRootViewControllerを作ります。<br />
と言っても特別なことはしておらず、何の変哲もないTableViewControllerです。</p>
<h4>RootViewController.h</h4>
<p>ヘッダファイルはこんな感じです。</p>
<pre class="source"><code>#import <UIKit/UIKit.h>

@class DetailViewController;

@interface RootViewController : UITableViewController {
    DetailViewController *detailViewController;
}

<strong>//@property (nonatomic, retain) IBOutlet DetailViewController *detailViewController;
@property (nonatomic, retain) DetailViewController *detailViewController;</strong>

@end</code></pre>
<h4>RootViewController.m</h4>
<p>お次は実装ファイル。</p>
<pre class="source"><code>#import "RootViewController.h"
#import "DetailViewController.h"


@implementation RootViewController

@synthesize detailViewController;


#pragma mark -
#pragma mark View lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    self.clearsSelectionOnViewWillAppear = NO;
    self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
}

/*
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}
*/

// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}


#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return 10;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *CellIdentifier = @"CellIdentifier";
    
    // Dequeue or create a cell of the appropriate type.
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryNone;
    }
    
    // Configure the cell.
    cell.textLabel.text = [NSString stringWithFormat:@"Row %d", indexPath.row];
    return cell;
}


/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/


/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/


/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}
*/


/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/


#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    /*
     When a row is selected, set the detail view controller's detail item to the item associated with the selected row.
     */
    detailViewController.detailItem = [NSString stringWithFormat:@"Row %d", indexPath.row];
}


#pragma mark -
#pragma mark Memory management

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Relinquish ownership any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload {
    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}


- (void)dealloc {
    [detailViewController release];
    [super dealloc];
}


@end</code></pre>
<p>もうお気づきかもしれませんが、IBでSplitVIew basedを選択した時に自動作成されるファイルを流用しています。<br />
プロな方はどうか知りませんが、少なくとも僕はこんな内容を一から書くスキルも元気もありません。<br />
というわけで、太字部分以外はそのままです。<br />
（つまりヘッダファイルのプロパティからIBOutletを削っただけ）</p>

<h3>DetailViewController</h3>
<p>次にright paneとなる、DetailVIewControllerです。<br />
見た目は単なるToolbar付きViewControllerですが、<br />
UISplitViewControllerのDelegteとなっており、<br />
画面が回転した際、ToolbarにPopover用のボタンを追加・削除する機能を持ちます。<br />
</p>
<h4>DetailViewController.h</h4>
<p>まずはヘッダファイル。rootview同様、IBOutletを消すだけです。</p>
<pre class="source"><code>#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController <UIPopoverControllerDelegate, UISplitViewControllerDelegate> {
    
    UIPopoverController *popoverController;
    UIToolbar *toolbar;
    
    id detailItem;
    UILabel *detailDescriptionLabel;
}

<strong>//@property (nonatomic, retain) IBOutlet UIToolbar *toolbar;
@property (nonatomic, retain) UIToolbar *toolbar;</strong>

@property (nonatomic, retain) id detailItem;
<strong>//@property (nonatomic, retain) IBOutlet UILabel *detailDescriptionLabel;
@property (nonatomic, retain) UILabel *detailDescriptionLabel;</strong>

@end</code></pre>
<h4>DetailViewController.m</h4>
<p>次に実装。長いですが、最後にinitメソッドを追加して、<br />
IBの代わりにtoolbar、labelを作成しているだけです。</p>
<pre class="source"><code>#import "DetailViewController.h"
#import "RootViewController.h"


@interface DetailViewController ()
@property (nonatomic, retain) UIPopoverController *popoverController;
- (void)configureView;
@end



@implementation DetailViewController

@synthesize toolbar, popoverController, detailItem, detailDescriptionLabel;

#pragma mark -
#pragma mark Managing the detail item

/*
 When setting the detail item, update the view and dismiss the popover controller if it's showing.
 */
- (void)setDetailItem:(id)newDetailItem {
    if (detailItem != newDetailItem) {
        [detailItem release];
        detailItem = [newDetailItem retain];
        
        // Update the view.
        [self configureView];
    }

    if (popoverController != nil) {
        [popoverController dismissPopoverAnimated:YES];
    }        
}


- (void)configureView {
    // Update the user interface for the detail item.
    detailDescriptionLabel.text = [detailItem description];   
}


#pragma mark -
#pragma mark Split view support

- (void)splitViewController: (UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {

    barButtonItem.title = @"Root List";
    NSMutableArray *items = [[toolbar items] mutableCopy];
    [items insertObject:barButtonItem atIndex:0];
    [toolbar setItems:items animated:YES];
    [items release];
    self.popoverController = pc;
}


// Called when the view is shown again in the split view, invalidating the button and popover controller.
- (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
    
    NSMutableArray *items = [[toolbar items] mutableCopy];
    [items removeObjectAtIndex:0];
    [toolbar setItems:items animated:YES];
    [items release];
    self.popoverController = nil;
}


#pragma mark -
#pragma mark Rotation support

// Ensure that the view controller supports rotation and that the split view can therefore show in both portrait and landscape.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}


#pragma mark -
#pragma mark View lifecycle

/*
 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
}
 */

/*
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}
*/

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.popoverController = nil;
}


#pragma mark -
#pragma mark Memory management

/*
- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}
*/

- (void)dealloc {
    [popoverController release];
    [toolbar release];
    
    [detailItem release];
    [detailDescriptionLabel release];
    [super dealloc];
}

<strong>- (id)init {
	if (self = [super init]) {
		self.view.backgroundColor = [UIColor whiteColor];
		
		toolbar = [[UIToolbar alloc] init];
		[toolbar sizeToFit];		
		[self.view addSubview:toolbar];
		// これやっとかないとpopview出すボタンが追加できない（[toolbar items]がnullになるから）
		[toolbar setItems: [NSArray array]];
		
		// heightはdefaultのfontsizeに合わせて17
		detailDescriptionLabel = [[UILabel alloc] initWithFrame: CGRectMake(0, self.view.bounds.size.height * 0.5, self.view.bounds.size.width, 17)];
		// 常に上下中央
		detailDescriptionLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
		detailDescriptionLabel.textAlignment = UITextAlignmentCenter;

		detailDescriptionLabel.text = @"Detail view content goes here";
		[self.view addSubview:detailDescriptionLabel];		
	}
	return self;
}</strong>

@end</code></pre>

<h3>AppDelegate</h3>
<p>最後にAppDelegate。<br />
実はこいつが一番修正が多かったりする。<br />
（太字が前回からの修正点）</p>
<h4>AppDelegate.h</h4>
<p>rootとdetailのヘッダファイルをimport。</p>
<pre class="source"><code>#import <UIKit/UIKit.h>

<strong>#import "RootViewController.h"
#import "DetailViewController.h"</strong>

@interface EdhitaAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
}

//@property (nonatomic, retain) IBOutlet UIWindow *window;

@end</code></pre>
<h4>AppDelegate.m</h4>
<p>前回はwindowにlabelを突っ込んでたけど、<br />
今回はrootとdetailをもとにSplitViewを作成。<br />
※ rootはNavigationControllerのrootとして設定</p>
<pre class="source"><code>#import "EdhitaAppDelegate.h"

@implementation EdhitaAppDelegate

// @synthesize window;


#pragma mark -
#pragma mark Application lifecycle

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
	
    // Override point for customization after application launch.
	
	window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

<strong>	RootViewController *rootViewController = [[RootViewController alloc] init];
	// tableview単体じゃ仕方ないのでnavviewでwrap
	UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
	
	DetailViewController *detailViewController = [[DetailViewController alloc] init];

	rootViewController.detailViewController = detailViewController;

	UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
	splitViewController.viewControllers = [NSArray arrayWithObjects:navigationController, detailViewController, nil];
	splitViewController.delegate = detailViewController;
	
	[window addSubview:splitViewController.view];
	[rootViewController release];
	[navigationController release];
	[detailViewController release];</strong>
	
    [window makeKeyAndVisible];
	
	return YES;
}


- (void)applicationWillResignActive:(UIApplication *)application {
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive.
     */
}


- (void)applicationWillTerminate:(UIApplication *)application {
    /*
     Called when the application is about to terminate.
     */
}


#pragma mark -
#pragma mark Memory management

- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
    /*
     Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
     */
}


- (void)dealloc {
    [window release];
    [super dealloc];
}


@end</code></pre>

<h3>完成</h3>
<p>
<img src="http://file.blog.bornneet.com/ipad2_landscape.png" alt="landscapeモード" /><br />
<img src="http://file.blog.bornneet.com/ipad2_portrait.png" alt="poatraitモード" /><br />
</p>

<h3>[まとめ]</h3>
<p>
第2回目の今回は単純なSplitViewアプリを作ってみました。<br />
ようやくIBでSplitViewプロジェクトを作成したものに追いついたわけですね。<br />
<br />
次回以降いよいよテキストエディタの機能を追加していきます。<br />
ご期待下さい。
</p>

<h3>[コード]</h3>
<p>今回のコードは「Edhita2.zip」に入っています。<br />
GitHubのdownloadページからダウンロードして下さい。<br />
<br />
<a href="http://github.com/tnantoka/Edhita/downloads" class="external" target="_blank" title="新しいウィンドウで開きます">Downloads for tnantoka's Edhita - GitHub</a></p>]]>
			</description>
			<link>http://blog.bornneet.com/Entry/288/</link>
			<pubDate>Sun, 15 Aug 2010 06:56:47 GMT</pubDate>
		</item>
		<item>
			<title>IB不使用＆オープンソースなiPadアプリ（テキストエディタ）を作る 第1回：プロジェクトの作成</title>
			<description>
			<![CDATA[<p>
3月にv1.0、7月にv1.5(.1)を公開した<a href="http://jsany.org/">jsany</a>ですが、<br />
たくさんの方に使っていただいているようで、嬉しい限りです。<br />
<br />
ただ、何もわかってない頃に作り始めたこともあり、こいつの内部実装はもうぐちゃぐちゃです。<br />
その結果、1.5で重大なバグを出してしまい、すぐ1.5.1を出すハメになりました。<br />
<br />
このままいくといずれ破綻しそうなので、<br />
オープンソースなアプリで腕を磨いて、改めてObjective-Cを勉強しなおしたいと思います。<br />
<br />
題材はテキストエディタ、名前はまんまですが「edhita」です。<br />
中身を深く理解する為、IBは使用しません。<br />
また、ソースコードは全てgithubで公開します。<br />
<br />
このアプリ作成で得たノウハウをjsanyにFeedbackしていこうという魂胆です。<br />
※ ホントはjsanyをオープンソースにしたいんですが、<br />
　今のコードは恥ずかしすぎてとても晒せないので。<br />
　（ただでさえ高くないプログラマとしての評判がガタ落ちしちゃいます）<br />
<br />
では、始めます。<br />
初回はIB不使用なiPadアプリプロジェクトを作成するところまでやります。
</p>
<h3>[参考書籍]</h3>
<p>と、その前に参考にした書籍を紹介しておきます。<br />
他に参考にした情報があれば、それぞれの回で記載します。</p>

<div class="hreview" ><a class="item url" href="http://www.amazon.co.jp/iPhone%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0UIKit%E8%A9%B3%E8%A7%A3%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-%E6%89%80-%E5%8F%8B%E5%A4%AA/dp/4897978440%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4897978440"><img src="http://ecx.images-amazon.com/images/I/51VKXcaczAL._SL160_.jpg" alt="photo" class="photo" style="float:left; margin: 0 15px 10px 10px; padding: 0;border:none;" /></a><dl style="margin-bottom:0.5em; text-align:left; min-height: 168px;font-size:12px;line-height:16px;"><dt class="fn"><a class="item url" href="http://www.amazon.co.jp/iPhone%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0UIKit%E8%A9%B3%E8%A7%A3%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9-%E6%89%80-%E5%8F%8B%E5%A4%AA/dp/4897978440%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4897978440">iPhoneプログラミングUIKit詳解リファレンス</a><img src="http://www.assoc-amazon.jp/e/ir?t=bornneet-22&l=ur2&o=9" width="1" height="1" style="border: none;" alt="" /></dt><dd>所 友太 京セラコミュニケーションシステム株式会社 </dd><dd>リックテレコム 2010-01-12</dd></dl><p class="gtools" style="font-size:10px;">by <a href="http://www.goodpic.com/mt/aws/index.html" >G-Tools</a> ,  <abbr class="dtreviewed" title="2010/08/08">2010/08/08</abbr></p></div>

<div class="hreview" ><a class="item url" href="http://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Objective-C-2-0-%E8%8D%BB%E5%8E%9F-%E5%89%9B%E5%BF%97/dp/4797346809%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4797346809"><img src="http://ecx.images-amazon.com/images/I/41xicvv7UEL._SL160_.jpg" alt="photo" class="photo" style="float:left; margin: 0 15px 10px 10px; padding: 0;border:none;" /></a><dl style="margin-bottom:0.5em; text-align:left; min-height: 168px;font-size:12px;line-height:16px;"><dt class="fn"><a class="item url" href="http://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3-Objective-C-2-0-%E8%8D%BB%E5%8E%9F-%E5%89%9B%E5%BF%97/dp/4797346809%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4797346809">詳解 Objective-C 2.0</a><img src="http://www.assoc-amazon.jp/e/ir?t=bornneet-22&l=ur2&o=9" width="1" height="1" style="border: none;" alt="" /></dt><dd>荻原 剛志 </dd><dd>ソフトバンククリエイティブ 2008-05-28</dd></dl><p class="gtools" style="font-size:10px;">by <a href="http://www.goodpic.com/mt/aws/index.html" >G-Tools</a> ,  <abbr class="dtreviewed" title="2010/08/08">2010/08/08</abbr></p></div>
<div class="hreview" ><a class="item url" href="http://www.amazon.co.jp/iPad%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E4%BD%9C%E6%B3%95-%E6%A9%8B%E6%9C%AC%E4%BD%B3%E5%B9%B8/dp/4798026417%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798026417"><img src="http://ecx.images-amazon.com/images/I/31SRip0nOrL._SL160_.jpg" alt="photo" class="photo" style="float:left; margin: 0 15px 10px 10px; padding: 0;border:none;" /></a><dl style="margin-bottom:0.5em; text-align:left; min-height: 168px;font-size:12px;line-height:16px;"><dt class="fn"><a class="item url" href="http://www.amazon.co.jp/iPad%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AE%E4%BD%9C%E6%B3%95-%E6%A9%8B%E6%9C%AC%E4%BD%B3%E5%B9%B8/dp/4798026417%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D4798026417">iPadプログラミングの作法</a><img src="http://www.assoc-amazon.jp/e/ir?t=bornneet-22&l=ur2&o=9" width="1" height="1" style="border: none;" alt="" /></dt><dd>橋本佳幸 </dd><dd>秀和システム 2010-06-15</dd></dl><p class="gtools" style="font-size:10px;">by <a href="http://www.goodpic.com/mt/aws/index.html" >G-Tools</a> ,  <abbr class="dtreviewed" title="2010/08/08">2010/08/08</abbr></p></div>
<table  border="0" cellpadding="5"><tr><td colspan="2"><a href="http://www.amazon.co.jp/Software-Design-%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2-%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-2010%E5%B9%B4/dp/B003U4GQEC%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB003U4GQEC" target="_blank">Software Design (ソフトウェア デザイン) 2010年 08月号 [雑誌]</a><img src="http://www.assoc-amazon.jp/e/ir?t=bornneet-22&l=ur2&o=9" width="1" height="1" style="border: none;" alt="" /></td></tr><tr><td valign="top"><a href="http://www.amazon.co.jp/Software-Design-%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2-%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-2010%E5%B9%B4/dp/B003U4GQEC%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB003U4GQEC" target="_blank"><img src="http://ecx.images-amazon.com/images/I/515GiuiEMYL._SL160_.jpg" border="0" alt="Software Design (ソフトウェア デザイン) 2010年 08月号 [雑誌]" /></a></td><td valign="top"><font size="-1"><br />技術評論社  2010-07-17<br />売り上げランキング : <br /><br /><br /><a href="http://www.amazon.co.jp/Software-Design-%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2-%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-2010%E5%B9%B4/dp/B003U4GQEC%3FSubscriptionId%3D15SMZCTB9V8NGR2TW082%26tag%3Dbornneet-22%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3DB003U4GQEC" target="_blank">Amazonで詳しく見る</a></font><font size="-2"> by <a href="http://www.goodpic.com/mt/aws/index.html" >G-Tools</a></font></td></tr></table>

<h3>[IB不使用なプロジェクトの作成]</h3>
<p>前置きが長くなりました。<br />
<br />
IBを使わないプロジェクトは、以下の手順で作成できます。<br />
簡単ですね。</p>
<ol>
<li>Xcodeの新規プロジェクトから、「Window-based Appication」、Productは「iPad」を選択。<br />
<img src="http://file.blog.bornneet.com/ipad1_newprj.png" alt="新規プロジェクト作成" />
</li>
<li>MainWindow.xibファイルを削除する。<br />
（参照を削除じゃなく、一緒にゴミ箱に入れる）<br />
<img src="http://file.blog.bornneet.com/ipad1_xib.png" alt="xibファイルの削除" />
</li>
<li>「プロジェクト名-info.plist」の「Main nib file base name」を項目ごと削除。<br />
<img src="http://file.blog.bornneet.com/ipad1_plist_before.png" alt="plist削除前" /><br />
<img src="http://file.blog.bornneet.com/ipad1_plist_after.png" alt="plist削除後" />
</li>
<li>main.mのmain()を修正。<br />
（plistに指定したnib fileから自動で取得されていたものをコードで指定）
<pre class="source"><code>int main(int argc, char *argv[]) {
    
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
<strong>//    int retVal = UIApplicationMain(argc, argv, nil, nil);
    int retVal = UIApplicationMain(argc, argv, nil, @"EdhitaAppDelegate");</strong>
    [pool release];
    return retVal;
}</code></pre>
</li>
<li>AppDelegateの修正。<br />
（自動で作成されていたUIWindowインスタンスを作成し、viewとlabelを追加。）
<pre class="source"><code>//  EdhitaAppDelegate.m

<strong>// @synthesize window;</strong>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
	
    // Override point for customization after application launch.
	
<strong>	window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
	
	UIView *view = [[UIView alloc] initWithFrame: [window frame]];
	[window addSubview:view];

	UILabel *label = [[UILabel alloc] initWithFrame: [window frame]];
	label.text = @"Hello, iPad!";
	label.textAlignment = UITextAlignmentCenter;
	label.font = [[UIFont alloc] fontWithSize: 50];
	[view addSubview:label];</strong>
	
    [window makeKeyAndVisible];
	
	return YES;
}</code></pre>
<pre class="source"><code>//  EdhitaAppDelegate.h

<strong>//@property (nonatomic, retain) IBOutlet UIWindow *window;</strong></code></pre>
</li>
<li>ビルドと実行。<br />
<img src="http://file.blog.bornneet.com/ipad1_run.png" alt="実行結果" />
</li>
</ol>
<h3>[まとめ]</h3>
<p>今回の作業はこれで終了です。<br />
俗に言うHello, world!ですね。<br />
<br />
次回以降、テキストエディタとしての機能を追加していきます。<br />
宜しくお付き合い下さい。<br />
<br />
突っ込みもお待ちしています。</p>
<h3>[コード]</h3>
<p>今回のコードは「Edhita1.zip」に入っています。<br />
GitHubのdownloadページからダウンロードして下さい。<br />
<br />
<a href="http://github.com/tnantoka/Edhita/downloads" class="external" target="_blank" title="新しいウィンドウで開きます">Downloads for tnantoka's Edhita - GitHub</a></p>
<h3>[おまけ：目次]</h3>
<p>こんな感じで進めたい。</p>
<ul>
<li>第1回：プロジェクトの作成</li>
<li>第2回：SplitView</li>
<li>第3回：ファイル操作とNavigationController</li>
<li>第4回：Syntax Highlighting</li>
<li>第5回：Accessory View</li>
<li>第6回：広告</li>
<li>第7回：FTP</li>
<li>第?回：未定</li>
</ul>
]]>
			</description>
			<link>http://blog.bornneet.com/Entry/287/</link>
			<pubDate>Sun, 08 Aug 2010 14:56:14 GMT</pubDate>
		</item>
		<item>
			<title>JavaScriptでタイピングゲーム（英語長文暗記用）</title>
			<description>
			<![CDATA[<p>
いつまでも「英語苦手」とも言ってられないので、<br />
やる気を出してプレゼンでも暗記するかと思って、<br />
任意の長文をタイピングするようなWebサービスを探したけど、<br />
イマイチ見つからなかったので作ってみた。<br />
<br />
ながらプログラミングなので、<br />
コードはひどいけど、一応動いているのでよしとする。<br />
（といってもテスト全然してないけど。）<br />
<br />
<a href="http://jsany.org/memorize/">タイピング試作版</a><br />
<br />
使い方は至って簡単。<br />
初めて開いた時に表示されるtextareaに英文を入力してregisterします。<br />
※ テストの時は<a href="http://slashdot.org/comments.pl?sid=152625&cid=12810404" class="external" target="_blank" title="新しいウィンドウで開きます">この英文</a>を使いました。<br />
<br />
すると、localStorageに英文を保存して、タイピングができるようになります。<br />
問題を変えるときは、右上の問題登録から再度同じ操作を行ないます。<br />
<br />
と、まぁ最低限の機能は備えてるかな、と思います。<br />
自分で使ってる中で不満があれば、機能追加するかもしれません。<br />
<br />
以上、久々の投稿にしては質が低いなー。
</p>]]>
			</description>
			<link>http://blog.bornneet.com/Entry/286/</link>
			<pubDate>Sat, 07 Aug 2010 12:49:20 GMT</pubDate>
		</item>
		<item>
			<title>JavaScript Anywhere 1.5リリース！</title>
			<description>
			<![CDATA[<p>
iPadに（暫定）対応した<a href="http://jsany.org/">JavaScript Anywhere</a>のアップデート版がリリースされました。<br />
6月末リリースを目指していたので、約1週間遅れですが。<br />
<br />
今回のバージョンでは、皆様からいただいた要望を元に、<br />
以下の機能を盛り込みました。<br />
<br />
是非、使ってみてください。（もちろん価格は無料のままです。）
</p>
<ul>
<li>複数プロジェクトのサポート</li>
<li>Landscapeモードに対応</li>
<li>各種設定<ul>
<li>テキスト・背景色</li>
<li>メール送信時の形式（添付ファイル or 本文）</li>
<li>画面回転ロック</li>
</ul>
<li>Webからファイルをダウンロード</li>
</ul>
<p>
ただ、付け焼刃の対応をした為、コードがもうぐちゃぐちゃです。<br />
<br />
このままでは動作の安定にも悪影響を与えかねないということで、<br />
改めてObjective-Cの勉強をしています。<br />
<br />
次のリリースでは書き直したコードによる安定・高速版をお届けできる予定です。<br />
<br />
「打倒有料ライバルアプリ」で頑張っていきますので、<br />
今後ともjsanyを宜しくお願いします。
</p>
]]>
			</description>
			<link>http://blog.bornneet.com/Entry/285/</link>
			<pubDate>Fri, 09 Jul 2010 23:41:32 GMT</pubDate>
		</item>
		<item>
			<title>jQTouchとHTML5のlocalStorageでwikiみたいなの作った（w3c widget化も）</title>
			<description>
			<![CDATA[<p>
約一ヶ月ぶりのエントリ…完全に暑さに負けてますね^^<br />
<br />
というわけで今日は日曜出勤の振替休日を利用して、<br />
最近Ext.jsに合流したりで話題のjQTouchを触ってみました。<br />
<br />
そしてできあがったのが、このwikiもどきです。<br />
<br />
<a href="http://jsany.org/wiki5/">wiki5</a><br />
<br />
<img src="http://file.blog.bornneet.com/wiki5.png" />
</p>
<h3>説明</h3>
<p>
触っていただければ使い方はなんとなくわかると思います。<br />
ただ、Mobile Safari以外では一切動きません。<br />
（iOS4上では動作未確認です。）<br />
<br />
また、タップが効かない、ボタンがアクティブのままになる、<br />
画面が真っ黒になる等、全体的に挙動が安定していません。<br />
（はい、テスト不足です。）<br />
<br />
どうにもならなくなったときは「wiki5/index.html?clear」にアクセスすれば、<br />
初期化されます。<br />
<br />
あと、ついでですがw3c widgetにもしてみました。<br />
cloud readerで動作することを軽く確認しています。<br />
<br />
<a href="http://jsany.org/wiki5/wiki5.wgt">wiki5</a><br />
<br />
中身の解説は暑いのでやめておきます（！）が、<br />
ソースコードはgithubに置いてますので、ご自由にどうぞ。<br />
<br />
<a href="http://github.com/tnantoka/wiki5" class="external" target="_blank" title="新しいウィンドウで開きます">tnantoka's wiki5 at master - GitHub</a>
<br />
</p>
<h3>感想</h3>
<p>
今回、jQTouchのドキュメントを一切読まずに進めてしまったので、<br />
予想以上に苦労しました。<br />
やっぱり無茶はダメですね。<br />
<br />
あと、iPhone Webアプリはデバッグが大変だな、と。<br />
MacのSafariで動いても、シミュレータでは全然動かないとかも多々。<br />
<br />
小さいアプリこそ実は、IBでちょちょいと作ってネイティブアプリにした方が<br />
楽だったりするのかも。<br />
</p>
<h3>使用ライブラリ</h3>
<ul>
<li><a href="http://jqtouch.com/" class="external" target="_blank" title="新しいウィンドウで開きます">jQTouch — jQuery plugin for mobile web development</a><br />
説明不要。</li>
<li><a href="http://attacklab.net/showdown/" class="external" target="_blank" title="新しいウィンドウで開きます">Showdown - Markdown in JavaScript</a><br />
Wiki記法の代わりにMarkdownを採用しました。</li>
<li><a href="http://www.json.org/js.html" class="external" target="_blank" title="新しいウィンドウで開きます">JSON in JavaScript</a><br />
Mobile SafariでJSON.parse/stringifyする為に。<br />
（現在の実装はlocalStorageに文字列しか格納できないので。仕様上はany data。）</li>
</ul>
<h3>参考サイト</h3>
<p><a href="http://www.studio-bloom.net/archives/2240" class="external" target="_blank" title="新しいウィンドウで開きます">jQTouch – 画面遷移の前にデータ処理 | STUDIO Bloom 大阪・北摂地域を中心としたWebサイト・システム制作</a><br />
他、多数。</p>
<p>
以上です。<br />
あーブログの書き方をどんどん忘れていくー
</p>]]>
			</description>
			<link>http://blog.bornneet.com/Entry/284/</link>
			<pubDate>Tue, 22 Jun 2010 03:55:58 GMT</pubDate>
		</item>
		<item>
			<title>自作iPhoneアプリをiPad実機で動かすところまで</title>
			<description>
			<![CDATA[<p>
ついに出ましたね、iPad。<br />
ぼーっとしてる間に予約をし損ねたのですっかり諦めてたんですが、<br />
当日に入手することができました。<br />
※ softbank wifiスポットが2年間ただで使えるんですね、知りませんでした。<br />
　（3Gを売るためにあまり宣伝してなかった？？）<br />
<br />
どうやらかなり在庫があったようで、ビックカメラでは当日完売店舗が0だったと日経で報じられていました。<br />
<br />
予約数をあえて制限し人気の過熱っぷりをアピールするマーケティング、さすがアップルと言ったところですか。<br />
（日本企業なら予約者のことを考えて、とてもできなさそうです）<br />
<br />
まだ少ししか触ってないですが、これはかなり使い易いです。<br />
確かに機能的にはiPod Touchが大きくなっただけですが、<br />
キーボードの打ちやすさとか、ネットの見やすさとか、大きいだけで断然違います。<br />
これはますますPCを使う時間が減りそうだ…。<br />
<br />
さて、そんなiPadですが、入手した自分のアプリがどう動くか気になります。<br />
で、早速試してみたところ、iPhoneエミュレータが起動してその中で動くという残念な形に。<br />
<br />
というわけでiPadの実機で動かすところまでをやってみました。<br />
（iPhoneアプリを動かすところまではできてる前提にした殴り書きです。）
</p>
<h3>参考サイト</h3>
<ul>
<li><a href="http://blog.myrss.jp/archives/2010/04/iphone_ipad.html" class="external" target="_blank" title="新しいウィンドウで開きます">iPhone アプリを iPad 対応にする方法（プログラミング編） : 管理人@Yoski</a></li>
<li><a href="http://bakkers.gr.jp/~kitani/event/iphonekyoto/#3-2" class="external" target="_blank" title="新しいウィンドウで開きます">iPhone京都勉強会（第３弾 - 第２回: 2010.05.19）</a></li>
<li><a href="http://ameblo.jp/shrinetree/entry-10530346246.html" class="external" target="_blank" title="新しいウィンドウで開きます">iPad app from iPhone codes｜iPhone App 開発</a></li>
</ul>
<h3>3.2 SDK導入</h3>
<p>
まずは、iPhone SDK 3.2をインストールします。<br />
iPhone Dev Centerからどうぞ。<br />
ダウンロード＆インストールで1時間以上かかるので注意です。<br />
インストーラは全部デフォルトのまま次に行っちゃって問題なしです。
</p>
<h3>シミュレータで動かす</h3>
<h4>Upgrade Current Target for iPad</h4>
<p>
Xcodeで既存iPhoneアプリのプロジェクトを開きます。<br />
左ペインの「グループとファイル」から「ターゲット」を開きます。<br />
その中にあるターゲット（プロジェクト名のもの）を右クリックして、<br />
「現在のターゲットをiPad用にアップグレード…」をクリックするとポップアップが出てくるので、<br />
「One Universal application」を選んで進みます。<br />
「Resouces-iPad」グループ（中身は空）ができればOKです。<br />
<br />
次に、メニューの「プロジェクト」→「プロジェクト設定を編集」を選びます。<br />
Targeted Device FamilyをiPhone/iPadに変えておきます。<br />
<br />
これで下準備はOKです。
</p>
<h4>Create iPad Version</h4>
<p>
次にiPad用のリソースを作り、シミュレータで動かします。<br />
<br />
「Resouces」の「MainWindow.xib」をダブルクリックで開きます。<br />
開いたInterface Builderのメニューから、<br />
「File」→「Create iPad Version Using Autosizing Masks」を選択します。<br />
<br />
すると、iPad用の画面が出てくるので、保存します。<br />
場所はプロジェクトの「Resouces-iPad」内に、名前は「MainWindow-iPad.xib」で良いです。<br />
※ このファイル名は「*-info.plist」の「Main nib file base name (iPad)」で指定する必要がありますが、<br />
　デフォルトで上記の名前になっています。<br />
<br />
保存を押すとポップアップが出てくるので、プロジェクト名のターゲットをチェックしてAddします。<br />
<br />
「*ViewController.xib」も同じ手順で「-iPad」付きのファイルを作ります。<br />
<br />
こうすると、「グループとファイル」の中に「-iPad」付きの.xibファイルができるので、<br />
「Resouces-iPad」にドラッグ＆ドロップします。<br />
<br />
最後に「MainWindow-iPad.xib」を開き、<br />
「Attributes」の「NIB Name」を「-iPad」付きのControllerに変更します。<br />
<br />
これで、「Simulator - 3.2 | Debug」等で実行すればiPadシミュレータで動くはずです。<br />
※ 部品の大きさなどは調整する必要が有ります。
</p>

<h3>実機で動かす</h3>
<p>
iPhone Provisioning Portalの左メニューから「Devices」を選択します。<br />
「Add Devices」を選択して、左列の名前は適当に（iPad等）、右列のDevice IDには、<br />
iPadを繋いで、「Xcode」→「ウィンドウ」→「オーガナイザ」から表示される「identifier」をコピペします。<br />
<br />
次に、左メニューから「Provisioning」を選択します。<br />
iPhoneアプリ用に既に作っているものを使いまわす為、<br />
「Edit」→「Modify」を選びます。そして「Devices」を「Select All」してsubmitします。<br />
<br />
するとPending状態になるので、画面を更新しActiveにし、downloadします。<br />
<br />
先程開いた「オーガナイザ」でiPadを選択し、「Use for development」をクリックすると出てくる、<br />
「Provisioning」にダウンロードしたファイルをドラッグ＆ドロップします。<br />
「プロジェクト設定を編集」から「コード署名ID」も今ダウンロードしたものに変更します。<br />
<br />
そして、「Device - 3.2 | Debug」等で動かせば…<br />
<br />
<strong>動きました！！</strong><br />
<img src="http://file.blog.bornneet.com/jsany_ipad_test.png" /><br />
<br />
</p>

<h3>まとめ</h3>
<p>
<br />
とりあえず実機テストまでは行けました。<br />
<br />
このままApp Storeに申請…といきたいところなのですが、<br />
どうやらiPadアプリはportrait/landscape両対応が必須らしいので、<br />
頑張りたいと思います。
</p>
]]>
			</description>
			<link>http://blog.bornneet.com/Entry/283/</link>
			<pubDate>Sat, 29 May 2010 05:49:15 GMT</pubDate>
		</item>
		<item>
			<title>ruby1.9をcoreserverとmacのホームディレクトリにインストール</title>
			<description>
			<![CDATA[<p>
久々のブログ。<br />
大したネタはないけど、たまには書かないと文章の書き方忘れちゃいそうなので。<br />
<br />
ということで、rubyに関するちょっとしたメモ。<br />
<br />
開発環境であるmacと本番環境であるcoreserverを統一したくて、<br />
rubygemsをホームディレクトリに入れようとするも失敗。<br />
<br />
諦めかけたけど、1.9にはgemが同梱されているということで、<br />
いっそのこと1.9をインストールしちゃえばいいんじゃないかとやってみた。<br />
<br />
結果、すんなりうまく行ったので手順を残しておく。
</p>
<h3>参考</h3>
<p>
<a href="http://d.hatena.ne.jp/seuzo/20090925/1253806231" class="external" target="_blank" title="新しいウィンドウで開きます">Ruby1.8系とRuby1.9系を共存させてみる。 - 名もないテクノ手</a>
</p>
<h3>手順</h3>
<pre class="source"><code># 作業ディレクトリの作成
mkdir src
cd src

# ダウンロード・展開
wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p378.tar.gz
tar zxf ruby-1.9.1-p378.tar.gz
cd ruby-1.9.1-p378

# パス設定
vim .profile
export PATH=$HOME/local/bin:$PATH
:wq
source .profile

# coreserverは.bashrcで
vim .bashrc
source .bashrc

# インストール
# 場所は~/local以下、コマンド名はruby19(gemはgem19)
./configure --prefix=$HOME/local --program-suffix=19
make
make install

# coreserverでは以下のエラーが出た
make[1]: Entering directory `/virtual/core/src/ruby-1.9.1-p378/ext/dl'
gcc -I. -I../../.ext/include/i686-linux -I../.././include -I../.././ext/dl -DRUBY_EXTCONF_H=\"extconf.h\"  -D_FILE_OFFSET_BITS=64  -fPIC  -O2 -g -Wall -Wno-parentheses -fno-defer-pop -fno-omit-frame-pointer  -o callback-4.o -c callback-4.c
gcc: Internal error: Killed (program cc1)
Please submit a full bug report.
See <URL:http://www.suse.de/feedback> for instructions.
make[1]: *** [callback-4.o] Error 1
make[1]: Leaving directory `/virtual/core/src/ruby-1.9.1-p378/ext/dl'
make: *** [mkmain.sh] Error 1

# 手動で失敗したコマンドを叩いた後、makeすれば通った
cd /virtual/core/src/ruby-1.9.1-p378/ext/dl
gcc -I. -I../../.ext/include/i686-linux -I../.././include -I../.././ext/dl -DRUBY_EXTCONF_H=\"extconf.h\"  -D_FILE_OFFSET_BITS=64  -fPIC  -O2 -g -Wall -Wno-parentheses -fno-defer-pop -fno-omit-frame-pointer  -o callback-4.o -c callback-4.c
make

# インストール確認
ruby19 -v
gem19 -v</code></pre>
<p>
~/.profile, ~/.bashrcとmakeでこけるとこ以外は、mac, coreserver共通でいけました。<br />
貴重な日曜日のかなりの時間を費やしたのに、1.9ならこんなにすんなりいけるとは。<br />
やっぱ言語に標準で組み込まれているってのはいいですねー。
</p>
]]>
			</description>
			<link>http://blog.bornneet.com/Entry/282/</link>
			<pubDate>Mon, 24 May 2010 13:59:30 GMT</pubDate>
		</item>

		</channel>
	</rss>