Hatena::Groupiphone-dev

Ni chicha, ni limona - 平均から抜けられない僕

2009-07-31

[iPhone][tips] iPhoneアプリ開発時にフォント名を補完入力できるようにする 17:13  [iPhone][tips] iPhoneアプリ開発時にフォント名を補完入力できるようにする - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][tips] iPhoneアプリ開発時にフォント名を補完入力できるようにする - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][tips] iPhoneアプリ開発時にフォント名を補完入力できるようにする - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

若干誇張気味のタイトルですが・・・。


XcodeiPhoneアプリを作成していると、フォント名指定のところで「えーと、指定できるフォント名って何だっけ?」と、よく手が止まってしまいます。欲を言うならここで補完入力が効いてくれて、一覧から選べたりすると嬉しいんですが文字列なのでそうもいかず。


どうにかならないかなぁと常々思っていたのですが、ふと「ひょっとしたら力業でいけるかも?」と思い立ち、作ってみたのが次のコード。


   :
#define kKSFontArialMT  @"ArialMT"
#define kKSFontCourier  @"Courier"
   :

ハイ、単にフォント名をマクロ定義しただけなんですが、これが思いのほか便利。作業効率が上がりました。


そこでフォントファミリーも含めた全てのフォント情報をマクロ定義したヘッダファイルを作ってみましたので、ぜひ開発のお供にご利用くださいませ。


 カラーテーブル(KSFontMacros.hをzip圧縮)をダウンロードする


一応、iPhone OS3.0で増えた/改名したフォントフォントファミリーにも対応しています*1


ライセンスは一応MITライセンスとしておきますのが、大した情報ではないのでライセンス明記にはこだわりません。どうぞご自由に使用してください。

(そもそもマクロなのでバイナリには含まれず、無断使用しても分からないんですけどね)


いつも他愛もない情報ですみません。頑張ります。

*1:2.2.1で3.0用のマクロを使うとビルドエラーになるようにしておきました

2009-07-30

[iPhone][tips] UIAlertViewを別の場所に表示させる方法。 11:05  [iPhone][tips] UIAlertViewを別の場所に表示させる方法。 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][tips] UIAlertViewを別の場所に表示させる方法。 - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][tips] UIAlertViewを別の場所に表示させる方法。 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

UIAlertViewを使って表示させるUIを、任意の場所に表示させる方法です。元ネタは「Move alert(UIAlertView)」です。


方法はとても簡単で、UIAlertViewをインスタンス化した後にアフィン変換をかけてあげるだけ。

サンプルソースは以下のとおりです。ここではView-Based Applicationのコントローラクラスに作成しました。


@implementation MoveAlertViewController

- (void)viewDidLoad {
	// ボタンのタイプを指定できるメソッドがコンビニエンスメソッドしかないので、
	// 他のUIと同じ操作をすべく敢えてretainしています(なくても動作します。その場合は下のreleaseを削除)。
	UIButton *aButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
	aButton.frame = CGRectMake(105,180, 115, 35);
	[aButton setTitle:@"Tap" forState:UIControlStateNormal];
	[aButton addTarget:self	action:@selector(buttonPressed:)
	  forControlEvents:UIControlEventTouchUpInside];
	[self.view addSubview:aButton];
	[aButton release];
	
    [super viewDidLoad];
}

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

- (IBAction)buttonPressed:(id)sender {
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert"
                                                    message:@"Alert"
                                                    delegate:self
                                                    cancelButtonTitle:@"OK"
                                                    otherButtonTitles:@"NG",nil];
	// 後半2つの引数がx,yの移動量です。デフォルトの場所が0,0(->alert.transform)です。
	//  - この場合は「左へ200px, 上へ100px」です
	alert.transform = CGAffineTransformTranslate( alert.transform, 200.0, 100.0 );
	[alert show];
}

- (void)alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex {
	// do nothing.
}
@end

実行結果はこちら。


   f:id:paella:20090730110247j:image:h300

      OKが押せません・・・


使いどころはというと、・・・えーと、タブやツールバーなどで、操作画面の中央がずれているような場合に使えるのではないかと思います。

ご参考まで。

NonikNonik2012/08/08 20:22Your post is a teilmy contribution to the debate

dhfgdpnxxedhfgdpnxxe2012/08/10 03:46h8aCyQ <a href="http://tpvtkqcvnqsn.com/">tpvtkqcvnqsn</a>

2009-07-27

[iPhone][Develop] Grouped形式のテーブルに背景画像を設定する 19:56  [iPhone][Develop] Grouped形式のテーブルに背景画像を設定する - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][Develop] Grouped形式のテーブルに背景画像を設定する - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][Develop] Grouped形式のテーブルに背景画像を設定する - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

せっかく教えてもらった情報を独り占めしておくのは良くないなので、ここに記しておきます。

以下の情報は@tokidaさんに教えてもらった方法です(氏の記事はこちら)。@tokidaさん、これは素晴らしい情報です。ありがとうございます。

テーブルビューにGroupedを選択していると、背景には縦ストライプの、あまりパッとしない絵が表示されます。標準のUIだけを使ってアプリを作成していれば何となく合うんでしょうが、独自のアプリを作っているような場合には合わないような、なんとも微妙な柄です。


これをうまく変えられないかな、と思っていたら、@tokidaさんに「UIColorの+colorWithPatternImageを使えば良いですよ」と教えてもらいました。

こんな感じのソースです。

- (void)loadView {
	[super loadView];

	UIColor *col = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"backgroundbar.png"]];
	[self.tableView setBackgroundColor:col];
	[col release];
		:

その結果は以下のとおり。

      f:id:paella:20090727194902p:image


・・・イメージをガラリと変えることが出来ました。素晴らしい!!

今後も使うことの多いメソッドになりそうです。


参考図書

このメソッドの説明、私の読んだSDK本の範囲では「iPhoneアプリケーションプログラミング*1」にのみ記載がありました(p.181)。

この本にはUIColorのそれ以外のメソッドについても色々と紹介されていますので(たとえば+groupTableCiewBackgroundColorなんてご存じでした?)、けっこう重宝しています。


  「iPhoneアプリケーションプログラミング

   ※私のAmazonインスタントストアへのリンクです


Special Thanks

@tokidaさん

*1:Amazonインスタントストアへのリンクです。御了承ください。

FlakitaFlakita2013/01/20 18:19Franlky I think that's absolutely good stuff.

