<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sun Limited Mt. &#187; iPhone/iPod touch</title>
	<atom:link href="http://www.syuhari.jp/blog/archives/category/iphoneipod-touch/feed" rel="self" type="application/rss+xml" />
	<link>http://www.syuhari.jp/blog</link>
	<description>I love iPhone, CakePHP and WordPress.</description>
	<lastBuildDate>Thu, 22 Jul 2010 02:13:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>[iPhone] MFMailComposeViewController で画像入りの HTML メールを送る</title>
		<link>http://www.syuhari.jp/blog/archives/2184</link>
		<comments>http://www.syuhari.jp/blog/archives/2184#comments</comments>
		<pubDate>Thu, 22 Jul 2010 02:13:40 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[send]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2184</guid>
		<description><![CDATA[MFMailComposeViewController を使うと簡単にアプリ内から簡単にメール送信することができます。HTML メールも送信することが可能ですが、HTML で img タグを使うときには画像ファイルを Base64 エンコードする必要があります。
NSData+Base64
下記サイトの下の方にある NSData+Base64 のコードをダウンロードしてプロジェクトに追加します。
Cocoa with Love: Base64 encoding options on the Mac and iPhone

img タグを入れた HTML メールを送る
HTML メールを送るには以下のようにします。

NSMutableString* emailBody = [[[NSMutableString alloc] initWithString:@""] retain];
// HTML で本文を作成する
[emailBody appendString:@"太字"];

[emailBody appendString:@""];
MFMailComposeViewController* mailvc = [[MFMailComposeViewController alloc] init];
mailvc.mailComposeDelegate = self;
[mailvc setSubject:@"subject"];
[mailvc setToRecipients:[NSArray arrayWithObject:@"hoge@example.com"]];
[mailvc setMessageBody:emailBody isHTML:YES];
[self presentModalViewController:mailvc animated:YES];
[mailvc release];
[emailBody release];

しかし、img タグはタグを入れただけでは画像を本文内に表示させることはできません。img タグを使用する場合は、以下のように画像データを Base64 でエンコードして入れます。

NSString* path [...]]]></description>
			<content:encoded><![CDATA[<p>MFMailComposeViewController を使うと簡単にアプリ内から簡単にメール送信することができます。HTML メールも送信することが可能ですが、HTML で img タグを使うときには画像ファイルを Base64 エンコードする必要があります。</p>
<h4>NSData+Base64</h4>
<p>下記サイトの下の方にある NSData+Base64 のコードをダウンロードしてプロジェクトに追加します。<br />
<a href="http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html" target="_blank" class="liexternal">Cocoa with Love: Base64 encoding options on the Mac and iPhone</a><br />
<span id="more-2184"></span></p>
<h4>img タグを入れた HTML メールを送る</h4>
<p>HTML メールを送るには以下のようにします。</p>
<pre class="cpp" name="code">
NSMutableString* emailBody = [[[NSMutableString alloc] initWithString:@"<html><body>"] retain];
// HTML で本文を作成する
[emailBody appendString:@"<strong>太字</strong>"];

[emailBody appendString:@"</body></html>"];
MFMailComposeViewController* mailvc = [[MFMailComposeViewController alloc] init];
mailvc.mailComposeDelegate = self;
[mailvc setSubject:@"subject"];
[mailvc setToRecipients:[NSArray arrayWithObject:@"hoge@example.com"]];
[mailvc setMessageBody:emailBody isHTML:YES];
[self presentModalViewController:mailvc animated:YES];
[mailvc release];
[emailBody release];
</pre>
<p>しかし、img タグはタグを入れただけでは画像を本文内に表示させることはできません。img タグを使用する場合は、以下のように画像データを Base64 でエンコードして入れます。</p>
<pre class="cpp" name="code">
NSString* path = [[NSBundle mainBundle] pathForResource:@"foo" ofType:@"gif"];
NSData* data = [NSData dataWithContentsOfFile:path];
NSString* base64String = [data base64EncodedString];
[emailBody appendString:[NSString stringWithFormat:@&quot;&lt;img src='data:image/gif;base64,%@'&gt;&quot;, base64String]];
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2184/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[iPhone] Localized 時の小技</title>
		<link>http://www.syuhari.jp/blog/archives/2159</link>
		<comments>http://www.syuhari.jp/blog/archives/2159#comments</comments>
		<pubDate>Fri, 21 May 2010 01:14:23 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Localizable.string]]></category>
		<category><![CDATA[Localized]]></category>
		<category><![CDATA[NSLog]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2159</guid>
		<description><![CDATA[NSLog の文字列フォーマットは C言語の printf と同じです。この文字列フォーマットには引数を文字列内に入れる順番を指定することができます。

NSLog(@"%@, %@, %@", @"one", @"two", @"three");

上記の実行結果は &#8220;one, two, three&#8221; です。
次に下記のように実行すると


NSLog(@"%3$@, %2$@, %1$@, %2$@", @"one", @"two", @"three");

実行結果は &#8220;three, two, one, two&#8221; となります。&#8221;n$&#8221; と指定することにより、何番目の引数を入れるかを指定することができます。また同じ引数を何度でも指定することができます。
まあ、実際に NSLog ではこんな使い方をすることはないと思います。
しかし、これを知っておくと動的に出力する文字列をローカライズするときに役立ちます。
例えば、次のような日本語を出力したいとします。
（あまりいい例文が思いつかなかったw）

「太郎は2010年5月20日に花子と会った」

英語にローカライズすると

&#8220;Taro met hanako on May 20, 2010.&#8221;

この文章の中で「太郎」「花子」「2010年5月20日」が動的に変わるとすると困るのが語順が違うことです。
この時こそ、先程の文字列フォーマットの順番指定が聞いてきます。
.strings に下記のように指定してします。

"HogeFormat" = @"%1$@は%3$@に%2$@と会った";
"HogeFormat" = @"%1$@ met %2$@ on %3$@.";

実際に出力する際は語順を気にせずに全ての言語で同じ語順で指定すれば正しく出力されます。

format = NSLocalizedString(@"HogeFormat", nil);
formattedString = [NSString stringWithFormat:format, name, name2, date];

もちろん、日付のローカライズはその前に必要です。日付のローカライズに関しては下記エントリもご参照ください。
[iPhone] 日付をローカライズして表示する &#124; Sun [...]]]></description>
			<content:encoded><![CDATA[<p>NSLog の文字列フォーマットは C言語の printf と同じです。この文字列フォーマットには引数を文字列内に入れる順番を指定することができます。</p>
<pre class="cpp" name="code">
NSLog(@"%@, %@, %@", @"one", @"two", @"three");
</pre>
<p>上記の実行結果は &#8220;one, two, three&#8221; です。<br />
次に下記のように実行すると<br />
<span id="more-2159"></span></p>
<pre class="cpp" name="code">
NSLog(@"%3$@, %2$@, %1$@, %2$@", @"one", @"two", @"three");
</pre>
<p>実行結果は &#8220;three, two, one, two&#8221; となります。&#8221;<strong>n$</strong>&#8221; と指定することにより、何番目の引数を入れるかを指定することができます。また同じ引数を何度でも指定することができます。</p>
<p>まあ、実際に NSLog ではこんな使い方をすることはないと思います。<br />
しかし、これを知っておくと動的に出力する文字列をローカライズするときに役立ちます。</p>
<p>例えば、次のような日本語を出力したいとします。<br />
（あまりいい例文が思いつかなかったw）</p>
<ul>
<li>「太郎は2010年5月20日に花子と会った」</li>
</ul>
<p>英語にローカライズすると</p>
<ul>
<li>&#8220;Taro met hanako on May 20, 2010.&#8221;</li>
</ul>
<p>この文章の中で「太郎」「花子」「2010年5月20日」が動的に変わるとすると困るのが語順が違うことです。<br />
この時こそ、先程の文字列フォーマットの順番指定が聞いてきます。</p>
<p>.strings に下記のように指定してします。</p>
<pre class="cpp" name="code">
"HogeFormat" = @"%1$@は%3$@に%2$@と会った";
"HogeFormat" = @"%1$@ met %2$@ on %3$@.";
</pre>
<p>実際に出力する際は語順を気にせずに全ての言語で同じ語順で指定すれば正しく出力されます。</p>
<pre class="cpp" name="code">
format = NSLocalizedString(@"HogeFormat", nil);
formattedString = [NSString stringWithFormat:format, name, name2, date];
</pre>
<p>もちろん、日付のローカライズはその前に必要です。日付のローカライズに関しては下記エントリもご参照ください。<br />
<a href="http://www.syuhari.jp/blog/archives/1248" class="liinternal">[iPhone] 日付をローカライズして表示する | Sun Limited Mt.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2159/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[iPhone] UIWebView の表示内容をキャプチャして UIImage を生成する</title>
		<link>http://www.syuhari.jp/blog/archives/2145</link>
		<comments>http://www.syuhari.jp/blog/archives/2145#comments</comments>
		<pubDate>Fri, 21 May 2010 00:42:04 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[capture]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[rendering]]></category>
		<category><![CDATA[screenshot]]></category>
		<category><![CDATA[UIWebView]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2145</guid>
		<description><![CDATA[UIWebView の表示内容を UIImage にして、表示する方法です。UIWebView を表示させずに、指定した URL のページ内容をレンダリングして UIImage を生成して、UIImageViw に表示します。スクリーンショットだけを取りたいときに使えます。
UIWebView はインスタンスを生成しただけでは、URL をロードしてもレンダリングされません。レンダリングするには UIWindow 内になければダメです。そのために実際には表示しない UIWindow を作成して、その中に addSubview します。

UIWebView のデリゲートメソッド webViewDidFinishLoad: でロード終了の通知を受けてから、UIWebView のレイヤーの内容を UIImage に書きだします。

- (void)viewDidLoad {
  [super viewDidLoad];

  // 表示する UIImageView を生成
  self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 90, 200, 300)];
  [self.view addSubview:imageView];

  // UIWebView 用の表示しない UIWindow を生成
  self.offscreenWindow = [...]]]></description>
			<content:encoded><![CDATA[<p>UIWebView の表示内容を UIImage にして、表示する方法です。UIWebView を表示させずに、指定した URL のページ内容をレンダリングして UIImage を生成して、UIImageViw に表示します。スクリーンショットだけを取りたいときに使えます。</p>
<p>UIWebView はインスタンスを生成しただけでは、URL をロードしてもレンダリングされません。レンダリングするには UIWindow 内になければダメです。そのために実際には表示しない UIWindow を作成して、その中に addSubview します。<br />
<span id="more-2145"></span><br />
UIWebView のデリゲートメソッド webViewDidFinishLoad: でロード終了の通知を受けてから、UIWebView のレイヤーの内容を UIImage に書きだします。</p>
<pre class="cpp" name="code">
- (void)viewDidLoad {
  [super viewDidLoad];

  // 表示する UIImageView を生成
  self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(60, 90, 200, 300)];
  [self.view addSubview:imageView];

  // UIWebView 用の表示しない UIWindow を生成
  self.offscreenWindow = [[UIWindow alloc] initWithFrame:self.view.bounds];

  // UIWebView を表示しない UIWindow に生成
  NSURL* url = [NSURL URLWithString:@"http://www.yahoo.co.jp/"];
  self.webView = [[[UIWebView alloc] initWithFrame:imageView.bounds] autorelease];
  webView.delegate = self;
  webView.scalesPageToFit = YES;
  [offscreenWindow addSubview:webView];
  [webView loadRequest:[NSURLRequest requestWithURL:url]];
  isRendering = YES;
}

- (void) webViewDidFinishLoad:(UIWebView *)webView {
  if (isRendering) {
    isRendering = NO;
    // UIWebView の描画は別スレッドで行われ、
    // 描画完了前にこのメソッドが呼ばれるので
    // UIImage への描画処理は遅らせて実行する
    [self performSelector:@selector(renderWebContent) withObject:nil afterDelay:1.0];
  }
}

- (void) renderWebContent {
  UIGraphicsBeginImageContext(imageView.bounds.size);
  [webView.layer renderInContext:UIGraphicsGetCurrentContext()];
  imageView.image = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  [webView removeFromSuperview];
  webView.delegate = nil;
}
</pre>
<p>実行結果は以下のようになります。<br />
<a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/スクリーンショット（2010-05-20-5-20木-13.24.26）.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/スクリーンショット（2010-05-20-5-20木-13.24.26）-161x300.png" alt="スクリーンショット（2010-05-20 5-20木 13.24.26）" title="スクリーンショット（2010-05-20 5-20木 13.24.26）" width="161" height="300" class="alignnone size-medium wp-image-2146" /></a></p>
<p>注意点は UIWebView のレンダリング処理は別スレッドで非同期に行われるため、webViewDidFinishLoad: の通知の時にすぐに UIImage への書き出し処理を実行すると不完全なページになってしまいます。上記コードの 27行目を下記のように変更してすぐに書き出し処理すると不完全なページになってしまいます。</p>
<pre class="cpp" name="code">
[self renderWebContent];
</pre>
<p><a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/スクリーンショット（2010-05-20-5-20木-13.28.42）.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/スクリーンショット（2010-05-20-5-20木-13.28.42）-161x300.png" alt="スクリーンショット（2010-05-20 5-20木 13.28.42）" title="スクリーンショット（2010-05-20 5-20木 13.28.42）" width="161" height="300" class="alignnone size-medium wp-image-2148" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2145/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>[iPhone] UIWebView のタッチイベントを取得する</title>
		<link>http://www.syuhari.jp/blog/archives/2141</link>
		<comments>http://www.syuhari.jp/blog/archives/2141#comments</comments>
		<pubDate>Thu, 20 May 2010 02:36:53 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[UIWebView]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2141</guid>
		<description><![CDATA[iPhoneSDK開発のレシピのレシピ47「UIWebView をフィンガージェスチャーで操作する」書かせていただいたのですが、この処理でプライベートAPI を使用しているために、以下のように修正しまさせていただきました。GitHub のサンプルコードでは既に先月修正済みなのですが正式にアナウンスしていなかったので、改めて説明させていただきます。
やりたいことは、Firefox などのマウスジェスチャーのように UIWebView をフィンガージェスチャーで操作するということです。UIWebView ではシングルタッチはスクロールや拡大縮小などがあるため、２本指でのタッチで左右にスワイプしたときに戻る、進むという動作をさせることにします。（フレーム内のスクロールに２本指でのタッチを使用しますが、まあその辺はとりあえず置いておいて下さい）

詳細なコードは GitHub にありますので、詳しくはそちらをご参照ください。
ポイントはフィンガージェスチャーを認識するためにタッチ動作をフックする UIWindow のサブクラス GestureWindow を作り、AppDelegate でその GestureWindow を使用するところです。UIWindow の sendEvent: ですべてのタッチ動作をフックして UIWebView への2本指でのマルチタッチのときのみ、delegateを通じてタッチイベントを通知します。また、フックしたタッチイベントは全てスーパークラスへそのまま渡すことにより、通常のタッチイベントを邪魔しないようにします。

@protocol GestureWindowDelegate

- (void) touchesBeganWeb:(NSSet *)touches withEvent:(UIEvent *)event;
- (void) touchesMovedWeb:(NSSet *)touches withEvent:(UIEvent *)event;
- (void) touchesEndedWeb:(NSSet *)touches withEvent:(UIEvent *)event;

@end

@interface GestureWindow : UIWindow {
    UIWebView* wView;
    id delegate;
}

@property (nonatomic, retain) UIWebView* [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.co.jp/gp/product/4798025798?ie=UTF8&#038;tag=8109-22&#038;linkCode=as2&#038;camp=247&#038;creative=7399&#038;creativeASIN=4798025798" target="_blank" class="liexternal">iPhoneSDK開発のレシピ</a>のレシピ47「UIWebView をフィンガージェスチャーで操作する」書かせていただいたのですが、この処理でプライベートAPI を使用しているために、以下のように修正しまさせていただきました。GitHub のサンプルコードでは既に先月修正済みなのですが正式にアナウンスしていなかったので、改めて説明させていただきます。</p>
<p>やりたいことは、Firefox などのマウスジェスチャーのように UIWebView をフィンガージェスチャーで操作するということです。UIWebView ではシングルタッチはスクロールや拡大縮小などがあるため、２本指でのタッチで左右にスワイプしたときに戻る、進むという動作をさせることにします。（フレーム内のスクロールに２本指でのタッチを使用しますが、まあその辺はとりあえず置いておいて下さい）<br />
<span id="more-2141"></span><br />
詳細なコードは <a href="http://github.com/ktakayama/iPhoneSDK-RecipeBook/tree/master/047/" target="_blank" class="liexternal">GitHub</a> にありますので、詳しくはそちらをご参照ください。</p>
<p>ポイントはフィンガージェスチャーを認識するためにタッチ動作をフックする UIWindow のサブクラス GestureWindow を作り、AppDelegate でその GestureWindow を使用するところです。UIWindow の sendEvent: ですべてのタッチ動作をフックして UIWebView への2本指でのマルチタッチのときのみ、delegateを通じてタッチイベントを通知します。また、フックしたタッチイベントは全てスーパークラスへそのまま渡すことにより、通常のタッチイベントを邪魔しないようにします。</p>
<pre class="cpp" name="code">
@protocol GestureWindowDelegate

- (void) touchesBeganWeb:(NSSet *)touches withEvent:(UIEvent *)event;
- (void) touchesMovedWeb:(NSSet *)touches withEvent:(UIEvent *)event;
- (void) touchesEndedWeb:(NSSet *)touches withEvent:(UIEvent *)event;

@end

@interface GestureWindow : UIWindow {
    UIWebView* wView;
    id delegate;
}

@property (nonatomic, retain) UIWebView* wView;
@property (nonatomic, assign) id delegate;

@end
</pre>
<pre class="cpp" name="code">
@implementation GestureWindow

@synthesize wView, delegate;

-(void) dealloc {
    [wView release];
    [super dealloc];
}

- (void)sendEvent:(UIEvent *)event {
    [super sendEvent:event];
    if (wView == nil || delegate == nil) {
        return;
    }
    // 2本指でのマルチタッチか
    NSSet *touches = [event allTouches];
    if (touches.count != 2) {
        return;
    }

    UITouch *touch = touches.anyObject;
    // 指定のUIWebViewへのタッチか
    if ([touch.view isDescendantOfView:wView] == NO) {
        return;
    }

    switch (touch.phase) {
        case UITouchPhaseBegan:
            if ([self.delegate
                 respondsToSelector:@selector(touchesBeganWeb:withEvent:)]) {
                [self.delegate
                    performSelector:@selector(touchesBeganWeb:withEvent:)
                    withObject:touches withObject:event];
            }
            break;
        case UITouchPhaseMoved:
            if ([self.delegate
                 respondsToSelector:@selector(touchesMovedWeb:withEvent:)]) {
                [self.delegate
                    performSelector:@selector(touchesMovedWeb:withEvent:)
                    withObject:touches withObject:event];
            }
            break;
        case UITouchPhaseEnded:
            if ([self.delegate
                 respondsToSelector:@selector(touchesEndedWeb:withEvent:)]) {
                [self.delegate
                    performSelector:@selector(touchesEndedWeb:withEvent:)
                    withObject:touches withObject:event];
            }
        default:
            return;
            break;
    }
}

@end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2141/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[iPhone] UIWebView のリリース前に delegate に nil をセットする必要がある</title>
		<link>http://www.syuhari.jp/blog/archives/2137</link>
		<comments>http://www.syuhari.jp/blog/archives/2137#comments</comments>
		<pubDate>Thu, 20 May 2010 00:56:51 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[delegate]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[UIWebView]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2137</guid>
		<description><![CDATA[UIWebView のインスタンスに delegate を指定している場合は以下のように release する前に delegate に nil をセットする必要があります。

- (void) viewDidLoad {
    webView = [[UIWebView alloc] init];
    webView.delegate = self;
    ....
}

- (void)dealloc {
    webView.delegate = nil;
    [webView release];
}


アップルのマニュアルにも以下のように書かれています。
Important: Before releasing an instance of UIWebView for which you have set [...]]]></description>
			<content:encoded><![CDATA[<p>UIWebView のインスタンスに delegate を指定している場合は以下のように release する前に delegate に nil をセットする必要があります。</p>
<pre class="cpp" name="code">
- (void) viewDidLoad {
    webView = [[UIWebView alloc] init];
    webView.delegate = self;
    ....
}

- (void)dealloc {
    webView.delegate = nil;
    [webView release];
}
</pre>
<p><span id="more-2137"></span><br />
アップルのマニュアルにも以下のように書かれています。</p>
<blockquote><p>Important: Before releasing an instance of UIWebView for which you have set a delegate, you must first set its delegate property to nil. This can be done, for example, in your dealloc method.</p></blockquote>
<p>理由は UIWebView のロード処理が別スレッドで行われているために、release 後にデリゲートメソッドを呼ぶ可能性があるためだそうです。</p>
<p>以下のコードで実験してみました。UIWebView のインスタンスを生成後、loadRequest で読み込みます。その直後に UIWebView のインスタンスをリリースしてみました。そして、webView.delegate = nil を入れた時と入れないときの挙動を試してみるとわかりやすいです。</p>
<pre class="cpp" name="code">
- (void)viewDidLoad {
    [super viewDidLoad];

    UIWebView* webView = [[UIWebView alloc] init];
    [self.view addSubview:webView];
    webView.delegate = self;
    NSURL* url = [NSURL URLWithString:@"http://example.com"];
    [webView loadRequest:[NSURLRequest requestWithURL:url]];

    webView.delegate = nil;  // この行を入れた時と入れないときの挙動の違い
    [webView release];
}

- (void)webViewDidFinishLoad:(UIWebView *)_webView {
    NSLog(@"finish load");
}
</pre>
<p>delegate に nil を設定していないとデリゲートメソッドが呼ばれます。もし、このUIViewController のインスタンスが破棄されていればアプリが落ちてしまいます。</p>
<p>意図しないタイミングでデリゲートメソッドが呼ばれないために UIWebView のインスタンスをリリースする前にはデリゲートに nil をセットしなければいけないということです。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2137/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>[iPhone] UIView の小技 2つ</title>
		<link>http://www.syuhari.jp/blog/archives/2118</link>
		<comments>http://www.syuhari.jp/blog/archives/2118#comments</comments>
		<pubDate>Fri, 14 May 2010 21:11:25 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[Antialiasing]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Opacity]]></category>
		<category><![CDATA[UIView]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2118</guid>
		<description><![CDATA[iPhone OS3.0 から使用できる UIView の小技を2つ紹介。
※すべての画像はクリックで拡大表示できます。
Group Opacity
UIView 内にある重なった2つの UIImageView があるときに、UIView の alpha 値を下げると UIImageView が重なっている部分がお互いに透過されて見えてしまいます。（下図参照）


これだとカッコ悪いので重なっている部分をお互いに透過させずに、ひとつの画像のイメージで透過させる方法です。
info.plist に UIViewGroupOpacity を指定して、値を true にします。これで下図のように重なり部分がお互いに透過されずに表示されます。

Edge anti-aliasing
画像にアンチエリアシングをかける方法です。
赤い四角形の画像を45度回転させたときの図です。

これだとよく分からないので拡大してみました。

エッジがギザギザしています。
これにアンチエリアシングをかけるには info.plist に UIViewEdgeAntialiasing を追加して値を true にします。
以下が UIViewEdgeAntialiasing = true で実行した結果です。

同様に拡大してみました。

この2つは OS3.0 以上で使用可能です。
]]></description>
			<content:encoded><![CDATA[<p>iPhone OS3.0 から使用できる UIView の小技を2つ紹介。</p>
<p><strong>※すべての画像はクリックで拡大表示できます。</strong></p>
<h4>Group Opacity</h4>
<p>UIView 内にある重なった2つの UIImageView があるときに、UIView の alpha 値を下げると UIImageView が重なっている部分がお互いに透過されて見えてしまいます。（下図参照）<br />
<span id="more-2118"></span><br />
<a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/opacity_1.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/opacity_1-161x300.png" alt="opacity_1" title="opacity_1" width="161" height="300" class="alignnone size-medium wp-image-2119" /></a></p>
<p>これだとカッコ悪いので重なっている部分をお互いに透過させずに、ひとつの画像のイメージで透過させる方法です。<br />
info.plist に UIViewGroupOpacity を指定して、値を true にします。これで下図のように重なり部分がお互いに透過されずに表示されます。</p>
<p><a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/opacity_2.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/opacity_2-161x300.png" alt="opacity_2" title="opacity_2" width="161" height="300" class="alignnone size-medium wp-image-2120" /></a></p>
<h4>Edge anti-aliasing</h4>
<p>画像にアンチエリアシングをかける方法です。<br />
赤い四角形の画像を45度回転させたときの図です。</p>
<p><a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/antialiasing_1.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/antialiasing_1-161x300.png" alt="antialiasing_1" title="antialiasing_1" width="161" height="300" class="alignnone size-medium wp-image-2122" /></a></p>
<p>これだとよく分からないので拡大してみました。</p>
<p><a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/big_antialiasing_1.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/big_antialiasing_1-261x300.png" alt="big_antialiasing_1" title="big_antialiasing_1" width="261" height="300" class="alignnone size-medium wp-image-2123" /></a></p>
<p>エッジがギザギザしています。<br />
これにアンチエリアシングをかけるには info.plist に UIViewEdgeAntialiasing を追加して値を true にします。<br />
以下が UIViewEdgeAntialiasing = true で実行した結果です。</p>
<p><a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/antialiasing_2.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/antialiasing_2-161x300.png" alt="antialiasing_2" title="antialiasing_2" width="161" height="300" class="alignnone size-medium wp-image-2124" /></a></p>
<p>同様に拡大してみました。</p>
<p><a href="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/big_antialiasing_2.png" ><img src="http://www.syuhari.jp/blog/wp-content/uploads/2010/05/big_antialiasing_2-273x300.png" alt="big_antialiasing_2" title="big_antialiasing_2" width="273" height="300" class="alignnone size-medium wp-image-2125" /></a></p>
<p>この2つは OS3.0 以上で使用可能です。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2118/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[iPhone] Xcode3.2 で cocos2d の Device Build でエラーになる</title>
		<link>http://www.syuhari.jp/blog/archives/2102</link>
		<comments>http://www.syuhari.jp/blog/archives/2102#comments</comments>
		<pubDate>Fri, 23 Apr 2010 20:51:17 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[cocos2d]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Xcode]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2102</guid>
		<description><![CDATA[cocos2d の Device Build で以下のエラーがでました。シミュレータでは出ずに実機ビルドだけです。

The Info.plist  for application at /path/to/hoge.app specifies device capability requirements, which are not met by iPhone


先日、Xcode3.2 にやっとバージョンアップしたのですが、どうもそれが原因のようです。
info.plist にある、UIRequiredDeviceCapabilities の部分を削除したら実機ビルドできました。
参考サイト
Corrupt Info.plist « cocos2d for iPhone
]]></description>
			<content:encoded><![CDATA[<p>cocos2d の Device Build で以下のエラーがでました。シミュレータでは出ずに実機ビルドだけです。</p>
<div style="border:1px solid #666; padding: 3px">
The Info.plist  for application at /path/to/hoge.app specifies device capability requirements, which are not met by iPhone
</div>
<p><span id="more-2102"></span><br />
先日、Xcode3.2 にやっとバージョンアップしたのですが、どうもそれが原因のようです。<br />
info.plist にある、UIRequiredDeviceCapabilities の部分を削除したら実機ビルドできました。</p>
<p>参考サイト<br />
<a href="http://www.cocos2d-iphone.org/forum/topic/4602" target="_blank" class="liexternal">Corrupt Info.plist « cocos2d for iPhone</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2102/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[iPhone] UITableViewCell の高さを表示する内容によって変える方法</title>
		<link>http://www.syuhari.jp/blog/archives/2097</link>
		<comments>http://www.syuhari.jp/blog/archives/2097#comments</comments>
		<pubDate>Fri, 23 Apr 2010 08:17:26 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[UITableViewCell]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2097</guid>
		<description><![CDATA[Twitter クライアントのようにテーブルのセルの高さを表示するテキストの内容によって変える方法です。
UITableViewCell に UILabel を入れて、numberOfLines をゼロにします。numberOfLines をゼロにすると行数の制限がなくなります。
次に tableView: heightForRowAtIndexPath: で表示する行によって必要な高さを計算します。NSString を表示するサイズを計算するには、sizeWithFont:constrainedToSize:lineBreakMode: を使用します。


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  NSString* text = @"表示するテキスト";
  UIFont* font = [UIFont systemFontOfSize:12];
  // label は表示する UILabel
  CGSize size = CGSizeMake(label.size.width, 1000);
  CGSize textSize = [text sizeWithFont:font constrainedToSize:size lineBreakMode:UILineBreakModeCharacterWrap];

  float height = 50.0f; // セルの最低限の高さ

  [...]]]></description>
			<content:encoded><![CDATA[<p>Twitter クライアントのようにテーブルのセルの高さを表示するテキストの内容によって変える方法です。</p>
<p>UITableViewCell に UILabel を入れて、numberOfLines をゼロにします。numberOfLines をゼロにすると行数の制限がなくなります。</p>
<p>次に tableView: heightForRowAtIndexPath: で表示する行によって必要な高さを計算します。NSString を表示するサイズを計算するには、sizeWithFont:constrainedToSize:lineBreakMode: を使用します。<br />
<span id="more-2097"></span></p>
<pre class="cpp" name="code">
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  NSString* text = @"表示するテキスト";
  UIFont* font = [UIFont systemFontOfSize:12];
  // label は表示する UILabel
  CGSize size = CGSizeMake(label.size.width, 1000);
  CGSize textSize = [text sizeWithFont:font constrainedToSize:size lineBreakMode:UILineBreakModeCharacterWrap];

  float height = 50.0f; // セルの最低限の高さ

  // 元の UILabel よりも高さが高ければ高さを補正する
  float h = textSize.height - label.size.height;
  if (h > 0) {
	height += h;
  }
  return height;
}
</pre>
<p>最後に tableView: cellForRowAtIndexPath: で実際にセルに各値を入れるときに、UILabel の高さを上記の計算で出した高さに変更すれば OK です。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2097/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[iPhone] シェイク動作を簡単に取得する方法</title>
		<link>http://www.syuhari.jp/blog/archives/2089</link>
		<comments>http://www.syuhari.jp/blog/archives/2089#comments</comments>
		<pubDate>Mon, 19 Apr 2010 04:23:20 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[shake]]></category>
		<category><![CDATA[UIEvent]]></category>
		<category><![CDATA[UIResponder]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2089</guid>
		<description><![CDATA[iPhone OS3.0 から本体をシェイク（振る）すると Undo できるようになりました。OS3.0 以前では加速度センサをチェックすることで、シェイク動作をチェックすることができましたが、OS3.0 からは UIRespoer の motionEnded:withEvent: でシェイク動作を取得することができます。
UIEvent に以下のプロパティがあります。

@property(readonly) UIEventType type;
@property(readonly) UIEventSubtype subtype;


UIEventTypeMotion
UIEventSubtypeMotionShake


UIWindow でシェイクを感知
一番簡単にやるには、UIWindow のサブクラスを作成して、そこでチェックする方法です。

@implementation ShakeWindow
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
  if (event.type == UIEventTypeMotion &#038;&#038;
      motion == UIEventSubtypeMotionShake) {
    NSLog(@"shake!");
  }
}
@end

UIWindow クラスを使用している箇所を ShakeWindow クラスに変更すれば、シェイク動作を取得できます。
注意点は IB を使用しているときは AppDelegate だけでなく、MainWindow.xib の方も修正する必要があります。
UIView でシェイクを感知
UIWindow でシェイクを感知するとアプリケーション全体で常にシェイク動作を感知してしまいます。そこで必要なときにのみ感知するように、特定の UIView [...]]]></description>
			<content:encoded><![CDATA[<p>iPhone OS3.0 から本体をシェイク（振る）すると Undo できるようになりました。OS3.0 以前では加速度センサをチェックすることで、シェイク動作をチェックすることができましたが、OS3.0 からは UIRespoer の motionEnded:withEvent: でシェイク動作を取得することができます。</p>
<p>UIEvent に以下のプロパティがあります。</p>
<ul>
<li>@property(readonly) UIEventType type;</li>
<li>@property(readonly) UIEventSubtype subtype;</li>
</ul>
<ul>
<li>UIEventTypeMotion</li>
<li>UIEventSubtypeMotionShake</li>
</ul>
<p><span id="more-2089"></span></p>
<h4>UIWindow でシェイクを感知</h4>
<p>一番簡単にやるには、UIWindow のサブクラスを作成して、そこでチェックする方法です。</p>
<pre class="cpp" name="code">
@implementation ShakeWindow
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
  if (event.type == UIEventTypeMotion &#038;&#038;
      motion == UIEventSubtypeMotionShake) {
    NSLog(@"shake!");
  }
}
@end
</pre>
<p>UIWindow クラスを使用している箇所を ShakeWindow クラスに変更すれば、シェイク動作を取得できます。<br />
注意点は IB を使用しているときは AppDelegate だけでなく、MainWindow.xib の方も修正する必要があります。</p>
<h4>UIView でシェイクを感知</h4>
<p>UIWindow でシェイクを感知するとアプリケーション全体で常にシェイク動作を感知してしまいます。そこで必要なときにのみ感知するように、特定の UIView でのみ感知するようにしてみます。</p>
<p>まず、シェイク動作をチェックしたい UIView のサブクラス ShakeView を作成します。シェイク動作を検知するためにはファーストレスポンダにならないといけないので、canBecomeFirstResonder をオーバライドして YES を返します。</p>
<pre class="cpp" name="code">
@implementation ShakeView
- (BOOL)canBecomeFirstResponder {
	return YES;
}
@end
</pre>
<p>次に、UIViewController で ShakeView を addView して、motionEnded:withEvent: でシェイクを検知します。</p>
<pre class="cpp" name="code">
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
  if (event.type == UIEventTypeMotion &#038;&#038;
      motion == UIEventSubtypeMotionShake) {
    NSLog(@"shake!");
  }
}
- (void)viewDidLoad {
  [super viewDidLoad];

  ShakeView* shakeView = [[ShakeView alloc] init];
  shakeView.frame = self.view.bounds;
  [shakeView becomeFirstResponder];
  [self.view addSubview:shakeView];
  [shakeView release];
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2089/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>[iPhone] モーダルビューの非表示、値の受け渡しはデリゲートで行う</title>
		<link>http://www.syuhari.jp/blog/archives/2079</link>
		<comments>http://www.syuhari.jp/blog/archives/2079#comments</comments>
		<pubDate>Sun, 11 Apr 2010 08:02:58 +0000</pubDate>
		<dc:creator>matsuura</dc:creator>
				<category><![CDATA[iPhone/iPod touch]]></category>
		<category><![CDATA[delegate]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[ModalView]]></category>

		<guid isPermaLink="false">http://www.syuhari.jp/blog/?p=2079</guid>
		<description><![CDATA[iPhone でのモーダルビューの表示、非表示、値の受け渡し方法です。モーダルビューとは、下からニョキッと出てくるタイプの一時的なビューです。何か情報を入力させたりするのに使用します。
大事な点は、

モーダルビューの表示、非表示は両方共同じクラスでやること
値の受け渡しはデリゲートで行うこと

ということです。

サンプルでたまに見かけるのは、表示を親ビューでやり、非表示はモーダルビューの中でやっている方法です。この方法でもかまいませんが、より汎用的にするためにはデリゲートを使用して、モーダルビューを表示したビューコントローラで非表示も行うべきです。また、モーダルビューから値を渡すのもデリゲートを使用して行うべきです。
モーダルビューの例としては、UIImagePickerViewController があげられます。この UIImagePickerViewController からの値の受け取り方、モーダル表示、非表示の方法をみていただければ、上記の説明が理解しやすいかと思います。
実際の実装方法です。まず、モーダルビューとして表示されるビューのコントローラを作ります。UITextField だけのビューです。UITextField の入力値を渡すのに使用する ModalViewDelegate を作成します。UITextField で Return キーを押すと UITextField に入力した値を delegate で指定したクラスへ渡します。
ModalViewController.h

@protocol ModalViewDelegate
- (void) updateTextField:(NSString*) string;
@end

@interface ModalViewController : UIViewController &#60;UITextFieldDelegate&#62; {
  id delegate;
  IBOutlet UITextField* textField;
}
@property (nonatomic, retain) id delegate;
@end

ModalViewController.m

@implementation ModalViewController
@synthesize delegate;
- (void)viewDidLoad {
  [super viewDidLoad];
  textField.delegate = self;
  [textField becomeFirstResponder];
}

- (BOOL)textFieldShouldReturn:(UITextField *)_textField {
  [textField [...]]]></description>
			<content:encoded><![CDATA[<p>iPhone でのモーダルビューの表示、非表示、値の受け渡し方法です。モーダルビューとは、下からニョキッと出てくるタイプの一時的なビューです。何か情報を入力させたりするのに使用します。</p>
<p>大事な点は、</p>
<ul>
<li>モーダルビューの表示、非表示は両方共同じクラスでやること</li>
<li>値の受け渡しはデリゲートで行うこと</li>
</ul>
<p>ということです。<br />
<span id="more-2079"></span><br />
サンプルでたまに見かけるのは、表示を親ビューでやり、非表示はモーダルビューの中でやっている方法です。この方法でもかまいませんが、より汎用的にするためにはデリゲートを使用して、モーダルビューを表示したビューコントローラで非表示も行うべきです。また、モーダルビューから値を渡すのもデリゲートを使用して行うべきです。</p>
<p>モーダルビューの例としては、UIImagePickerViewController があげられます。この UIImagePickerViewController からの値の受け取り方、モーダル表示、非表示の方法をみていただければ、上記の説明が理解しやすいかと思います。</p>
<p>実際の実装方法です。まず、モーダルビューとして表示されるビューのコントローラを作ります。UITextField だけのビューです。UITextField の入力値を渡すのに使用する ModalViewDelegate を作成します。UITextField で Return キーを押すと UITextField に入力した値を delegate で指定したクラスへ渡します。</p>
<p>ModalViewController.h</p>
<pre class="cpp" name="code">
@protocol ModalViewDelegate
- (void) updateTextField:(NSString*) string;
@end

@interface ModalViewController : UIViewController &lt;UITextFieldDelegate&gt; {
  id delegate;
  IBOutlet UITextField* textField;
}
@property (nonatomic, retain) id delegate;
@end
</pre>
<p>ModalViewController.m</p>
<pre class="cpp" name="code">
@implementation ModalViewController
@synthesize delegate;
- (void)viewDidLoad {
  [super viewDidLoad];
  textField.delegate = self;
  [textField becomeFirstResponder];
}

- (BOOL)textFieldShouldReturn:(UITextField *)_textField {
  [textField resignFirstResponder];
  if ([delegate respondsToSelector:@selector(updateTextField:)]) {
    [delegate updateTextField:_textField.text];
  }
  return YES;
}

@end
</pre>
<p>今度は実際に ModalViewController をモーダル表示させる部分と、デリゲートを実装してその処理を作成します。モーダルビューからのデリゲート updateTextField: で値を受け取り、モーダルビューを非表示にします。<br />
ParentViewController.h</p>
<pre class="cpp" name="code">
@interface ParentViewController : UIViewController &lt;ModalViewDelegate&gt; {

}
</pre>
<pre class="cpp" name="code">
@implementation ParentViewController

- (void) updateTextField:(NSString *)string {
  NSLog(@"string=%@", string);
  [self dismissModalViewControllerAnimated:YES];
}

- (IBAction) start:(id) sender {
  ModalViewController* viewController = [[ModalViewController alloc] initWithNibName:@"ModalViewController" bundle:nil];
  viewController.delegate = self;
  [self presentModalViewController:viewController animated:YES];
  [viewController release];
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.syuhari.jp/blog/archives/2079/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
