2011年12月18日日曜日

test

選択して下さい
購入してください

NSOperationについて

NSOperationのサブクラスhogeを定義し,それに- (void) mainを、mainにマルチスレッドで実行したい処理を書き、hogeのインスタンスをインスタンスメソッドaddOperation:でNSOperationQueueのインスタンスに追加し実行する


という流れのようです。


いま読み中のNSOperation関連のブログ


NSOperationによるバックグラウンド処理
http://objective-audio.jp/2008/04/nsoperation.html


NSOperation 非並列実行モードと並列実行モードの使い分け
http://d.hatena.ne.jp/glass-_-onion/20110706/1309909082

XCode代替のIDE


ObjectiveCを書くためのIDEはXCode4が独占状態でしたが、AppCodeというObjectiveC用IDEがあるようです。

コード補完機能やリファクタリング機能ががXCodeよりかなり強力になっているようです。
使い方さえなれれば効率がよいエディタのほうがコーディング速度は早くなりそうです。

Appcode
http://www.jetbrains.com/objc/


Key Features
Smart editor with code completion
•Opening and creating Xcode projects (including Xcode 4)
•Integration with the standard Interface Builder
•Running applications in iOS Simulator
•Debugger with breakpoints, variables, watches and evaluate expression
•Refactorings, e.g. 'Change Signature' and 'Extract Method'
•On the fly code analysis and quick-fix suggestions
•Hi-class version control systems integration (SubversionGit, Perforce andCVS)

imp型とはなんぞや

解説書にimp型というものが書いてあったが、よくわからなかったので色々調べると、Cの関数で下記のように定義されているらしい。
typedef id (*IMP)(id, SEL, ...);

定義から見るに、Objective-C のすべてのメソッドは、id 型と SEL 型の引数をもっているので、結局のところC言語の関数みたいなものにいきつくとかなと思いました。

追記:この記事を見ると、IMP型を使ってCっぽいコードを書くとえらく早くなるようですね
ダイナミックObjective-C
22 メソッドとは何か(5) - メソッドの実装
http://news.mynavi.jp/column/objc/022/index.html

メソッドの遅延実行

とあるメソッドを1秒とか0.1秒とか遅れて実行させたいときってありますよね。
NSTimerなどで遅延させて実行させる方法もあるようですが、performSelectorメソッドを使うと簡単にメソッド実行のタイミングを設定することができます。
[self performSelector:@selector(メソッド名:) withObject:nil afterDelay:遅延時間0.1];

このメソッドの活用法としては、エフェクトの実行タイミングや、起動時の要素の読み込みで、重い要素の読み込みを遅延させることで見かけ上の起動時間を短縮させることができるなどいろいろつかえそうです。

2011年12月16日金曜日

initについて

よくある初期化パターン
- (id)init
     {
         [super init];
       初期化コードを書く
         return self;
     }
エラー処理を追加したコンストラクタ
- (id)init
{
    if(self = [super init]){
       初期化コードを書く
    }
    return self;
}
エラーが起きたら中途半端にとったメモリ領域を解放させたほうがトラブルが少ない
- (id)init
{
    if(self = [super init]){
       初期化コードを書く
}else{
            [super dealloc];
            return nil;
}
        
    }
    return self;
}

2011年12月8日木曜日

Grand Central Dispatchについてかじり中

CoreMotion関係でGCDを使う部分があったのでついでにかじり中

http://www.gamvaro.com/kswiki/index.php?%EF%BC%AF%EF%BC%B3%E9%96%A2%E4%BF%82%2FiPhone%E7%94%A8OS(IOS)%2FGrand%20Central%20Dispatch

CMMotionのエラーについて

CMMotion関係のコーディングをして実行したところ

Apple Mach-O Linker Error

Undefined symbols for architecture armv7:
  "_OBJC_CLASS_$_CMMotionManager", referenced from:
      objc-class-ref in MainViewController.o
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

というエラーが出て、ビルドができないことにずいぶんとはまりました。

文法的にも問題ないのに。。とおもっていたら
CoreMotion.frameworkを追加するのを忘れていました(@@)
CoreMotion.frameworkを追加してビルドすると、ちゃんとビルドできるようになります

CoreMotionについて


CoreMortionフレームワークは、デバイスの方向や動きを取得するインターフェースです