rhhhcgrhhhcg2013/01/23 04:42CpyMT5 <a href="http://vkwbwulpdgew.com/">vkwbwulpdgew</a>

2009-07-23

[iPhone] テーブルのスクロールが遅いので高速化に挑戦中(苦戦中) 23:44  [iPhone] テーブルのスクロールが遅いので高速化に挑戦中(苦戦中) - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone] テーブルのスクロールが遅いので高速化に挑戦中(苦戦中) - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone] テーブルのスクロールが遅いので高速化に挑戦中(苦戦中) - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

※@hiroaki310さんのレビューを反映させたコードもアップしました。本当にありがとうございます。

※@hirobeさんのコメントで有益な情報を得ました。ズルズルの原因はcellForRowAtIndexPath メソッド(+その後のセットアップ)の処理に時間がかかってしまうことのようです。コメントにあるように、ダミーのUIViewを用意して貼り付けておくと、だいぶん改善するようです。ありがとうございます!


現在作成中のアプリではテーブルビューを使う予定です。ところが実装して動かしてみると、スクロールさせたときの挙動がスムーズではありません。

本来なら「スルスル」とした感じでスクロールしてくれると思うのですが、実機上では「ズルッズルズルッ」といった具合に引っかかりがあり、イマイチ気持ちよくないUIになってしまっています。


テーブル内の各セルはビューコントローラの中で独自のものを作成しています。既存のものでは表示できない内容を表示させていることと、独自xibによるセルだと遅すぎて(ズ・・ズズズ・・・みたい)まともに動かないことで、その中間を狙って実装しました。

しかしそれでも遅い。


そこでテーブル高速化の常套手段:


  • セル内のビューを出来るだけ少なくする
  • セル内で半透明になっているものを不透明にする
  • セル内でのビューの重なりを避ける
  • テーブル動作中のデリゲートメソッドを出来るだけ減らす
  • テーブルの高さを高くする

などを試したのですが、どれも殆ど効果がありませんでした。


・・・で、「困った困った」とTwitterでつぶやいていたら、何人もの方*1にアドバイスをもらい、


 「Core Graphicsを使えばCPUの代わりにGPUで描いてくれるので、スクロールもスムーズになる」


といった趣旨の結論を得るに至りました。そこで教えてもらった参考サイトのプロジェクトファイル(リンク先)をベースに


  1. コントローラクラスの中でUITableViewCellクラスにビューを追加
  2. UITableViewCellクラスのサブクラスを作成してテーブルのセルに使用
  3. UITableViewCellクラスのサブクラスだけど、描画にはCoreGraphicsを使用

という3種類の方法でテーブルを実装し、動かしてみることにしました。


  サンプルプロジェクトをダウンロードする

   (修正前です。何が変わったかを比較したい方向け)

  サンプルプロジェクト(修正版)をダウンロードする

   (こちらが最新版。info.plistを変更して使ってください)


「これでうまく確認できる!」と思っていたのですが・・・

サンプルプログラムを実際に動かしてみると分かりますが、上記1-3のどれも殆ど同じでスベスベスクロールをしてくれました。orz

確かにCoreGraphicsが若干速いものの、殆ど誤差の範囲です・・・。じゃあどうして自作アプリのときはあんなにも遅いんだろう??


というわけで、今もって自アプリで遅い原因を調査中です。

何か分かったら、高速化できたらまた書きます。


長々と書いておきながらまだ解決していないという展開で、失礼しました。

*1:@takuma104さん、@cqa02303さん、@satokoさん、@hiroakiさん、@norio_nomuraさん、@onkn101さん、@khirohisさん、@kimadaさん、ありがとうございました。

@hiroaki310@hiroaki3102009/07/24 00:43ソース拝見しました。少し気になったことがありますので、以下に記させて頂きます。
メモリ管理上、不要なメモリの確保や解放し忘れ(リーク)が多いような気がします。

- FastTableViewCell.h
- プロパティをcopyで定義していますが、retainの方が早いのではないでしょうか?

- FastTableViewCell.m
- firstTextやlastTextプロパティへのセットはself.をつけないとダメじゃないでしょうか?
- firstTextやlastTextプロパティに s をセットする時にわざわざcopyする必要はないんじゃないでしょうか?
- drawAtPointする際に渡すUIFontを、わざわざstaticに持ってそれをセットする必要はないと思います。

- NormalTableViewCell.h
- プロパティをcopyで定義していますが、retainの方が早いのではないでしょうか?

- NormalTableViewCell.m
- firstTextLabelやlastTextLabelプロパティへの代入は self. をつけないとダメじゃないでしょうか?
- firstTextLabelやlastTextLabelをcontentViewにaddSubviewした後にリリースしていないようです。(この実装であれば、alloc/initWithFrameの後でautoreleaseした方がいいかもです。)
- UILableのfontプロパティは、それ自身がretainしてくれるので、わざわざUIFontをretainしたものをstaticに持ってそれをセットする必要はないと思います。
- 以下のような実装の方がいいと思います。
self.firstTextLabel = [[[UILabel alloc] initWithFrame:firstTextLabelRect] autorelease];
firstTextLabel.font = [UIFont systemFontOfSize:20];
[self.contentView addSubview:firstTextLabel];

- NormalView2Controller.m
- lastTextLabelをaddSubviewした後にreleaseしていないようです。

paellapaella2009/07/24 11:22コメント、というよりもレビューしていただいて恐縮です。

> FastTableViewCell.h
> - プロパティをcopyで定義していますが、retainの方が早いのではないでしょうか?
確かにそうですね。ここはオリジナルのファイルのままを使っていましたが、変えた方が良いですね。setFirst/LastTextメソッドは用意されていますので、
@property (nonatomic, retain) NSString *firstText;
としておきます(retainは警告つぶし)。そして、同セッターについては
[s retain]
[firstText release];
firstText = s;
[self setNeedsDisplay];
として、retain形式で保持するようにしました。コレによって、

> - firstTextやlastTextプロパティに s をセットする時にわざわざcopyする必要はないんじゃないでしょうか?
は解決出来たと思います。コピーは確かに不要ですね。

> - FastTableViewCell.m
> - firstTextやlastTextプロパティへのセットはself.をつけないとダメじゃないでしょうか?
これはセッター内でのことだと思いますが、ここでselfを付けてしまうとプロパティによって無限ループが発生してしまうので、あえて外してあると思っています。
勘違いしていたらすみません。

