Hatena::Groupiphone-dev

inuchinがiPhoneとObjective-Cに翻弄される日記 このページをアンテナに追加 RSSフィード

2010-01-15

iPhoneとMacBookを手に入れて開発を始めました。

| 18:15 | はてなブックマーク - iPhoneとMacBookを手に入れて開発を始めました。 - inuchinがiPhoneとObjective-Cに翻弄される日記

昨年末(本当に末です。買ったのが12月28日だっけかな?)にMacBookを手に入れ、XCodeに触り始めました。

C/C++での開発経験は、そろそろ15年を超えます。Objective-Cを触るのは初めてです。

Macそのものは、System 6とか漢字Talk7.5.1(知っている人いるんでしょうか)を触っていました。

windowsunixでのwindowプログラミングの経験がありますので、cocoa touchを触るのには余り違和感を感じなかったのですが、Objective-Cには相当惑わされています。

特に、クラス内の関数を呼び出すのに、[self hogehoge]とやるのが大変ですね。

また、自分の勘違いが原因なのかもしれないですが、NSStringを使ったクラス変数の中身の変化にも悩まされました。

@interface myClass : UIView {
NSString *localStr;
}
@end

こんな宣言をしていて、NSTimerを使って呼び出してきた関数から、localStrにアクセスすると、中身が入ってない!(例外発生)みたいなことがあります。

NSTimerから呼び出されたクラス関数が、localStrに文字列を代入したクラスオブジェクトと、別々に参照扱いになってるのかな?

localStr = [[[NSString alloc] initWithString:@"文字列"] retain];

みたいに宣言してあげると、目的通りの動きをしてくれます。

STD::stringに慣れきってる自分としては、クラス変数に実体を置けないのはちょっと面倒くさいなーと思いつつも、どうせC++の頃からメモリ管理は自前でほとんど行っていたので、リークさえしなけりゃいいや、って感じです。

そんなこんなで、2週間ほど格闘しています。

BrianBrian2010/01/16 13:35Objective-Cにクラス変数はないと思います。たぶん。
localStr = [[[NSString alloc] initWithString:@"文字列"] retain];
インスタンス変数にallocしてretainしたらretainCount が2になってしまいます。
myClass がどこでalocc されて dealloc されるのかわかりませんが、myClass の dealloc 内で[localStr release] したとしてもretainCountが1なのでリークすると思います。
Instruments.app を使ってleakをチェックするかSnow Leopardだと思うのでXcode.app の メニューから「build and analyze」を実行するとかすればわかるかと思います。

inuchin104inuchin1042010/01/17 09:41コメント&情報ありがとうございます。

わー、クラス変数に相当するものだと思ってましたが、そうではないのですね。

retainが、autoreleaseされない=スコープから外れても参照カウンタを減らさない、だと思ってたのですが、しっかり内部で+1されているのですね。

Instruments.app では、メモリリークしている表示が、
build and analyze では、何も表示されていないです。

retainCountという単語を知りましたので、参照数を追っかけてみますね。

inuchin104inuchin1042010/01/17 10:55retainCountを追っかけてみた結果、
>|objc|
localStr = @"文字列";
[localStr retain];
||<
でRelease後にきっちり0になることを確認しました。initWith〜をしなくても、きっちりautoreleaseのオブジェクトを作るようで、retainすることでautoreleaseを解除できるようです。allocが必要だと思っていました。
参考サイト http://ameblo.jp/xcc/entry-10400027873.html

objective-cの理解が進んでいませんが、@propertyで、今回やったようなretain/deleteを自動化してくれるみたいなので、さらにテストしてみます。

BrianBrian2010/01/18 22:20なんらかのきっかけになったようで良かったです。

私が教わったのは「init」ないし「initほげほげ」したら自分でreleaseする責任がある。
それ以外で作ったオブジェクトはautoreleaseがかかっているのでrunloopが回ったら回収される。とかでしょうか。

厳密にはallocなんでしょうが、イディオム的に[[Hoge alloc] init] とセットで書くことので感覚的にはあっていると思っています。(たまに new を使っているのを見かけますが個人的には alloc] init] がおすすめです)
autorelease はメソッドを抜けたら解放される(つもりでいる)っという感じかと思います。
ですので、autorelease がかかっているオブジェクトをメソッドを抜けても保持し続けたいときには retain しておきます。

property には assign と retain がありますので間違わないように気をつけてください。
私がよくやらかしてしまうのは retain な property に alloc init したオブジェクトを代入してしまうことです。
retain な property に 代入するときには autorelease なオブジェクトで。

「詳解 Objective-C 2.0」に詳しく載ってますので一読をおすすめします。

#build and analyze はメソッド内のとかの狭いスコープでのチェック向きという感じでしたね。失礼しました。