UIAccerometerクラスは次のiOSではサポートしなくなるとAppleが宣言していますので、CoreMotionを使うことにします。


加速度センサーとジャイロスコープ(ひねり)センサーからデータを取得します。


高度なフィルタリング機能もあります。





















☆位置情報の取得タイミングについて

iOSイベント処理ガイドより
http://developer.apple.com/jp/devcenter/ios/library/documentation/EventHandlingiPhoneOS.pdf

プッシュ型:アプリケーションは、更新間隔を指定し、モーションデータを処理する、(あるタイプの)ブロックを実装します。次いで、Core Motionにオペレーションキューとブロックを渡して、該当するタイプのモーションデータの更新を始めるよう指示します。CoreMotionは(指定された更新間隔で)更新データをブロックに渡してオペレーションキューに入れます。ブロックはオペレーションキューから順次取り出され、タスクとして実行されることになります。

プル型:アプリケーションは、あるタイプのモーションデータの更新を始めるよう指示し、定期的に、直近の測定値をサンプリングします。


☆取得できない情報
GPSデータ
-CoreLocationフレームワークを使いましょう
コンパス情報
-CoreLocationフレームワークを使いましょう

iPhone4以降ではジャイロスコープが搭載されていますのでx軸、y軸、z軸のひねりの速度も取得できます

●クラスについて
CMMotionManager 情報の取得タイミングなどの設定を行う
CMAccelerometerData デバイスのX,Y,Z軸情報を取得
重力情報
CMAttitude roll,pitch,yawなどの姿勢角や行列などの加工されたデーターを取得できます
CMDeviceMotion 加速度センサーおよびジャイロスコープから得られた、処理済みのデバイスモーションデータをカプセル化します
CMGyroData  rotationRateというプロパティ持ち、x,y,z軸における回転の早さ(ラジアン/秒)を持ちます
CMLogItem  それぞれの位置情報にタイムスタンプを付与する、計測系クラスの親クラス


2011年12月5日月曜日

加速度について

iPhoneの特徴の1つとして、加速度センサーが内蔵しており、iPhoneの動きを取得してゲームのエッセンスに使ったり、アプリにジェスチャー操作をつけるなど創意工夫で特徴あるアプリケーションを作ることができます。

●ヘッダファイルの書き方
加速度を取得するUIAccerometerクラス取得するは、UIAccerometerDelegateというプロトコルを使ってオブジェクトに傾きを通知するので、

@interface MainViewController : UIViewController {
IBOutlet UILabel *x; IBOutlet UILabel *y; IBOutlet UILabel *z; }

と指定します。

次にUIAccerometerインスタンス化と初期設定をコーディングしていきます(この場合は最初に読み込まれるviewDidLoadメソッドに書きこんでいます。

- (void)viewDidLoad {
[super viewDidLoad];
// UIAccerometerに対してsharedAccelerometerクラスメソッドを送り、インスタンスを作成
//setUpdateIntervalで取得間隔を設定します。この場合は0.1秒間隔で取得する設定
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:0.1];
// デリゲート通知を自身に指定します
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
}


//デリゲートメソッド - (void) accelerometer:didAccelerate:を実装
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration{
x.text  = [NSString stringWithFormat:@"%10.2f",acceleration.x];
y.text  = [NSString stringWithFormat:@"%10.2f",acceleration.y];
z.text  = [NSString stringWithFormat:@"%10.2f",acceleration.z];
}


2011年12月2日金曜日

iPhoneアプリ申請時に起きたエラーなどについて

とあるiPhoneアプリをiTunesConnectに提出することがありまして、前と仕様が変わっていたりエラーではまったのでメモ。

良くありがちな設定ミスの確認

●証明書の再発行
-再発行の時にメールアドレスや名前をAppleに登録したものと同じものにする

●プロビジョニングファイルの再発行

●Identifierの設定を確認する
XCodeの左ペインのあおいプロジェクトファイルのアイコンを選択して
TARGETS→アプリ名→Summary→Identifierの欄がcom.yourcompany.アプリ名ではなく
設定したAppIDを選択しているか確認

●Schemeの設定
Stopボタンの横のSchemeをクリックし、Edit Schemeを選択。左のArchiveを選択し、BuildConfigulrationをDistributionに設定しているか確認
もしDistributionがなかったら、XCodeの左ペインの青いプロジェクトファイルのアイコンを選択して、
Project→Info→Configurationsの左下の+マークを選択し、"Duplicate Release Configuration"を選ぶとrelease copyができるので、"Distributionに変更して、Schemeの設定をする。

