以前、書いたけど、addSubview:で何枚もview を貼るとメモリリークが起こりやすいので、removeFromSuperview で貼ったのを引っ剥がしてから新たなviewを貼る。

これを学んでから、画像が自由自在に貼れるようになった。
途中で落ちることもなくなった。

参考になったのが

http://blog.fenrir-inc.com/jp/2011/08/addsubview_memory_leak.html

インスタンス変数にしたり、tagを使ったりすると、かなり便利に使える。

とてもとても助かった手法。

円の画像はダンナに作ってもらった。
Macが使い慣れなくて、自分で画像を作れない。。。

「何で作ったらいい?」と聞いてくるので
「jpgかpngかなぁ。。。」

で、出来た円は四角い白の上。
円の周りを透明で指定したけど、白になってしまうそうだ。

これじゃあ画像の上に乗せたらちよっと変。

これ、丸く切り取れないのか?
などと探してみたら、余白を透明にできる方法があった。

画像ファイルをgifで作れば可能。
そういえばアニメの画像なんかたいていgifで作ってあるなぁ。。。

で、無事に円だけ表示することが出来た。めでたしめでたし。

グラフィックで描いた円は画像の上には描けなかった。
円の上に画像がかぶってしまう。

そもそもUIImageView上に画像が表示できない。
(UIImageView*).imageを使おうとするとエラーになる。

それにグラフィック円は好きな段階で描くのが出来ない??

とにかく無理そうなので、円は画像で作って使うことにした。
addSubviewで表示すれば、UIImageViewで画像を表示しても見えたまま。
今回はそれが助かる。

使ったことあるから~とやってみたけど、左上に表示される。
真ん中に表示したいのだけど、位置指定はどうやるの?

検索したら、CGPointMakeで指定できる。
表示したい画像の真ん中位置を指定する。

例)iv.center = CGPointMake(200, 100); // ivを200,100の位置に配置する

これでようやく解決。

画面に円を描きたい。

検索すると UIView を使っての CGContext系 での描き方は出てくる。
けど、実際にどうやってファイルを作るのか、実行するのかが出てこない。

丸1日探して見つけたのが『初心者のためのiphone/ipadプログラミング入門』の「UIViewとグラフィックの描画 」
http://libro.tuyano.com/index3?id=599001&page=1

プロジェクトの作り方から丁寧に書いてある。

書いてある通りにやったら出来たけど、UIViewのサブクラスを作るとか、Viewにクラスを設定するとか、始めてやることばかり。
なんでそれが必要なのかがよくわからない。

最終的には表示した画像の一部に円を描きたいのだけど、つまりUIImageViewとUIViewを一緒の画面に表示したい。
その場合のUIImageViewとUIViewの関係ってどうなるのか?

ちょっとサンプルプログラムは見つけたので、それを参考にやってみる。
出来るのかなぁ~?



この3連休、行き詰まってた。

新たな画像表示のアプリ。
実行するとそのうちにメモリリークで落ちる。
なんでだろ?と検索したら、addSubview:で何枚もview を貼るとメモリリークが起こりやすいというのが出てきた。

私のアプリ、何百枚も貼ってる。。。。
で、その対策が removeFromSuperview で貼ったのを引っ剥がす。
引っ剥がすというのが出来るの??とびっくり。

簡単じゃん。とやってみたけど、やっぱりメモリリークが起きる。
使い方が間違っているのか?とそこで探しまわって深みにはまり、
やがて、ここじゃないところが原因ではないか?に行き当たり、
どうやらUIImage を UIImageViewに変換するところでなるみたい。と判明。
じゃあ、他の方法は?
と、さらに深みにはまり、だんだんと自分が何をやっているのかわからなくなってくる。

そんなときに、ビデオカメラ画像表示は (UIImageView*).image=(UIImage*) でやってて、
それだと落ちないことに気がついた。
けど、テストではタッチイベントで表示しているのだけど、
- (void)touchesBegan: 内では表示してくれない。
- (void)viewDidLoad では表示できるのに。。。

これはいまだに疑問。

でも私のは (UIImageView*).image=(UIImage*) で表示できるから、問題ではない。
画像表示はこれで解決。

画像の上に数個のラベルを addSubview:で表示している。
これはそのままにして、その都度、removeFromSuperview で剥がす。
気をつけないとならないのが、何枚か貼ってたら、上から順番に剥がさないと剥がれないこと。

ということでメモリリークは起きなくなった。
ついでに前のアプリの表示も同様に変えたら、問題として残っていた、だんだん遅くなる。
5~600枚で落ちる。 座標の軌跡が残る。
が、ぜ~んぶ解決した。

(UIImageView*).image=(UIImage*) で表示するやり方は、探してもあまり出てこなかった。
さらにaddSubview:での表示はたくさん出てくるけど、removeFromSuperview が必要なことが書いてあるのは少ない。

検索して出てくるのは、誰かが書いたこと。
それが正解のすべてかどうかは自分で考えなければならないってことだね。
まるまる写して終了~~というわけにはいかないもので。。。




