2010年9月30日木曜日

クラス変数を扱う際にselfつけるか田舎、いや否か

はい、しょーもない出だしでした。

またクラスを定義して考えていくです(・ω・)ノ


<CVImageView.h>
 @interface CVImageView : UIView {
    UIView *menuView;
UILabel *label;
}

//ゲッター、セッター作るよー!という宣言
@property (nonatomic, retain)UIView *view;
@property (nonatomic, retain)UILable *label;
-(void)hoge;

@end

<CVImageView.m> 
@synthesize view;
@synthesize label;

-(void)viewDidLoad//ビルドして一番最初に呼ばれる関数
{
  //初期化
  self.label.text = @"hoge"; ー ①
  label.text = @"hoge"; ー②
}

-(void)hoge
{
/*viewDidLoadで説明しちゃうので略*/
}


さーて、①と②はどういう違いがあるのでしょうか。


(゚ε゚)えっと。。



正解は、
①はゲッター関数を経由して、クラス変数labelを初期化していて、②はゲッター関数を経由しないで初期化しています。

@property, @synthesizeを宣言するということはセッター関数とゲッター関数を自分で宣言せずにおまかせで作ってしまおうということでしたよね。

だから実は、この場合
-(UILabel *)label//getとは頭につけないのがobj-Cの習慣
{
     retrun label;
}
-(void)setlabel:(id)temp
{
   if(label != temp){
      [temp retain];
      [label release]
      label = temp;  
 }
}
が明示的には書かれないけど宣言されています。
だからself.labelとするとこの関数が呼ばれるんですねー。

これが気にいらない場合は@propertyはする一方で, @synthesizeを宣言をせずに、
自分でゲッター、セッター関数を定義するのも手ですね。

-(UILabel *)label
{
     retrun label;

}
実際これだとlabelのテキストが@"hoge"で初期化されてなくても(nilであっても)返ってきてしまうので、少し処理で困る事もあります。

というのは
[(中身がnilのインスタンス) 関数];とコードを書いても、ビルドは通るのですね。
しかし、中身がnilなので、関数は実行されずに無視されてしまうという罠。

だから、ビルドが通ってエラーが出なくても、そこの処理が行われないっていうことも起こりえます。

ここで、より確実に初期化でnilでは無いものを入れて、nilが返ってこないようにするには、 @synthesizeを宣言をせずに、自分で設定してしまいます。

ゲッター関数は以下のように定義します。

-(UILabel *)label
{
   if(!label.text) { //if(A) : if A is not nil labelがnilのとき
        UILabel *tempLabel.text = @"hoge";
        self.label = tempLabel;
   }
   return label; //label.textがnilではない時
}

ってやっちゃえば、確実にtextがnilじゃないものが返ってきますお!!

obj-Cのクラスメソッドとインスタンスメソッドの違い

以下のようなクラスを自分で定義したとする。

<CVImageProcessView.h>ーーーーーーーー
//どの画像処理をするのかを決定するようなUIなどの機能を持つクラス

@interface CVImageProcessView: UIView{
    UIImageView *imageView; //クラス変数
    UIButton *btn;
}

@property(nonatomic, retain)IBOutlet UIImageView *imageView;
@property(nonatomic, retain)IBOutlet UIButton *btn;

-(IBAction)pushBtn:(id)sender; //ボタンが押されたら(アクション実行)呼ばれる

@end

<CVImageProcessView.m>ーーーーーーーー
#import "CVImageProcessView.h"

@implementation CVImageProcessView
@synthesize imageView; //ゲッターとセッターを自動生成
@synthesize btn;

 -(IBAction)pushBtn:(id)sender
{
     //インスタンスを作らずにメソッドを呼び出す
     BOOL Call = [CVImageProcessor doSomeImageProcessClass:[imageView image]];
   
     //インスタンスを作ってからメソッドを呼び出す
     CVImageProcessor * imageProcessor = [[CVImageProcessor alloc]init];
     BOOL Call__ = [imageProcessor doSomeImageProcessInstance[imageView image]];
}
@end


<CVImageProcessor.h>ーーーーーーーー
//画像処理をするためのクラス

@interface CVImageProcessor : NSObject {

UILabel *label;
}

+(BOOL)doSomeImageProcessClass:(UIImage *)image; //クラスメソッド
- (BOOL)doSomeImageProcessInstance:(UIImage *)image; //インスタンスメソッド