> - drawAtPointする際に渡すUIFontを、わざわざstaticに持ってそれをセットする必要はないと思います。
staticでUIFontを書いているのは、コンビニエンスメソッドのautoreleaseによるオーバーヘッドを避けてのものではないかな、と推測しています。オリジナルのままなので推測ですが。

> - NormalTableViewCell.h
> - プロパティをcopyで定義していますが、retainの方が早いのではないでしょうか?
そうですね。オリジナルとの比較がしやすいように合わせましたが、無意味でした。

@property (nonatomic, retain) UILabel *firstTextLabel;
@property (nonatomic, retain) UILabel *lastTextLabel;

に変更です。

> - firstTextLabelやlastTextLabelプロパティへの代入は self. をつけないとダメじゃないでしょうか?
ここは私のミスでした。付けます。

> - firstTextLabelやlastTextLabelをcontentViewにaddSubviewした後にリリースしていないようです。(この実装であれば、alloc/initWithFrameの後でautoreleaseした方がいいかもです。)
> - UILableのfontプロパティは、それ自身がretainしてくれるので、わざわざUIFontをretainしたものをstaticに持ってそれをセットする必要はないと思います。
ここはNormalTableViewCellセルクラスのメンバーであって、所有権は破棄していないことを明記したくて意図的に残しました。
あと、UIFontは確かにstaticで持つ必要は全然無いですが、オリジナルと合わせた方向で,というのを優先したのは事実です。
しかしdeallocメソッド内でreleaseされていないのは問題なので,リリースしておきます。

ということで、修正版を本記事中に改めてアップしておきます。
ありがとうございました。

@hiroaki310@hiroaki3102009/07/27 11:17>> - FastTableViewCell.m
>> - firstTextやlastTextプロパティへのセットはself.をつけないとダメじゃないでしょうか?
>これはセッター内でのことだと思いますが、...

すみません、これ、私の勘違いです。setterでしたね。大変、失礼しました。m(_ _)m

>> - firstTextLabelやlastTextLabelをcontentViewにaddSubviewした後にリリースしていないようです。
>ここはNormalTableViewCellセルクラスのメンバーであって、所有権は破棄していないことを明記したくて意図的に残しました。

そうでしたか。そういう意味では、firstTextLabelとlastTextLabelプロパティをretainじゃなくてassignで宣言しないとリークしちゃいそうですね。リファレンスカウンタが2個になると思うので。。(もし、self.を付けてセットするように変更する場合は、です。。)

色々と余計なコメントしてしまって逆にお時間とらせてしまったようで失礼しました。
これからもどうぞヨロシクお願いします。

paellapaella2009/07/27 19:00いいえ、こちらこそ色々と参考になったので助かりました。

> そうでしたか。そういう意味では、firstTextLabelとlastTextLabelプロパティをretainじゃなくてassignで宣言しないとリークしちゃいそうですね。リファレンスカウンタが2個になると思うので。。(もし、 self.を付けてセットするように変更する場合は、です。。)

そうですね。self.と付けるのと付けないのとで挙動が変わるコードはメンテナンス性が著しく落ちると思いますので、retainではなくassignにした方がいいですね。

いずれにせよ、助かっています。ありがとうございます。

hirogramhirogram2009/07/28 22:24わたしもズルズルスクロールで試行錯誤中です。
試した限りでは、ダミーのUIViewを用意して、Cellに張る予定のViewを先にダミーUIVewに張っておくとズルズルを回避できるようです。ただし、テーブルビュー自体の初期商事が遅くなるので、別スレッドでやるなどの対処が必要そうです。メモリ的にOKかNGかとかは未検証ですが。

paellapaella2009/07/29 16:18id:hirogramさん、貴重な情報を教えていただいて、ありがとうございます。

別のビューに貼り付けておくとズルズルが回避出来る、というのは朗報です。
これはテーブル内で使われる全セルの、全ビューということでしょうか。

余談ですが, UIへの処理を別スレッドでやるのは危険なので、初期処理が遅くなるのはしょうがないと諦めた方が良いかもです。

hirogramhirogram2009/08/05 01:33hirogramこと@hirobeです。
要は、cellForRowAtIndexPathが呼ばれるのが画面に出る直前なので、そこでの処理に手間取るとズルズルするようです。なので全ビューというよりは描画の遅そうなビューを対象とするとよいと思います。
セルについては全セルですが、データが多い場合は以下にあるようなページング処理と組み合わせるとよいかと。
http://d.hatena.ne.jp/KishikawaKatsumi/20090118/1232224534

heightForRowAtIndexPathがreload時に呼ばれるので、私はそこでビューをダミーUIViewに貼付けるなどしています。
別スレッドはご指摘の通り、うまくいきませんでした。

あと、グループを使うと一番上のセクションヘッダがスクロールに逆らおうとするアニメーション(?)で少し遅くなるような気がしています。セクションヘッダを使わないのも一つの手のようです。

paellapaella2009/08/11 15:22hirogramさん、返事が大幅に遅くなってしまってすみません。

色々とありがとうございます。ずいぶん掘り下げた調査をされているようで、とてもためになります。

表示のための準備処理が遅くなるとずるずるする、ということは果たしてセルの準備がボトルネックであるということですね。ここをできるだけ速くするように頑張ってみます。

それにしても、3.0だと幾つかの高速なスタイルが使えるので楽ちんになりましたね。互換性がない、というのが本当にネックですが・・・。

ChynaChyna2011/09/16 14:13Always the best content from these prodigious wrtires.

fhidfodmfhidfodm2011/09/16 21:21ACGU6E <a href="http://adezyoxivecp.com/">adezyoxivecp</a>