●CodeSigningの確認
XCodeの左ペインのあおいプロジェクトファイルのアイコンを選択して
TARGETS→Build Settings→Code Signing Identityをチェックして、Distributionの項目がiPhone Distributionの適切なアプリ名を選択しているか確認。

どうしてもダメな場合、OSの再起動やXCode再起動や再インストールで治ることもあったりします笑

参考にしたブログ
登録の方法のおさらい
Xcode4でiPhoneアプリをiTunes Connectに登録する方法
http://blog.livedoor.jp/tattyamm/archives/2957285.html

App StoreへのiPhoneアプリの登録手順のまとめ(Xcode4環境)
http://www.facebook.com/note.php?note_id=153450554720309


エラー対処について

■[iPhoneプログラミング]新しい開発環境を構築したときにprofile関連でエラーとなるときの対処法
http://d.hatena.ne.jp/nakamura001/20100214/1266172164

XcodeでArchiveエラーのときの対処 その1
http://iphone-app-developer.seesaa.net/article/230412566.html

ハマッた。Application failed codesign verification. The signature was invalid, or it was not signed with an iPhone Distribution Certificate. (-19011)
http://www.hirano-dept.com/blog/2011/11/application-failed-codesign-verification-the-signature-was-invalid-or-it-was-not-signed-with-an-ipho.html


2011年11月17日木曜日

【メモ】iPhoneアプリケーションの読み込み順序


●最初にmain.mのUIApplicationクラスをインスタンス化
●info.plistを読み込み、main xib file base nameからxibファイルを探す
●xibファイルを読み込み、記述に従いインスタンス化(今まではMainWindow.xibを読み込み、そこからViewControllerのxibファイルをロードしていたが、XCode4.2からAppDelegate.mに該当のソースが追加され、MainWindow.xibがなくなってしまったようです。これに2-3日はまりました)

2011年11月10日木曜日

XCodeでビルド後、iPhoneで実行する前にDon't know how to run. Try "help target" というエラーが出る件

Don't know how to run. Try "help target" というエラーが出てはまったので直った方法をシェア。
●試したこと
クリーニング
XCodeの再起動
プロパティの見直し
コンパイラの変更
→どれもうまくいかず。。
●直った方法
実機のポータルへの登録しなおし


アクセサ

インスタンスの値や属性を見たり変更したりするためのメソッドを作って使うのが流儀。
該当インスタンスの値を直接みたり変更するのではなくメソッドを作って変更する。

値や属性などを確認するのがゲッタ(getter)
値や属性を変更するのがセッタ(setter)
という名前としてつけられてる。
例)
num1 num2 num3というインスタンス変数があった場合の
num1だけ見たり変更したりするゲッタセッタ
-(int)num1{return num1;) //ゲッタ(ただnum1の値を返す)
-(void)setNum1 : (int)newvalue{
num1 = newvalue; //セッタ(num1の値をnewvalueに変更)
}

アクセサは@property @symthesizeを書くことで同様のことができる。
@propertyの書き方
例)
@property (retain,nonatomic) (id) *count;
のように属性などをつけて定義する。
アクセサを作る対象がオブジェクトの場合、retain nonatomicはつけるのが慣例
nonatomic とretainについて後で確認。
この例のretainは使用中はメモリから消されないようにする

あるインスタンスから他のインスタンス変数にアクセスする方法

例)obj1のval1に他のインスタンスからアクセスするには
obj1->val1
という書き方をする。
同じクラス内のインスタンスのみ利用可能。
使う場合にもクラス名でキャストしておく必要がある。

-(id)makerandnum:(mknum *)num
{
num1 = num->num2;
//mknumクラスの型にキャストされたインスタンス変数numにアクセス
}
☆インスタンス変数の使える範囲の指定
num->num1のように他のインスタンス変数を利用できるが、インスタンス変数へのアクセスできる
範囲を制限することができる。どこからでも変更、読み込みができたり、クラス内でしか読めないようにできたり。

@private
宣言したクラス内だけ利用可能
サブクラスからも使えない。
@protected
宣言したクラスとサブクラスから利用可能
何も指定しないと@protectedが適用される
@public
どこからでも利用可能
書き方
@interface num1 : num
{
id inclementvall;
@public
int decval;
@private
double outval;
int testval1;
@protected
int testval;
}
@end
というように種類ごとに定義する。