@end


<CVImageProcessor.m>ーーーーーーーー

+(BOOL)doSomeImageProcessClass:(UIImage *)image//クラスメソッド
{
        lable.text = @"doSomeImageProcessClass is called";
/*Imageを使った画像処理*/
        return YES;
}

- (BOOL)doSomeImageProcessInstance:(UIImage *)image; //インスタンスメソッド
{
    lable.text = @"doSomeImageProcessInstance is called";
/*Imageを使った画像処理*/
        return YES;

}



って感じですかね。


さー、間違いはどこだ!!!www


って言うのは冗談で、関数の戻り値の頭に+がついている
+(BOOL)doSomeImageProcessClass:(UIImage *)image//クラスメソッド
がありますよね。

これの中で、 
lable.text = @"doSomeImageProcessClass is called";
という処理をしていますが、これが出来ません!

普段C++を使っているのもあるのか無いのか、これが意味不明でした。。
(C++だとクラスメソッド使えば、アクセスできるやん!ってことで。)

でも、簡単にいうと
+がついてる関数→クラス変数にアクセス出来ません。
ーがついてる関数→クラス変数にアクセス出来ます。

(もちろんどっちの関数にしろ、スコープ内で変数は宣言、使用できます。)

て感じらしいです。

本には、ちゃんとインスタンスがどうのこうの書いてありますが、
知識でしかなくて実際これで困らないと理解できませんでした(´ー`)

lib**.aファイルの参照

相変わらずsimulatorでテストしようとしても、以下のようなエラーが出るのでそれは放置。





これもいつかは直さないとな。。

ってことで、今回はあくまで実機向けのライブラリファイルへのリンク。

このdevice_libはどこから読みこんでいるんだ!っていうと、ここからです。



自分のいま作業を行っているプロジェクト内にあるopencv_deviceディレクトリ内にある、lib**.aを参照しています。これを参照すると実機で動くようになりました。

 (追記メモ)
ちなみに、ここでOpenCV2.1のライブラリファイルを参照すると、
ld: library not found for - lcv 2.1.0
とエラーが出てしまい、実機でもシミュレータでもビルドできなくなる。

iOS4.1+XCode(ver.3.2.4)でOpenCV2.1を使用する

 基本的には以前の日記にも書いたniwa氏のサイトを参考にした。
http://niw.at/articles/2009/03/14/using-opencv-on-iphone/ja


しかし、ここだけでは自分の設定が悪いのか、環境が悪いのかどうにもこうにも
動かないことがあったので、メモ代わりにいくつか書いておく。
(間違いがれば、随時訂正します。)

4.OpenCVにiOS SDK 4.xでビルドできるようにパッチを当ててください
% cd OpenCV-2.1.0
% patch -p1 < ../OpenCV-2.1.0.patch
 
とありますが、OpenCV-2.1.0.patchはniwa氏のサンプルをgitからダウンロードすると
そのディレクトリ内にあるので、それを自分の作業ディレクトリ内にコピー。
 
 
5.6. 実機向け、シミュレータむけのビルド〜
% ../opencv_cmake.sh Simulator ../OpenCV-2.1.0 とありますが、ここでも 
opencv_cmake.shを同様にコピーして使用する。
 
ここで、niwa氏のblogのコメント欄にも書いてあるが(残念ながら英語)、
 
AMさんのコメント 09/15, 2010

Thanks so much for your work and support on this project.

I'm
 running into a build issue and I wonder if you can help. Everything is 
fine until I'm at the building static Device library phase 
(../opencv_cmake.sh Device ../OpenCV-2.1.0
) and I get the error

'iOS SDK Version 4.0 is not found, please select iOS version you have'

-- I'm running XCode 3.2.4 with iOS 4.1 on Mac 10.6.4 -- (OpenCV 2.1.0 obviously).

Am I doing something wrong? 
Thanks again for your help. 
 
iOS4.1ではエラーが出てしまうのだ。実際自分も同じエラーが出て困った。
 
そこで、opencv_cmake.shをテキストエディタで開き、
 
4行目、24行目SDK VERSIONが4.0で指定されているところを手動で4.1に変えてしまう。
(念のため元ファイルはコピーしてバックアップしておきましょう。) 
 
 
 
こうすると上記のエラーが無くなり、ビルドは問題なく実行される。
さて、次に行きますか。
 
(しかし、書いてはいるものの、正解かどうかは自信が無いのであしからず。。。
やる時は自己責任でお願いします(>_<) )
 
プロジェクト”your_project”の情報→ビルドタブを見ます。
 
ここのヘッダ検索パスにもし、/usr/loacl/includeが含まれていればそれを削除。
 
次にターゲット ”your_project”の情報→ビルドを見ます。
 
 
ここで、 アクティブアーキテクチャのみをビルドにチェックを入れる。
さらに、他のリンカフラグに -lstdc++, -lz を追加する。
 
 
さー、あともうちょい頑張って書くぞっと( ゚Д゚)
 
このターゲットの情報、ビルドのタブの中から次に、検索パスを探す。


 ここで、以下のように設定する。


左下にあるこの設定プルからビルド設定条件を追加を選択して以下を足す。
 ※niwaさんのプロジェクト参照

ヘッダ検索パス
Any iOS Device Any Architecture $(SRCROOT)/opencv_device/include
Any iOS Simulator Any Architecture$(SRCROOT)/opencv_simulator/include

ライブラリ検索パス
$(inherited)
$(SRCROOT)/opencv_device/lib
Any iOS Device Any Architecture$(SRCROOT)/opencv_device/lib
Any iOS Simulator Any Architecture$(SRCROOT)/opencv_simulator/lib

そして、最後に、左上の構成プルダウンから、アクティブ(Debug)を選択してひとまず終了。


これでこの回はとりあえず終了して、次回に期待。

( ゚Д゚)<おい待て

MacでOpenCVを使用する際に出るエラー





simulatorでビルドした時に出るエラー。ライブラリファイルへの関連づけがおかしいらしいけど。。

googleで同じエラーを探しても解決策は見つからなかったので、今(10/09/30)はsimulatorでテストするのを断念。

<参考:同じエラーで困ってる人>

http://opencv-users.1802565.n2.nabble.com/problems-linking-with-OpenCV-2-1-td5266354.html

2010年9月15日水曜日

Xcodeの便利な機能

よく使用方法が分からないクラス、サブクラスのことを知りたいときはそのクラスまたはサブクラスをダブルクリックして選択する。

そして、右クリックでこのようなウインドウがでる。



ここで、定義へジャンプすると。


必要な関数や、その中に使われている変数などの説明や一覧を見る事ができる。
@optionalとなっているものは書いてもよいし、書かなくてもよい。必要に応じて利用する。

また、__OSX_AVAILABLE_BUT_DEPRECATEDと書かれているものはサポートが終わるものを示しているのでなるべく使わない。

以下の例で見てみる。



ここでは、一番上の選択されているものがサポートが終わるものである。
これをダブルクリックして、”テキストをドキュメント内から検索”を選択すると、このような画面がでて、選択した関数に変わってこれがいいよ。という情報ももらえる。


従って、訳が分からんようになってしまったら見てみる癖をつけたい。

便利なサイトまとめ<随時追加>

<OpenCVをmac, iPhoneで使いたいとき> 

・yoshimiura niwa氏のサイトおよびソースコード
http://niw.at/articles/2009/03/14/using-opencv-on-iphone/ja
http://github.com/niw/iphone_opencv_test


Nacho4d氏のサイト
http://nacho4d-nacho4d.blogspot.com/


<サンプルアプリをiPhone/iPod touchの実機でテストしたいとき>
キーチェーンだの証明書だの登録だのと色々めんどくさいんですね。。

kentaro shimizu氏のサイト
http://kentaro-shimizu.com/lecture/iphone/step3.html

タナカイチロウ氏のサイト
http://d.hatena.ne.jp/ichiro_tanaka/20090717/1247798246

Jewel-mmo開発日記
http://dgames.jp/dan/permalink/20100312

Sun Limited Mt.
http://www.syuhari.jp/blog/archives/973

<iPhoneアプリ作成での禁則事項>
意外と多くない?

http://fladdict.net/blog/2010/09/reject-list.html

macの便利なショートカット:スクショライクな機能

command + shift + 3 で全体のスクリーンショットをpng形式で保存

command + shift + 4 で任意の選択領域のスクリーンショットをpng形式で保存

iPhoneでOpenCV2.1

今回は、下に紹介するyosimasa niwa氏のblogを参考にしながら書く。

http://niw.at/articles/2009/03/14/using-opencv-on-iphone/ja

githubのdownloadリンクからzipをダウンロードして解凍してみる。
>>OpenCVTest.xcodeprojをXcodeで開いてビルドします。 デモアプリケーションがシミュレータと実機両方で動くことが確認できると思います。

でけた!(・∀・)

ということで、同氏のblog内で紹介されている4. 5. 6. の過程ではなく、違った方法でopencv2.1を使ったプロジェクトを実機でも、シミュレータでもビルドできるようにする方法を教わったので書いていきます。

niwa氏のこのプロジェクトからopencv_device、opencv_simulatorという2つのフォルダをコピーします。



そしてこのふたつのフォルダを自分の作ったプロジェクトの階層にペーストします。



次に、niwa氏のサンプル OpenCVTest.xcodeproj を実際に開く。
そして開いたプロジェクトの左窓のターゲット内のOpenCVtestをダブルクリックすると、以下のようなウインドウが開くので、ビルドを選択する。



そして、ヘッダ検索パスとライブラリ検索パスが上の選択領域のようになっていることを確認する。

次に自分が作成したプロジェクトを開く。
上と同様に、ターゲット内のオブジェクトをダブルクリックして、情報ウインドウを開き、ビルドを選択し、ヘッダ検索パスとライブラリ検索パスを見つける。
そして、niwa氏の設定をそのまま真似する!

具体的には、デフォルトのままではヘッダ検索パス、ライブラリ検索パスともに、数が足らないのでまずは以下のように


左下のアイコンをクリックして、ビルド設定条件を追加していく。

次にAny iPhone OS Deviceなのかsimulator なのかに気をつけながら設定を真似していく。



次に値を真似る。



$(SRCROOT)/opencv_device/include

などと書いてあるので、適宜コピペしていく。そうすると、以下のような見た目になるはず。


これでおk。

Mac Snow LeopardでOpenCV2.1を動かす


Nacho4dさんのページを参照して、フォローする形式で書いていく。
Special Thx Nacho4d !!

http://nacho4d-nacho4d.blogspot.com/2010/07/blog-post.html

では、順に追っていく。

まず自分が行ったのは、書いてある通りにsvnでopencvをダウンロードしてcmakeを実行

$ svn co https://code.ros.org/svn/opencv/trunk/opencv
$ cd opencv
$ mkdir build
$ cd build
$ cmake ..

次に、buildのステップ
Nacho4dさんのブログでは以下のようになっているが、
$ make -j8
$ sudo make install

自分の場合
$ sudo (あとで追記)make install
とした。これは権限の問題をパスする方法らしい。

次にXcodeで実際にプロジェクトを作る。(2010/09/14の時点ではver3.2.3を使用。)



左窓のMac OSXのApplicationを選択。
さらにcommand lineを選択して、TypeはC++ stdc++を選択する。
※OpenCVはC++で書くことが多いため。

次にOpenCVのヘッダパスを追加する。
プロジェクト名が書いてある左の窓の青いアイコンを選択しつつ、プロジェクトの新規グループを選択して、名前をOpenCV Frameworks などと設定する。(これは任意でおk)



そしてこのフォルダを選択したまま、メニューのプロジェクトから”プロジェクトに追加”を選ぶ。そして以下のような画面になるので、おもむろに /usr/local/lib と打ち込む。


こうするとOpenCV2.1を動かすために必要な動的ライブラリファイルが一括してプロジェクトに取り込める。


そうするとヘッダファイルも読み込みたくなるので、左窓からプロジェクト名が
書かれた青いアイコンを選択して、command + i (青い i の情報ボタンでも可)

一般、ビルド〜と並んでいる小窓から、ビルドを選択。
そして有効なアーキテクチャを選択する。


ここでppc系はいらないので消去してしまう。

次に、ユーザヘッダ検索パスという設定を見つけて、右側の窓に/usr/local/include/と打ち込む。


これでOpenCVを使うときに必要な設定はおしまい。

実際に使うファイルの**.hの冒頭で
#include "opencv/cv.h" 
または
#include <opencv/cv.h>

と書けば、使える!!(はず。)

もし、ワーニングが気になるなら

#include "opencv2/imgproc/imgproc.hpp" //for image processing
#include "opencv2/highgui/highgui.hpp" //for GUI

と書けばよいらしい。本当にNacho4dさんに多謝多謝。