iuvtuyxwswziuvtuyxwswz2011/09/17 00:48g7bH92 , [url=http://aowajsamsbeg.com/]aowajsamsbeg[/url], [link=http://nhjcorppwbkv.com/]nhjcorppwbkv[/link], http://qmkvwdwikygg.com/

lfywczlfywcz2011/09/18 23:32ZCDUQA <a href="http://gmipmimfdzwd.com/">gmipmimfdzwd</a>

nsephopsfnsephopsf2011/09/19 20:09rCmbdQ , [url=http://hszuyduvmgjv.com/]hszuyduvmgjv[/url], [link=http://eycjthyxcyvk.com/]eycjthyxcyvk[/link], http://vfuxwdhqhvuf.com/

EstelaEstela2013/01/22 21:48Life is short, and this atrilce saved valuable time on this Earth.

lpvofflpvoff2013/01/25 00:38LeM0GH , [url=http://vcpbhgrhxamd.com/]vcpbhgrhxamd[/url], [link=http://rgiaxdceqhkn.com/]rgiaxdceqhkn[/link], http://hhnnjmulwtdh.com/

nzltynshrdqnzltynshrdq2013/01/26 11:352MNhSa , [url=http://qrcauybfhfcl.com/]qrcauybfhfcl[/url], [link=http://yrqpsjnmrlxx.com/]yrqpsjnmrlxx[/link], http://jubcgaqhxmml.com/

2009-07-22

[iPhone][Develop] UITableViewDelegateのメソッドを自分なりにまとめてみた 22:55  [iPhone][Develop] UITableViewDelegateのメソッドを自分なりにまとめてみた - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone][Develop] UITableViewDelegateのメソッドを自分なりにまとめてみた - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone][Develop] UITableViewDelegateのメソッドを自分なりにまとめてみた - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

UITableViewのデリゲートメソッドについて、自分なりにまとめてみました。

  • 各メソッドがサポートするバージョン
  • 各メソッドがいつ呼ばれるか

をポイントにしています。ご参考になれば幸いです。


役割

テーブルビューを表示する時の、テーブルビュー構築に必要なプロパティを伝えてあげること。

※データソースは、テーブルビュー内で表示する情報を渡したり、テーブルビュー上の情報の変化をデータに反映させるためのもの。


必須メソッド

UITableView.h上で「@required」と表記されているもの。このメソッドがデリゲートを担当するクラスで定義されていないとビルドが通らない。


・・・はありませんでした。デリゲート無しでも動きはするよ、ということです。


オプションメソッド

UITableView.h上で「@optional」と表記されているもの。このメソッドが無くても、動く。でも細かい制御をしたい場合には必要。

こちらは用途に応じたメソッドがいっぱいありました。


■表示を変更したいとき
メソッド名2.2.13.0内容いつ呼ばれるか
- (void)tableView:(UITableView *) willDisplayCell:(UITableViewCell *) forRowAtIndexPath:(NSIndexPath *)セルが表示される直前に呼ばれるメソッド各セルが表示されるたび、何度も

■セル等の高さを決定
メソッド名2.2.13.0内容いつ呼ばれるか
- (CGFloat)tableView:(UITableView *) heightForRowAtIndexPath:(NSIndexPath *)各セルの高さを決めるテーブル表示時に各セルで1回だけ
- (CGFloat)tableView:(UITableView *) heightForHeaderInSection:(NSInteger)当該セクションのヘッダの高さを決めるテーブル表示時に各セクションで1回だけ
- (CGFloat)tableView:(UITableView *) heightForFooterInSection:(NSInteger)当該セクションのフッタの高さを決めるテーブル表示時に各セクションで1回だけ

■セクションのヘッダやフッタの情報決定

ここで決められた情報はtitleプロパティよりも優先されます。

メソッド名2.2.13.0内容いつ呼ばれるか
- (UIView *)tableView:(UITableView *) viewForHeaderInSection:(NSInteger)当該セクションのヘッダに表示するビューを決定テーブル表示時に各セクションで1回だけ
- (UIView *)tableView:(UITableView *) viewForFooterInSection:(NSInteger)当該セクションのフッタに表示するビューを決定テーブル表示時に各セクションで1回だけ

■アクセサリ領域(セルの右側)の構成決定
メソッド名2.2.13.0内容いつ呼ばれるか
- (UITableViewCellAccessoryType)tableView:(UITableView *) accessoryTypeForRowWithIndexPath:(NSIndexPath *)アクセサリ領域に何を表示するか各セルが表示されるたび、何度も
- (void)tableView:(UITableView *) accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)アクセサリ領域のボタンがタップされたときのイベントハンドラアクセサリ領域のボタンがタップされたとき

■選択

選択系はwill→didの順で呼ばれます。

メソッド名2.2.13.0内容いつ呼ばれるか
- (NSIndexPath *)tableView:(UITableView *) willSelectRowAtIndexPath:(NSIndexPath *)当該セルが選択された直後(didSelectRowAtIndexPathの直前)のイベントハンドラセルが選択されたとき
- (NSIndexPath *)tableView:(UITableView *) willDeselectRowAtIndexPath:(NSIndexPath *)×当該セルが選択解除された直後(didDeselectRowAtIndexPathの直前)のイベントハンドラセルが選択解除されたとき
- (void)tableView:(UITableView *) didSelectRowAtIndexPath:(NSIndexPath *)当該セルが選択解除された直後のイベントハンドラセルが選択されたとき
- (void)tableView:(UITableView *) didDeselectRowAtIndexPath:(NSIndexPath *)×当該セルが選択解除された直後のイベントハンドラセルが選択解除されたとき

■編集
メソッド名2.2.13.0内容いつ呼ばれるか
- (UITableViewCellEditingStyle)tableView:(UITableView *) editingStyleForRowAtIndexPath:(NSIndexPath *)当該セルが編集状態になったときに左側に表示するアイコン(挿入/削除/なし)editingプロパティをYESにしたときに、各セルで
- (NSString *)tableView:(UITableView *) titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)×当該セルを削除するときの、「Delete」の代わりに表示する文字列editingプロパティをYESにしたときに、各セルで(削除の場合)
- (BOOL)tableView:(UITableView *) shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)当該セルが編集状態になったときにセルをインデントするかどうかeditingプロパティをYESにしたときに、各セルで
- (void)tableView:(UITableView*) willBeginEditingRowAtIndexPath:(NSIndexPath *)当該セルをスワイプして編集状態にした直後(Deleteボタンが表示される前)のイベントハンドラセルをスワイプしてeditingプロパティをYESにしたとき
- (void)tableView:(UITableView*) didEndEditingRowAtIndexPath:(NSIndexPath *)当該セルのスワイプによる編集状態を解除した直後のイベントハンドラセルをスワイプして編集した後

■移動/ソートの振る舞い
メソッド名2.2.13.0内容いつ呼ばれるか
- (NSIndexPath *)tableView:(UITableView *) targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *) toProposedIndexPath:(NSIndexPath *)当該セルをドラッグした後の、妥当なインデックスを決定セルをドラッグして移動した後