インターフェースに他のクラスを使うとき

インターフェースを定義するときに、他のクラスを型としてインスタンス変数に定義することができる。
その方法として、インターフェースを定義するヘッダファイルの最初に@class つかうクラス名
を宣言し、実処理を行うときに該当クラスのヘッダファイルをインポートする。
例)
@class class1
@interface newclass :NSObject
class1 *theclass1;
@end

//ヘッダファイル部
import "class1.h"
→使う暮らすヘッダファイルをインポートする。

型とクラス

インスタンス化するとき、id型を利用するが、特定のクラスのインスタンスということを明記することができる
クラス"class"専用のインスタンスを言うことを書きたい場合
class *x
というように*をつける。
このように生成されたオブジェクトはポインタとして生成され
class *x,*y
x = [[class alloc] val : 0];
x = y;
とした場合。xで実行した結果がそのままyに引き継がれる。

継承して新しく作ったクラスは、スーパークラス用に定義されたクラス名に入れることができる
例) class1 *a
@interface class : NSObject
- (void)hello
@end
@implemantation
なんちゃら
@end
@interface class2 : class
-(void) hello
@end

int main(void){
class *a,*b;
a = [[class alloc] init];
b = [[class2 alloc] init];
}
というようにclass1用に作ったものでも継承して作られたclass2に入れることができる。
ただし、スーパークラスで定義されたメソッドのみしか使えない。
使いたい場合は、class2の型にキャストして利用する。

class1 *a,*b;
a = [[class1 alloc] init];
b = [[class2 alloc] init];
[a class1onlymethod];
[b class1onlymethod];//class2でclass1から継承したclass1にあるメソッドを利用してもエラーでない

[b class2onlymethod];//オーバーライドしたものはエラーが出る
[(class2 *)b class2onlymethod];//class2用の型にキャスト

テクニック
if文の条件の評価順序をうまく使い、インクリメントや文字列の評価をする
例)if (p && *p)
pが空の場合はそれ以降の評価は行われない。
ポインタのpかどうか調べる際、pが空だとコンパイラが落ちるので落とさずに値の評価ができる

継承とクラス

[self]でクラス自身のメソッドを呼び出したとき、上書きされていない継承したメソッドを呼んだとき
スーパークラスのメソッドが呼ばれる。
スーパークラスのメソッド内で[self]でメソッドが呼ばれたとき、スーパークラス内のメソッドが参照されるのではなく、自分のクラスのメソッドが呼ばれる(オーバーライドされたものが呼ばれる)


実装手順
ヘッダーファイルにインターフェースを書く
mファイルに実処理を@implementation以下にインターフェースに対応した処理を書いていく

実行プログラム上で書いた処理の呼び出しを行う
@interface
-変数やクラス名定義
@implementation
-色々処理
int main(void)
{
id x = [[newinstance alloc] init];//インスタンス生成
[x method1];//インスタンスのメソッド呼び出し
}
外部からのメッセージで動くメソッドの場合はinterface部分にメソッド名を定義する必要があるが
そのクラス内部でしか使わない内部用のメソッドの場合はインターフェースは書かなくてもよい。
[self]で呼び出してつかったりする。
例)カウンターアプリでダウンアップそれぞれメソッドを作るが、アップダウンと同時に音を鳴らせる場合、内部で音を鳴らせるメソッドを作成し、[self]で呼び出すなど
この場合、最初の部分に定義する必要がある([self]で呼び出される前に定義)

継承について

クラスの機能を受け継いで新しい機能をつけたしたクラスを簡単につくることができます。
クラスの機能を受け継ぐことを継承といいます。

クラスA→クラスB(Aの機能にメソッドを一個追加)→クラスD(A+Bの機能)
→クラスC(Aの機能に変数とメソッドを追加)

クラスAのインスタンス変数名やメソッド名はBでもCでもそのままつかえます。
さらにクラスBからクラスDのように機能をどんどん継承して自由に機能を利用することができます。

継承する元のクラスをスーパークラスと言い、継承して新しく作ったクラスはサブクラスといいます。

iPhone開発の場合、全ての大本のクラスはNSObjectsというクラスなので
特段継承するクラスを作っていない場合などはNSObjectsを継承させる。