画面が変わったり、入力されたら「ピッ」などの音が鳴った方がわかりやすい。
効果音を入れてみよう!ということになった。
音を扱うのは初めてだよ。

探したら、ここがとてもわかりやすかった。
http://ameblo.jp/micro-garden/entry-10376945194.html

最初の方に効果音を作るのは

「コードは短いけど難易度はスーパー」

と書いてあるからビビったけど、説明に従ったらそのまま出来ちゃいました。
とても丁寧な説明ですよ。

音を入れるとすごく見栄えがするねぇ~

サルできさん、あいがとうございました♪

実行しているとだんだん遅くなる。
どこかでメモリが溜まってる?
なるべくreleaseするようにしているんだけど。。。

メモリをチェックするには。。。
で見つけたのが 

retainCount:デバッグ目的のためにレシーバーの参照カウントを返します。

あちこちのカウントを出してみたら、カウントがどんどん増えているところを発見!
複数の画像から1枚を選んで表示しているところ。

UIImageView *imageView_ = [[UIImageView alloc] initWithImage:image[viewNo]];
[self.imageView addSubview:imageView_];
[imageView_ release];

この image[] ののメモリが増えてる!
init 系メソッドを呼ぶと参照カウントが1になるらしい。呼ばれるたびに増えている。
じゃあ、release しなくちゃ。
でも、image[] はずっと使うからrelease出来ないよね。。。
で、こうした。

  UIImage *ima=image[viewNo];
UIImageView *imageView_ = [[UIImageView alloc] initWithImage:ima];
[self.imageView addSubview:imageView_];
[imageView_ release];
[ima release];

これで image[] のカウントはずっと1。
とりあえずここはO.Kかな?

問題発生したら解決法を探してやってるけど、それが正解かどうかわからないのが困るなぁ。。。
判断してくれる人が欲しい。

何も操作しないと、画面は暗くなる。スリープ状態ね。

操作するアプリだとその心配は無いけど、眺めるだけのアプリはしばらくするとスリープになり、画面をタッチする必要がある。

暗くならないように出来ないか?

探しました。で、ありました。

[UIApplication sharedApplication].idleTimerDisabled

これを YES にすると画面は明るいまま。

どこで設定するの?
起動したときに設定したいから、- (void)viewDidLoad でかな?やってみる。
明るいままになった。

これをそのままにしておくと、アプリ終了後も明るいままになってしまう。
だから終了するときに

[UIApplication sharedApplication].idleTimerDisabled=NO;

にしないといけない。

終了するとき?どこで設定するの?

ViewControllew.m 内でやるなら、- (void)dealloc  かな?

やってみたらちゃんと元に戻った。
でもここだと、アプリが途中で落ちたときは通らないのでは?(不明)

ん~~。。。と悩んで、扱うものではないのだろうけど、
AppDelegate.m の - (void)applicationWillTerminate:(UIApplication *)application でやってみた。

正しく動く。
でもいいのかな?ここをいじって。。。






上下逆さまに表示してほしい。と言われた。
カメラ位置の関係で、逆さまにして操作したいと。。。

逆さまねぇ。。。
画像はそもそもを逆さまにすれば良いけど、文字列はどうなる?
文字をひっくり返して、しかも後ろから表示。
???どうやるの?

と、言ったら、
そもそもiPot touchを回すと、一緒に画像が回る機能があるのだから、逆さまにできるはず。と言われた。

そうだなぁ。。と検索したら、ある!
しかもその機能、View-basedアプリでプロジェクトを作成したときに付いてるじゃない。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

機能を調べないまま、そのままにしてた。。。

内容は
 *通常状態(ホームボタン下)
return (interfaceOrientation == UIInterfaceOrientationPortrait);

 *左に倒した状態で固定(ホームボタン右)
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);

 *右に倒した状態で固定(ホームボタン左)
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);

 *逆さま状態で固定(ホームボタン上)
return (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);

 *回転を感知して、常に上向きにViewを表示
return YES;

必要なものはちゃんと付いてるのねぇ。
不明なところはきちんと調べよう!

iPot touchで実行すると、値が飛ぶことがある。
iPad2では飛ぶことが無いから、変だなぁ。。。とは思っていた。

他のことでiPot touch上でいろいろデバッグしていたら、誤りを見つけた。
short intの範囲で収まらない場合がある変数をshort int型にしていた。

これは去年の秋に作ったヤツ。
けっこう重いアプリになったので、最後の方で軽くしようと、intをshort intに変える作業で発生したミス。
short intの範囲は知っていたから気をつけてたつもりなんだけど。。。

short int にすると、メモリーは本来の4バイトから2バイトへと変更され、表現できる数値の範囲も -32768~+32767。
最高値の32767に1を足すと、最低値の-32768に戻る。
だから値が飛んでたんだ。。。

iPad2で起きなかったのは、性能の違いでiPad2では範囲を超すような値にならなかったから。
ほとんどiPad2ばかり使ってたから気がつかなかった。

short intはあまり使うものじゃないね。
for文のカウントとか、すぐに使い終わる変数くらいにしといた方が良いみたい。

このミスが見つかって、ちょっと行き詰まって間に合わないかも。。。だったのが解決した。