■インデント量
メソッド名2.2.13.0内容いつ呼ばれるか
- (NSInteger)tableView:(UITableView *) indentationLevelForRowAtIndexPath:(NSIndexPath *)当該セルをインデントするときの深さeditingプロパティをYESにしたときに、各セルで

まとめ

デリゲートだけで結構色々あるので、データソースの方は挫折してしまいました。ごめんなさい。また気が向いたらやります。


この表を作る時に参考にした書籍

ちなみにですが、このテーブルを作る際は書籍「iPhoneアプリケーションプログラミング*1」を参考にしました。


  「iPhoneアプリケーションプログラミング

   ※Amazonインスタントストアへのリンクです


この本は日本語がおかしい部分があるものの、リファレンスとして活用できるようになったときに一番役に立つ本です。各クラスの主要なメソッドが一覧として書かれているので、最近何かをしたいときにとりあえず手元に置くようになっています。

はじめてのiPhoneプログラミング*2」がチュートリアルだとすれば、こちらはリファレンスですね。


特筆すべきは、はじめての〜よりこちらの方が、UITableViewCellを使う時に行儀の良くてスピードの出る書き方をしていることです。はじめての〜だけを読んでいたボクは、「テーブルはやっぱり遅いなぁ」という固定観念を持ってしまっていました。

危なかったです。


不明点や間違っている部分があれば教えてください。宜しくお願いします。

*1Amazonインスタントストアへのリンクです

*2Amazonインスタントストアへのリンクです

LuisLuis2012/05/30 12:22This is exactly what I was looinkg for. Thanks for writing!

kcqrzggwkcqrzggw2012/05/30 18:547cD2b3 <a href="http://shckrerkmrce.com/">shckrerkmrce</a>

qpahajvwnqpahajvwn2012/05/31 23:08tpfioi <a href="http://ilhtpfxfmarg.com/">ilhtpfxfmarg</a>

dsrvwihwdsrvwihw2012/06/01 21:21Zpq1e6 , [url=http://lmkchwjsnmnt.com/]lmkchwjsnmnt[/url], [link=http://vqajdhrnabhp.com/]vqajdhrnabhp[/link], http://ghuczrchtljr.com/

2009-07-14

[iPhone] UITableViewのスクロールバーを任意の画像に差し替える方法 01:51  [iPhone] UITableViewのスクロールバーを任意の画像に差し替える方法 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [iPhone] UITableViewのスクロールバーを任意の画像に差し替える方法 - Ni chicha, ni limona - 平均から抜けられない僕  [iPhone] UITableViewのスクロールバーを任意の画像に差し替える方法 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

※注意※

今回の記事は未申請の方法ですので、ひょっとすると審査に通らなくなるかもしれません。戻すのは簡単ですのでリスクは少ないですが、ご利用は計画的にお願いします。(@cqa02303さん、ご指摘ありがとうございました)


UITableViewをスクロールさせると、画面の右側にスクロールバーが表示されます。この画像を変更する方法が分かりました。


UITableViewは幾つかのSubviewを持っていて、そのうちの1つがスクロールバーを表すUIImageViewですので、そのイメージを差し替えるだけです。

	for (UIView *view in [self.tableView subviews]) {
		if ([view class] == [UIImageView class]) {
			UIImageView *v = (UIImageView *)view;
			v.image = [UIImage imageNamed:@"scrollbar.png"];
		}
	}

こうすることで、たとえば下の画像のようにスクロールバーの見た目を変更できます。


    f:id:paella:20090715013937p:image:medium


使いどころが難しいとは思いますが、自分のUIに統一性を持たせたい時に活用すると良いのではないかと。


どうやってこのビューを見つけたか

ちなみにこのビューをどうやって見つけたかを記しておきます。


・・・とはいっても簡単で、tableViewは複数のサブビューを持っているという話をエリカ本で読んだので、subviewsメソッドで1つ1つを取り出し、そのクラス名を出力しただけです。


そのときのソースコードは以下のとおり。

	for (UIView *view in [self.tableView subviews]) {
		NSLog(@"Class name is %@", [[view class] description]);
	}

これを実行させると、

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UITableViewCell

XXXX Class name is UIImageView ← コレ!!

という出力が得られます。

そして「最後のは何?」ということで取りあえず画像を突っ込んでみたら分かった、という流れです。


ご参考まで。

参考にした本

以下のAmazonインスタントストアで紹介した本を参考にしました。特にエリカ本と、iPhoneアプリケーションプログラミングの2冊は今回お世話になリました。


 「中級者にオススメだと言えるiPhoneプログラミング の関連図書Amazonストアへのリンク)」

BabyLarsBabyLars2012/02/06 08:30Ah, i see. Well that's not too trkicy at all!"

nokghmmfcjunokghmmfcju2012/02/07 18:31q59JOD <a href="http://ozrvtootmlvk.com/">ozrvtootmlvk</a>

druadyukndruadyukn2012/02/09 20:42oY5RLX , [url=http://gaswkylvmrom.com/]gaswkylvmrom[/url], [link=http://ydyhbqoivamv.com/]ydyhbqoivamv[/link], http://tgmbyruogedd.com/

zwrtghbnzwrtghbn2012/02/11 01:03xWg1dJ <a href="http://vynxoammiroy.com/">vynxoammiroy</a>

xohryvzkxohryvzk2012/02/12 02:04XXT06w , [url=http://jccgnynoddwm.com/]jccgnynoddwm[/url], [link=http://kznpulcczjyp.com/]kznpulcczjyp[/link], http://uaqadpjfesdd.com/

2009-07-10

[疑問] 解決!→UITableViewのサイズをアプリ動作中に変更する方法が分からない 13:33  [疑問] 解決!→UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [疑問] 解決!→UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕  [疑問] 解決!→UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

前日の日記:

[疑問] UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕 - iPhoneアプリ開発グループ

で書いていた、テーブルビューのサイズ変更をするとテーブル表示がおかしくなるという問題が、その原因とともに解決したので記録を残しておきます。


以下が修正後のソースです(実際はもう少し手を入れましたが、今回は違いが分かるように同じソースを使っています)。


- (void)toggleEdit:(UIBarButtonItem *)sender {
	NSLog(@"toggleEdit: is called by %@", sender);
	[self.tableView setEditing:!self.tableView.editing animated:YES];
	// User interfaceの向上(削除中は右上ボタンを「完了」に変更)
	if (self.tableView.editing) {
		// [self.tableView beginUpdates]; ← この処理を書いてはいけなかった!
		self.navigationItem.rightBarButtonItem.style = UIBarButtonItemStyleDone;
		self.navigationItem.rightBarButtonItem.title = @"Done";
	} else {
		// [self.tableView endUpdates]; ← この処理を書いてはいけなかった!
		self.navigationItem.rightBarButtonItem.style = UIBarButtonItemStyleBordered;
		self.navigationItem.rightBarButtonItem.title = kEditButtonMessage;
	}
	
	// ツールバーのフレームイン/アウト
	[UIView beginAnimations:@"Move in/out toolbar" context:nil];
	if (self.tableView.editing) {
		_toolBar.frame = CGRectMake(0.0f, 395.0f, 320.0f, 36.0f);
		self.tableView.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 370.0f); // 3の処理
		[self.tableView reloadData];
	} else {
		_toolBar.frame = CGRectMake(0.0f, 480.0f, 320.0f, 36.0f);
		self.tableView.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 406.0f); // 4の処理
		[self.tableView reloadData];
	}
	[UIView commitAnimations];
}