クラスを継承する場合のクラスの書き方
@interface newclass : NSObjects または継承するクラス名(スーパークラス)
{
インスタンス変数;
}
-メソッド
@end;

継承とメソッドのオーバーライドについて
クラスA
クラスB
クラスC
の3つのクラスがあったとして、A→B→Cという感じで継承していた時
クラスAにはa b cの3つのメソッドが定義されているとする。
クラスBでbメソッドの定義を書き換えたら、クラスCで継承されたとき書き換えられたbメソッドをつかう。
他に書き換えられてない場合、大本のAのメソッドが継承され、使われる。
☆クラスBで書き換えたbメソッドではなく、スーパークラス(クラスA)の書き換え前のbメソッドを使いたい場合、superというものに対してメソッドを引数にして呼び出すとスーパークラスのメソッドが呼ばれる。
例)
[b]→自分で書き換えたメソッドが呼ばれる
[super b]→スーパークラスのbが呼ばれる

☆イニシャライザについて
インスタンス変数の初期化、サブクラスで初期化を行う場合
-(id)init
{
self = [super init];
if(self =! nil){
year = @"";
//初期化するコードが入る
}
return self;
}

Objective-cの書き方基本

オブジェクトはid型という型で定義される
例 id temp;
あるオブジェクト(obj)にメッセージを送るとき
[obj messege];
とかく。messageを処理した値が帰ってくる。
返り値がオブジェクトの場合、さらに[[obj message] messsage2]のように
さらにメッセージを送って処理させることもできる

クラス→インスタンス生成方法
クラスにメッセージを送る
とりあえずインスタンス作る場合
[classname alloc];
というようにallocというメッセージを送って空のインスタンスを作る
この後、初期化処理を行う。初期化処理するためのメソッドはイニシャライザといいinitもしくはinitなんちゃらという名前になるルール
☆インスタンスを作って初期化する例
[[class alloc] init];

2011年11月2日水曜日

テスト

#import "sm2ViewController.h"

@implementation sm2ViewController

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle
//数値を表示
-(void)updatedisplay
{
    display.text=[NSString stringWithFormat:@"%d",count];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    srand(time(NULL));
    [NSTimer scheduledTimerWithTimeInterval:1.5 
                                     target:self 
                                   selector:@selector(move:) 
                                   userInfo:nil 
                                    repeats:YES];
    //解像度取得
    CGRect r = [[UIScreen mainScreen] bounds];
    CGFloat w = r.size.width;
    CGFloat h = r.size.height;
    NSLog(@"%f",h);
    
    //音の指定
    NSString *path= [[NSBundle mainBundle]
                     pathForResource:@"Alarm" ofType:@"caf"];
    NSURL *url=[NSURL fileURLWithPath:path];
    //NSLog(@"%s",path);
    //
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)url,&SoundID);

}
-(void)move:(NSTimer *)timer
{
    //アニメーションの動きの定義
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.5];
    
    //iPhoneの解像度を取得する(これをすることで未来の解像度にも対応できるかも)
    CGRect r = [[UIScreen mainScreen] bounds];
    CGFloat w = r.size.width;
    CGFloat h = r.size.height;
    
    //CGFloatはfloat型なのでintにキャスト
    int wid=(int)w;
    int hei=(int)h;
    
    //x,y座標rand()%hogeで0〜(hoge-1)までの数値をランダムで出力
    int x = rand()%wid;
    int y = rand()%hei;
    
    //targetアウトレットのcenterプロパティ
    target.center = CGPointMake(x,y);
    
    //アニメーション終了
    [UIView commitAnimations];
    
}
//あたらなかった場合のペナルティ
-(IBAction)nohit;
{
    count=count-1;
    [self updatedisplay];
}

//あたった場合に音が鳴る
-(IBAction)smash
{
    AudioServicesPlaySystemSound(SoundID);
    AudioServicesPlayAlertSound(SoundID);
    AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}

//あたった場合カウントアップする
-(IBAction)countsmash
{
    count = count+1;
    [self updatedisplay];
}
//解像度取得メソッド
-(void)getresolution
{
    CGRect r = [[UIScreen mainScreen] bounds];
    CGFloat w = r.size.width;
//    CGFloat h = r.size.height;
    NSLog(@"%f",w);
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
 [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
 [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    } else {
        return YES;
    }
}

@end