ということで、テーブルビューに対して

 「Edit開始でbeginUpdates」

 「Edit終了でendUpdates」

という処理を行わせていたことが悪かったようです。


これらのメソッドはテーブルの情報を実際に変更しているコードの前後で書いてあげればよく、上記ソースのようにイベントをまたぐような大きな処理で使わせるものではありませんでした。

これを消すことで、ものの見事に動くようになりました。


お騒がせいたしました。


たしかこれ、エリカ本で書かれていた方法なんだよなぁ・・・。

情報が間違っているのか、それとも少しずつ情報が古くなっているのか。公式ドキュメントも含めて、記述されている情報を鵜呑みにしてはいけないという好例になってしまいました。


参考サイト

 ・テーブルのセルの削除や追加にbeginUpdates/endUpdatesは必要か(1) - iPhoneアプリ開発まっしぐら★ - iPhoneアプリ開発グループ

 ・テーブルのセルの削除や追加にbeginUpdates/endUpdatesは必要か(2) - iPhoneアプリ開発まっしぐら★ - iPhoneアプリ開発グループ


上記のサイトで「もしかしてひょっとして」と気づきました。多謝です。

あえて付け加えるなら、


「beginUpdatesとendUpdatesは、複数のセル情報を一度に入れ替える場合にのみ必要」


といったところですかね。


Thanks

kouichiさん、ohnoさん、有益なコメントをありがとうございました。問題解決のヒントになっただけでなく、知識も広げられました。

平野平野2009/12/22 09:23NavigationControllerを使用しているTableViewControllerで次のようにするとtoolbarが表示されます。tableViewのサイズは自動的に変わります。

- (void)viewWillAppear:(BOOL)animated {
self.toolbarItems = toolbarButtons;
self.navigationController.toolbarHidden = NO;
}

私がやったところでは、本記事の方法ではうまく行きませんでした。

paellapaella2009/12/23 01:15コメントありがとうございます。
toolbarItemsはOS3.0から導入されたプロパティですね。私はまだ2.2.1をDeployment Targetにしているためこの方法は使えないですが、将来のために参考にさせていただきます。

貴重な情報、ありがとうございました。

whaison@me.comwhaison@me.com2011/05/03 20:34貴重な情報ありがとうございます。参考にさせていただいています。
Tableviewのサイズを変更できずに私も困っています。
上記方法でも変更できませんでした。
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.rowHeight=128.0;
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
self.tableView.autoresizingMask);
//self.tableView.frame = CGRectMake(100,100,320,100);//NG
self.tableView.bounds = CGRectMake(100.0f, 100.0f, 320.0f, 370.0f); // 3の処理
[self.tableView reloadData];
}

paellapaella2011/05/03 20:58whaison@me.comさん、コメントありがとうございます。
1つ簡単なトリックとして、テーブルビューを置く時はUIViewを下に一枚敷いた上でウィンドウに配置すると、UIView(テーブルビューではない)のサイズ変更に対して上手に追随してくれてサイズ変更も容易、という方法があります。
いかがでしょうか?

SharleenaSharleena2011/09/16 18:02This makes everything so complteely painless.

vpecwmfnvpecwmfn2011/09/16 20:55nvgnT6 <a href="http://ehurocfnmuuq.com/">ehurocfnmuuq</a>

pluuyapluuya2011/09/19 00:49uYzEuZ <a href="http://rvhifqyqjzet.com/">rvhifqyqjzet</a>

2009-07-09

[疑問] UITableViewのサイズをアプリ動作中に変更する方法が分からない 20:20  [疑問] UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [疑問] UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕  [疑問] UITableViewのサイズをアプリ動作中に変更する方法が分からない - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

今、タイトルのことで悩んでいます。

やろうとしていることは、


  1. ナビゲーションバー付きのテーブルビューを最初に表示しておいて、ナビゲーションバー上には「Edit」ボタンを付けておく
  2. 「Edit」ボタンが押されたら、隠しておいたツールバー(UIToolBar)を表示させて、編集画面に移行する
  3. このツールバーを表示させたとき、テーブルビューの大きさをツールバーぶん縮める(でないとツールバーに隠れる最後の方の行を編集できないため)
  4. 「Edit」ボタン(UIではDoneに変えてます)をもう一度押すと、ツールバーは隠れてテーブルビューも元の大きさに戻る。

という処理。Safariブックマーク編集のときのようなイメージを持ってもらうと良いかもしれないです。


ところが、上記の3のときに縮めたテーブルビューが行全体の一部しか表示しなくなってしまう問題に当たってしまいました。たとえば全体で20行程度のテーブルを表示させているときに3で縮めると、今画面上に表示されているぶんはそのまま残りつつも、残りの行が何も表示されなくなってしまうのです(スクロールは20行ぶんは行えるみたい)。

ただし4の処理を行えば、また元通りです。


どなたか同じような症状に陥った方っていますか?

ちなみに「Edit」を押したときの処理はこんな風にしています。

- (void)toggleEdit:(UIBarButtonItem *)sender {
	NSLog(@"toggleEdit: is called by %@", sender);
	[self.tableView setEditing:!self.tableView.editing animated:YES];
	// User interfaceの向上(削除中は右上ボタンを「完了」に変更)
	if (self.tableView.editing) {
		[self.tableView beginUpdates];
		self.navigationItem.rightBarButtonItem.style = UIBarButtonItemStyleDone;
		self.navigationItem.rightBarButtonItem.title = @"Done";
	} else {
		[self.tableView endUpdates];
		self.navigationItem.rightBarButtonItem.style = UIBarButtonItemStyleBordered;
		self.navigationItem.rightBarButtonItem.title = kEditButtonMessage;
	}
	
	// ツールバーのフレームイン/アウト
	[UIView beginAnimations:@"Move in/out toolbar" context:nil];
	if (self.tableView.editing) {
		_toolBar.frame = CGRectMake(0.0f, 395.0f, 320.0f, 36.0f);
		self.tableView.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 370.0f); // 3の処理
		[self.tableView reloadData];
	} else {
		_toolBar.frame = CGRectMake(0.0f, 480.0f, 320.0f, 36.0f);
		self.tableView.bounds = CGRectMake(0.0f, 0.0f, 320.0f, 406.0f); // 4の処理
		[self.tableView reloadData];
	}
	[UIView commitAnimations];
}

tableView.boundsではなくtableView.frameでも全く同じ状況でした。


さて、困った。

kouichikouichi2009/07/09 21:14同じことをアプリケーションで実装していますが、tableView.frame で期待通りの動作をします。
SDK のバージョンを変えて試してみて、すべて同じ状況ならプログラムのどこかがおかしい?
異なるバージョンで動作した場合は、SDK のバグと問題を切り分けることができないですかね。

paellapaella2009/07/09 21:29ありがとうございます!
SDKは2.2.1と3.0のデバイス/シミュレータ全ての組み合わせで試したのですが、まったく同じ症状でした。ということは私のビューの作り方か、もしくはその取り扱いのどこかに問題がある可能性が濃厚ですね。

方向性としては間違っていなかったということが、何よりの収穫です。
kouichiさん、ありがとうございます。がんばってみます。

kouichikouichi2009/07/09 21:47補足。私のコードでは、toolbar.hidden = YES として tableView の frame.size.height を toolbar の高さ分だけ増やしていました。toolbar.hidden = NO の場合は、逆の処理をして tableView の高さを減らしています。つまり、toolbar の frame は loadView で作成した後は、
変更していません。なお、IB は使わないで Programmatically にコードを書いています。

ohnoohno2009/07/10 00:34こんなのはどうでしょう?
的外れでしたらごめんなさい。

CGRect tableViewRect = CGRectMake(0,0,320,412);

UITableView *tv = [[UITableView alloc] initWithFrame:tableViewRect style:UITableViewStylePlain];
tv.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight);
tv.delegate = self;
tv.dataSource = self;

UIView *totalView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[totalView addSubview:tv];
self.view = totalView;
[tv release];
[totalView release];

paellapaella2009/07/10 08:12kouichiさん:
たびたびありがとうございます。
サンプルとを比較してみると、ナビゲーションコントローラー内のRootViewControllerに相当するところがUINavigationControllerを継承していたり、表示するビューのxibファイルでTableViewを再定義していたり(NavigationControllerでTableViewは自動的に作られるはず)と、幾つか問題があることが分かりました。

それを修正してもまだ直っていないので、kouichiの方法も含めて見直してみます。ありがとうございます。

paellapaella2009/07/10 08:25ohnoさん:
ありがとうございます。
autoresizingMaskプロパティは知りませんでした。なるほど、ビューの関係が適切であればきちんとリサイズしてくれそうですね。

こちらはまだ試していないのですが、試してみますね。
ありがとうございます。

※ちなみに今も同じ現象が出ています。しっかり調べます。

paellapaella2009/07/10 13:08わかりました!そして意図通りテーブルがリサイズ&再描画されるようになりました!

別記事でまとめます。皆さん、ありがとうございました。

2009-07-08

[Tips] 現在対象にしているビューのサイズを調べる方法 17:56  [Tips] 現在対象にしているビューのサイズを調べる方法 - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [Tips] 現在対象にしているビューのサイズを調べる方法 - Ni chicha, ni limona - 平均から抜けられない僕  [Tips] 現在対象にしているビューのサイズを調べる方法 - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

f:id:paella:20090708174938p:image:right

ちょっとしたことなんですがメモメモ。


タブやナビゲーションバーを表示していると、「表示可能な領域って今はいったいどれだけ?」と思うことがあります。とかく開発中のサイズ調整なんかではけっこう苦労するわけで。

それを調べる方法です。


	CGRect size = self.parentViewController.view.bounds;
	NSLog(@"Target view : %f, %f, %f, %f", size.origin.x, size.origin.y, size.size.width, size.size.height);

上のコードを適当なビューコントローラクラスに書いて実行すると、デバッガコンソールに


Target view : 0.000000, 0.000000, 320.000000, 431.000000


みたく表示されます。

※この値は右の画像でピンク色になっている部分の領域を調べています(ピンク色のビューコントローラ上に書いた、ということです)。


なお、self.view.boundsでも情報は取得出来たのですが、これだと320x480が返ってきてしまいました。注意です。

2009-07-06

[Cocoa] リファレンスカウンタ方式でのオブジェクトの代入について 19:09  [Cocoa] リファレンスカウンタ方式でのオブジェクトの代入について - Ni chicha, ni limona - 平均から抜けられない僕 を含むブックマーク はてなブックマーク -  [Cocoa] リファレンスカウンタ方式でのオブジェクトの代入について - Ni chicha, ni limona - 平均から抜けられない僕  [Cocoa] リファレンスカウンタ方式でのオブジェクトの代入について - Ni chicha, ni limona - 平均から抜けられない僕 のブックマークコメント

もう書くまでもないことですし、日本のiPhone開発本を開けば必ず載っていることなんですが、CocoaCocoa touchはメモリ管理形式にリファレンスカウンタ形式を用いています。


このリファレンスカウンタと、プロパティとの振る舞いでちょっと不安になったので、調べてみました。

試したのは以下のコードです。


@interface Hoge:NSObject {
	NSString *name;
}
@property (nonatmic, retain) NSString *name; // retain方式で宣言
@end

@implementation Hoge
@synthesize name;
	      :
	NSString *fuga = [[NSString alloc] initWithFormat:@"fuga%d", 1];
	NSLog(@"retainCount:%u", [fuga retainCount]);
	self.name = fuga;
	NSLog(@"retainCount:%u", [fuga retainCount]);
	self.name = @"Boke";  // ← 疑問:ここでちゃんとfugaをリリースしてくれるか
	NSLog(@"retainCount:%u", [fuga retainCount]);
	      :
@end

気になったのは、代入時にretainしてくれるのはともかくとして、別の値を代入した時(上記ソースのコメントがある箇所です)にきちんとreleaseしてくれるかどうか、という点です。


「ひょっとしてreleaseしてくれないのでは?」と思いましたが、なんのことはない、ビルド&Runしてみると、

XXXX[XXXX:XX] retainCount:1
XXXX[XXXX:XX] retainCount:2
XXXX[XXXX:XX] retainCount:1

上記の実行結果のとおり元々セットされていたオブジェクトもきちんとreleaseされていました。まったく問題なく、杞憂だったわけです。


よかったよかった*1


■assignの場合

・・・いやいや、上記だけだと誰にとっても限りなく意味のない情報になってしまいますので、プロパティを「assign」にしたときの結果も載せておきます。

XXXX[XXXX:XX] retainCount:1
XXXX[XXXX:XX] retainCount:1
XXXX[XXXX:XX] retainCount:1

このとおり、retainCountは変化しませんでした。最初にinitWith...で作ったときの値1のままで、変化していないことが分かります。

つまりオブジェクトへのassignプロパティは、「対象クラスにこのオブジェクトの所有権を持たせない」という意味にもとれますね。


■もう1つついでに

最後にもう1つ。


プロパティ宣言子は確かに便利ですが、古いバージョンのMac OS X(=Objective-C 2.0ではない)にも対応させたい場合には使用出来ません。

では、当時はどうやっていたかを参考として記述しておきます。これらはいずれもヒレガス本(Amazonインスタントストア)に書かれている方法です。

// 方法その1 : retainしてrelease
- (void)setFoo:(NSString *)x {
	[x retain];
	[foo release];
	foo = x;
}

------------------
// その2: 違うオブジェクトのときだけrelease&retain
- (void)setFoo:(NSString *)x {
	if (foo != x) {
		[foo release];
		foo = [x retain];
	}
}

------------------
// その3 : autoreleasePoolにつっこんでおく
- (void)setFoo:(NSString *)x {
	[foo autorelease];
	foo = [x retain];
}

それぞれのメリット・デメリットを以下に記しておきます。

方法メリットデメリット
その1ベーシックな方法。これでやっておけば取りあえず問題無し。毎回retain&release処理が入ってしまう。
その2同じ値のときはretainやreleaseのコストを避けられる毎回比較処理をおこなう必要有り。それに「同じ」とどう判断する?
その3あまり考えずに書ける。パフォーマンスの悪化。あと、取り扱いのミスが即クラッシュに繋がる。

こんなところです。

※最後にチラリと書きましたがautoreleaseのパフォーマンス悪化についてはiPhone開発では注意が必要です。そのうちちゃんと測って記事にしようと思っていますが、autoreleaseを使うよりもinit&releaseの方が処理が速いみたいですよ。


自分の場合、楽な構文やライブラリができると、その裏側がどうなっていたかをついつい忘れがちになります。今回のように、気になったときはきちんと確認しないといけないな、と自戒の念を新たにするのでした。


※hiroaki310さん、Twitterで的確なコメントをしていただきありがとうございました。

*1:最初はinitWithString:@"..."で作成したのですが、これだとretainカウントが-1、ではなくて2147483647(id:tokoromさん、ありがとうございました)になっていて計測できませんでした。これってクラスクラスタですよね?

tokoromtokorom2009/07/06 23:30retainCountの件、便乗して記事書かせていただきました。
http://iphone-dev.g.hatena.ne.jp/tokorom/20090706/1246890179

iPhoneの実行環境では、initWithString:@"..."のときのretainCountは-1ではなく2147483647になってます。
解放不要なオブジェクトはretainCountとしてNSUIntegerのMAX値(iPhoneではNSIntegerのMAX値)を返すようになってるみたいです。

horigoodhorigood2009/07/07 11:09>「同じ」とどう判断?の件
同一のオブジェクトかどうかは"=="で判定できます。内容の比較は、NSStringなら"isEqualToString:"、その他のクラスでは"isEqual:"で比較することになります。
ただし"isEqual:"の比較内容はクラスによって違うので注意が必要…と、たしか荻原本にありました。
けど、この比較の際にまたコストがかかるようだと、あまり意味ないですね。w

paellapaella2009/07/07 12:12tokoromさん、ありがとうございます。私も最初はinitWithString:@"..."を試したのですが、このときのretainCountは-1ではなく2147483647になってしまって、減っているかどうかが分からずに困ってしまいました。

NSStringの実装の裏側では、状況によって色々なクラスが暗躍しているのが垣間見えて、なかなか面白かったです。

あと、私よりも参考になる記事を書いていただいてありがとうございます。日本のiPhoneアプリ開発が活発化すると良いですね。

horigoodさん、仰るとおりです。
ちょっと私の説明が不足していたのですが、オブジェクトがNSString以外の、比較にコストのかかるオブジェクトだとすると、どれを選ぶかで検討が必要だと思います。

Appleのデベロッパーも「Macとは違うから。二度言うけれど違うから」と言っていますので、やっぱり意識しないといけないですね。

tokoromtokorom2009/07/08 16:33コメントで一部間違ったことを言ってました。
retainCountが「-1」になったり「2147483647」になったりするのはiPhoneどうこうって話じゃないですね。「2147483647」しか見たことがなかったのですみません・・・

●まとめ
オブジェクト定数: 2147483647 == INT_MAX == NSIntegerMax
解放できないオブジェクト: -1 == UINT_MAX == NSUIntegerMax

paellapaella2009/07/09 00:59ご指摘ありがとうございました。修正しておきました。

恐縮です。

tokoromtokorom2009/07/09 01:48私もきちんと整理できていなかったところなので勉強になりましたー^^
ありがとうございました。

ErikaErika2012/08/08 21:29This piece was a lifejacket that saved me from drwoinng.

itlfgwvcwiitlfgwvcwi2012/08/10 03:52Y7Tfuq <a href="http://yrviiqigchdp.com/">yrviiqigchdp</a>

cpiehilohcpiehiloh2012/08/12 10:03P110j0 , [url=http://astocxyplnjv.com/]astocxyplnjv[/url], [link=http://gdvgbpaaxrrn.com/]gdvgbpaaxrrn[/link], http://smmosyueefjc.com/