2010/06/30

[objective-c][iPad][sqlite]動的にCREATEとINSERT文を発行

やっと、バインド変数ではなく、動的にSQL文を実行することに成功したので、ソースを紹介します。
//TestTable.h

#import <Foundation/Foundation.h>
#import <sqlite3.h>

@interface TestTable : NSObject {
sqlite3 *db;
NSString *dbPath;
NSArray *columnNames;
NSString *tableName;
}

@property sqlite3 *db;
@property (retain,nonatomic) NSString *dbPath;
@property (retain,nonatomic) NSArray *columnNames;
@property (retain,nonatomic) NSString *tableName;

-(id)init;
-(BOOL)openDataBase;
-(BOOL)createTable;
-(BOOL)insertData;
-(void)closeDataBase;
-(void)errDataBase;
@end

//TestTable.m
#import "TestTable.h"

@implementation TestTable

@synthesize db;
@synthesize dbPath;
@synthesize columnNames;
@synthesize tableName;
@synthesize columnDatum;

-(id)init{
self = [super init];

tableName = @"test";
columnNames = [[NSArray alloc] initWithObjects:
@"column_no1"
, @"column_no2"
, @"column_no3"
, nil
];


//dbが存在しているかどうかの確認
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.db"];

//ファイルが存在しない場合
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) {
//ファイルを作成する
BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath contents:nil attributes:nil];
//ファイル作成が失敗した場合
if (!result) {

}

//sqliteをオープンする
if([self openDataBase]){
//テーブルの作成
[self createTable];

//テーブルのクローズ
[self closeDataBase];
}

}

if([self openDataBase]){
//データを登録
[self insertData];
//テーブルのクローズ
[self closeDataBase];
}

return self;
}

//sqliteをオープンする
-(BOOL)openDataBase{
int ret;
ret = sqlite3_open([dbPath UTF8String],&db);
//正常終了
if(ret == SQLITE_OK){
return YES;
//異常終了
}else {
//エラーが発生してしまったので、クローズを行う
sqlite3_close(db);
return NO;
}
}

//tableの作成
-(BOOL)createTable{
//sqlの設定
NSMutableString *createsql = [NSMutableString string];
[createsql appendString:@"CREATE TABLE "];
[createsql appendString:tableName];
[createsql appendString:@"("];
for (NSUInteger i=0; i< [columnNames count]; i++) {
[createsql appendString:((i>0)?@",":@"")];
[createsql appendString:[columnNames objectAtIndex:i]];
}
[createsql appendString:@")"];

//各関数の戻り値
int ret;
//sql文を実行するための変数
sqlite3_stmt *sqlstmt;

ret = sqlite3_prepare_v2(db,[createsql UTF8String],-1,&sqlstmt,NULL);
//実行準備おk
if(ret == SQLITE_OK){
//sqlの実行を行う
ret = sqlite3_step(sqlstmt);
//sql文の解放
sqlite3_finalize(sqlstmt);

//sqlの実行が正常終了した場合
if(ret == SQLITE_DONE){
return YES;
}
}

//エラーメセッドをコール
[self errDataBase];
//dbクローズ
[self closeDataBase];
return NO;

}

-(BOOL)insertData{

NSArray *tmpArray = [[NSArray alloc] initWithObjects:@"test_01"
, @"test_02"
, @"test_03"
, @"test_04"
, nil
];

BOOL q_Ret = NO;

//各関数の戻り値
int ret;

//トランザクションの開始
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL);

//insert文の作成
sqlite3_stmt* sqlstmt;
NSMutableString *inssql = [NSMutableString string];
[inssql appendString:@"insert into "];
[inssql appendString:tableName];
[inssql appendString:@"("];
for (NSUInteger i=0; i<[columnNames count]; i++) {
[inssql appendString:((i>0)?@",":@"")];
[inssql appendString:[columnNames objectAtIndex:i]];
}
[inssql appendString:@")values("];
for (NSUInteger i=0; i<[columnNames count]; i++) {
[inssql appendString:((i>0)?@",":@"")];
[inssql appendString:@"?"];
}
[inssql appendString:@")"];

ret = sqlite3_prepare_v2(db, [inssql UTF8String], -1, &sqlstmt, NULL);
//構文解析の結果問題なし(バインド前)
if (ret == SQLITE_OK) {
for (NSUInteger tmp=1; tmp<3; tmp++) {
//sqlをリセット
sqlite3_reset(sqlstmt);
//バインド変数をクリアー
sqlite3_clear_bindings(sqlstmt);
sqlite3_bind_text(sqlstmt,1,[[tmpArray objectAtIndex:(tmp-1)] UTF8String],-1,SQLITE_TRANSIENT);
sqlite3_bind_text(sqlstmt,2,[[tmpArray objectAtIndex:tmp] UTF8String],-1,SQLITE_TRANSIENT);
sqlite3_bind_text(sqlstmt,3,[[tmpArray objectAtIndex:(tmp+1)] UTF8String],-1,SQLITE_TRANSIENT);
//sql文を実行
ret = sqlite3_step(sqlstmt);

//一回でもエラーが発生した場合はクローズさせて終了
if(ret != SQLITE_DONE){
//sql文の解放
sqlite3_finalize(sqlstmt);
//異常終了(ROLLBACKして処理を終了)
sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
//エラーメソッドをコール
[self errDataBase];
//dbをクローズ
[self closeDataBase];
return q_Ret;
}
}
//正常終了(COMMITをして処理を終了)
sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, NULL);
q_Ret = YES;
//構文解析の結果問題あり(バインド前)
}else {
//エラーメソッドをコール
[self errDataBase];
//異常終了(ROLLBACKして処理を終了)
sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
}

//sql文の解放
sqlite3_finalize(sqlstmt);

//クローズ
[self closeDataBase];
return q_Ret;
}

//sqliteをクローズする
-(void)closeDataBase{
sqlite3_close(db);
}

//sqliteのエラー処理
-(void)errDataBase{

UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[[NSString alloc] initWithFormat:@"error:%d",sqlite3_errcode(db)]
message:[[NSString alloc] initWithUTF8String:sqlite3_errmsg(db)]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil
];
[alertView show];
[alertView release];

}

@end

NSArrayとNSStringクラスを使ってそれぞれカラム名とテーブル名をセットした後、createTableメソッドでテーブルを作成し、insertDataでデータの登録をしています。

かつinitメソッドで設定しているので、initメソッドを拡張させることで、インスタンス変数宣言時に、これらの変数をもっていくことができます。

ただ唯一気になったのが、sqlite3_prepare_v2の第二引数にchar型のsql文を叩き込むのですが、NSMutableStringでセットした変数を一度、char型変数にセットするとコンパイル時に警告がでちゃうんですよね〜。

なぜだろう???

ちなみに、上記を実行した結果、正常終了しました。

ここまでくると、iPad版のObjectBrowser的なものを作りたくなってきた。

ただ、やはり、INSERT文発行時に、登録対象となるデータをインスタンス変数に設定したいなー。
getterとsetterを使ってインスタンス変数経由で、うまくできないものだろうか?

NSDictionaryとNSArrayを使ってどうにかならないものかなーっと想定しているのだが。

2010/06/29

[本]上司は思いつきでものを言う

やっとこさ、読了。

第1章 上司は思いつきでものを言う
第2章 会社というもの
第3章 「下から上へ」がない組織
第4章 「上司でなにが悪い」とお思いのあなたへ

via:目次

なんかタイトルでつられてしまったような。

書いてあることがタイトルと全然違ったような。

後、重複されてい何回も同じことが書いてあったような。
これ、凝縮させれば、半分ぐらいの量に落ち着いたんじゃーないのかなーっと。

とサッカーをみながら、感想文

2010/06/28

[objective-c][iPad][sqlite]INSERT文の発行その2

前回は、バインド変数を使わずに、INSERT文を実行する方法について書きました。

今日は、長い試行のすえできた、バインド変数を使ったトランザクション処理について書いてみたいと思います。

// TestTable.h

#import <Foundation/Foundation.h>
#import <sqlite3.h>

@interface TestTable : NSObject {
sqlite3 *db;
NSString *dbPath;
}

@property sqlite3 *db;
@property (retain,nonatomic) NSString *dbPath;

-(id)init;
-(BOOL)openDataBase;
-(BOOL)createTable;
-(BOOL)insertData;
-(void)closeDataBase;
-(void)errDataBase;
@end

// TestTable.m
#import "TestTable.h"

@implementation TestTable

@synthesize db;
@synthesize dbPath;

-(id)init{
self = [super init];

//dbが存在しているかどうかの確認
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.db"];

//ファイルが存在しない場合
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) {
//ファイルを作成する
BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath contents:nil attributes:nil];
//ファイル作成が失敗した場合
if (!result) {
}
//BOOL sql_exec_ok = NO;
//sqliteをオープンする
if([self openDataBase]){
//テーブルの作成
[self createTable];

//データを登録
[self insertData];

//テーブルのクローズ
[self closeDataBase];
}
}
return self;
}

//sqliteをオープンする
-(BOOL)openDataBase{
int ret;
ret = sqlite3_open([dbPath UTF8String],&db);
//正常終了
if(ret == SQLITE_OK){
return YES;
//異常終了
}else {
//エラーが発生してしまったので、クローズを行う
sqlite3_close(db);
return NO;
}
}

//tableの作成
-(BOOL)createTable{
//sqlの設定
char *sql = "CREATE TABLE test(column_no1,column_no2)";
//各関数の戻り値
int ret;
//sql文を実行するための変数
sqlite3_stmt *sqlstmt;

ret = sqlite3_prepare_v2(db,sql,-1,&sqlstmt,NULL);
//実行準備おk
if(ret == SQLITE_OK){
//sqlの実行を行う
ret = sqlite3_step(sqlstmt);
//sql文の解放
sqlite3_finalize(sqlstmt);

//sqlの実行が正常終了した場合
if(ret == SQLITE_DONE){
return YES;
}
}

//エラーメセッドをコール
[self errDataBase];
//dbクローズ
[self closeDataBase];
return NO;

}

-(BOOL)insertData{

NSArray *tmpArray = [[NSArray alloc] initWithObjects:@"test_01"
, @"test_02"
, @"test_03"
, @"test_04"
, nil
];

BOOL q_Ret = NO;

//各関数の戻り値
int ret;

//トランザクションの開始
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL);

//insert文の作成
sqlite3_stmt* sqlstmt;
char *sql = "insert into test(column_no1,column_no2)values(?,?)";
ret = sqlite3_prepare_v2(db, sql, -1, &sqlstmt, NULL);
//構文解析の結果問題なし(バインド前)
if (ret == SQLITE_OK) {
for (NSUInteger tmp=1; tmp<3; tmp++) {
//sqlをリセット
sqlite3_reset(sqlstmt);
//バインド変数をクリアー
sqlite3_clear_bindings(sqlstmt);
sqlite3_bind_text(sqlstmt,1,[[tmpArray objectAtIndex:(tmp-1)] UTF8String],-1,SQLITE_TRANSIENT);
sqlite3_bind_text(sqlstmt,2,[[tmpArray objectAtIndex:tmp] UTF8String],-1,SQLITE_TRANSIENT);
//sql文を実行
ret = sqlite3_step(sqlstmt);

//一回でもエラーが発生した場合はクローズさせて終了
if(ret != SQLITE_DONE){
//sql文の解放
sqlite3_finalize(sqlstmt);
//異常終了(ROLLBACKして処理を終了)
sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
//エラーメソッドをコール
[self errDataBase];
//dbをクローズ
[self closeDataBase];
return q_Ret;
}
}
//正常終了(COMMITをして処理を終了)
sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, NULL);
q_Ret = YES;
NSLog(@"OKです");
//構文解析の結果問題あり(バインド前)
}else {
//エラーメソッドをコール
[self errDataBase];
//異常終了(ROLLBACKして処理を終了)
sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
}

//sql文の解放
sqlite3_finalize(sqlstmt);

//クローズ
[self closeDataBase];
return q_Ret;
}

//sqliteをクローズする
-(void)closeDataBase{
sqlite3_close(db);
}

//sqliteのエラー処理
-(void)errDataBase{

UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[[NSString alloc] initWithFormat:@"error:%d",sqlite3_errcode(db)]
message:[[NSString alloc] initWithUTF8String:sqlite3_errmsg(db)]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil
];
[alertView show];
[alertView release];

}

@end

バインドの方法は、SQLiteで“おこづかいちょう”の部分を読みながら、NSArrayに設定したNSStringをchar型に変換させて、それを、sqlite3_bind_text関数を使ってバインドさせてます。

同関数の第四引数には、SQLITE_TRANSIENTという定数があるが、これは、Binding Values To Prepared Statementsを読んで、SQLITE_STATICかSQLITE_TRANSIENTという選択肢があり、SQLITE_STATICは性的な場合のみ使えと書いてあったので、今回、SQLITE_TRANSIENTを採用しました。

ここからちょっと気になったのだが、SQLiteで“おこづかいちょう”に記載されていたコードには、sql文を解放させるsqlite3_reset関数が使われていたが、バインド変数をリセットするsqlite3_clear_bindingsが使われていなかった。

確かに、sqlite3_clear_bindings関数を使わずに実行をした結果、きちんと登録されているが、Reset A Prepared Statement Objectを読んでみると、

Any SQL statement variables that had values bound to them using the sqlite3_bind_*() API retain their values. Use sqlite3_clear_bindings() to reset the bindings.

via:Reset A Prepared Statement Object

と書いてあるので、やはり、sqlite3_clear_bindings使わないといけないんじゃーないのかなーっと疑問に思いつつ。

やっとこれでバインド変数を使った動的SQL文を作成することができました。

ただ、やはり、前回から指摘しているが、各メソッドに、カラム名及び、テーブル名を直指定してしまっている。

これを、NSStringなどの変数に設定して、動的に、テーブルを作成したり、ドロップしたりすることはできないのだろうか?
そうすれば、もっとプログラム全体が汎用的になるはず。

実は、その方法も発見したのですが、今回は、バインド変数を使った登録までなので、次回に譲りたい。

2010/06/27

[本]頭のいい段取りの技術

こちらも堪能

第1章 「段取り」とは一体なにか?
第2章 余裕を生み出す「予定・時間管理」の段取り術
第3章 仕事スピードが上がる「環境・情報整理」の段取り術
第4章 超効率アップ!「知的作業」の段取り術
第5章 できる人の「コミュニケーション」段取り術
第6章 「ゴチャゴチャ仕事」の段取りのつけ方・動かし方─実践編
終章 段取りの目的は人生を楽しむこと!

via:目次

ひょっとしたら、ここまで具体的かつプログラマー視点の仕事術の本を読んだことがなかったかも。

そう、著者は、元プログラマーなので、合理的かつ論理的に仕事を進める方法、つまり、段取りについてフォーカスしている本でありました。

読み進めていくと、すでに実行していることがあり、特にバッファを使った工数見積にすごく納得してしまった。

会社に入って驚いたのは、バッファを取らず工数を見積もっていたこと。
急な仕様変更やバグ、不具合、プログラム難易度の設定ミスから工数が遅れてしまう可能性が十分にあるし、現にそんなことはしょちゅうなのに、早く仕事を進めるのがお客様のサービスだと思っているのか、ギリギリの工数で算出していたため、いつも納期に遅れる結果になり、以後の案件ではバッファをとるように、後輩社員ながら、いつも直訴していました。

バッファをとることで、作業する社員に心の余裕ができるし、早くできてしまった場合は、他の案件に時間を割く事ができるとうれしいことずくめ。
他にもいくつかバッファを取る理由があるのですが、話がずれてしまうので、それはまた今度。

かつさらに具体的な方法については本書で確認を。

しかし、著者の用心深さに驚くばかりでした。
ここまで、用心深くなるためには、日々の注意力を鍛錬する必要があるのかと。

またアイデア創出法も納得、納得。
考えこんで出るわけでもなく、日々、想像していくことが重要なんですね。
しかも、出てきた瞬間にメモることも大事。

こうして、書いてみると、日々、意識して生活をしていくことが、段取りをする上で大切なんだなーっと。

段取りを駆使して仕事を効率的に処理したい方は、必見。

弾さんの本当に頭のいい一冊 - 書評 - 頭のいい段取りの技術も是非、参考に

2010/06/26

[本]数に強くなる

この本もおもしろかったなー。


1 数に強くなる
2 数の感覚をみがく
3 数の声を聞く
4 数を使う

via:目次

本書は、数学でもなく、ましては数(すう)でもなく、数(かず)に強くなるための本である。

数と聞くと「う〜ん???orz」となってしまう方、ご安心を。

この本は、そんな悩みとは裏腹に、身近な問題について、イラストをふんだんに取り入れ、著者のおもしろい蛇足を織り交ぜながら、数をベースにその問題を解決していく方法が、書かれている。
(蛇足として奥さんとの日常会話があるのですが、おもしろすぎて腹を抱えてしまうほど笑ってしまいました。)

つまり、数をツールとして使いこなして、人生の幅を広げようぜーという流れです。

ここまで、厳密に数学ではなく数について解説しているおもしろい本あったかなーっと思ったぐらいです。
ただ対数という概念が登場するので、高校数学をやっていない方はちょっと厳しいかもしれません。
後、最初は、数を使いこなしている人の特徴や、数の概念が出てくるのですが、そこを乗り越えれば残りは楽勝です。

本書は、元々、弾言で紹介されていて興味が沸いたので手に取りました。

弾さん自身もエントリーがありますので、参考に。
書評 - 数に強くなる

2010/06/25

[本]99.9%は仮説

今まで読んだ新書の中で一番おもしろかった。

プロローグ 飛行機はなぜ飛ぶのか?実はよくわかっていない
第1章 世界は仮説でできている
第2章 自分の頭のなかの仮説に気づく
第3章 仮説は一八〇度くつがえる
第4章 仮説と真理は切ない関係
第5章 「大仮説」はありえる世界
第6章 仮説をはずして考える
第7章 相対的にものごとをみる
エピローグ すべては仮説にはじまり、仮説におわる

via:目次

飛行機が、なぜ飛ぶのかというところから始まり、ガリレオの地動説、アインシュタインの相対性理論、クオークなど、数多くの科学を題材に仮説の本質に迫った内容なのですが、一般的に知れ渡った理論を難しい言葉ではなくわかりやすく説明している上に主題を展開していたので、非常に楽しく読むことができました。

元々、フィクッション作家なのか、最後の帰結の仕方がすごくうまくて正直鳥肌が立ってしまった。
科学の本で、ここまで感動したのは初めてだと思います。

しかし、誰でも読めるかと言えば、正直、難しいところがある。
というのも、途中でホーキングの虚時間仮説が登場するのですが、虚数についての説明がなく、高校数学をやっていないと難しい、後、ニュートンの力学方程式やアインシュタインの光学方程式なども、高校物理の範囲なので、この両方を専攻していないと、厳しいかなと。

後、ここまで科学の話をおもしろく展開しているのだから、本書全体を科学の話に統一してほしかったなーっと。
途中で仮説を日常生活やビジネスに反映させる方法について書いてあったのですが、それこそ、読者の宿題にして伏せてほしかった。
(ちょっとショック。)
でも、それだと出版社の移行にそぐわないのかなーっと思いをめぐらせてみたり。
まー難しところなのかな。

本書は、もともと、弾さんの空気を読むな、本を読め。 小飼弾の頭が強くなる読書法で紹介されていたので読みました。


弾さんのブログにも、より科学好きな人が読んだ場合の視点から書評されていました。すごく参考になりますよ。
残り0.1%も仮説 - 書評 - 99.9%は仮説

2010/06/24

[本]オラクルマスター教科書 Bronze Oracle Database 10g(DBA10g)編

やっとこさ、読了

第1章 Oracleデータベース管理の概要
第2章 Oracleソフトウェアのインストールとデータベースの作成
第3章 Oracle Enterprise Manager Database ControlとSQL Plus
第4章 Oracleネットワーク環境の構成
第5章 Oracleインスタンスの管理
第6章 データベース記憶域構造の管理
第7章 ユーザーおよびセキュリティの管理
第8章 スキーマオブジェクトの管理
第9章 バックアップおよびリカバリの実行
第10章 データベースの監視とアドバイザの使用

via:目次

はっきり言って初心者向けでは全くないし、EMが使えないと画像はあるが実感がわかない。

かつ、実際に実務で使ってないと厳しいんじゃーないのかなー。
このまま11gで機能が増えたらさらに、この本は厚くなってしまうのだろうか?

逆に、(持っている|使っている)人は、どう感じたでしょうか?

2010/06/23

[objective-c][iPad][sqlite]INSERT文の発行その1

何回かエントリーが分かれそうな気がしたので。

やっとできたINSERT文の方法について書いていきたいと思います。
と同時に、CREATE文やオープン、クローズの作業をメソッド化させて、前回よりも、綺麗に整いました。

//TestTable.h

#import <Foundation/Foundation.h>
#import <sqlite3.h>

@interface TestTable : NSObject {
sqlite3 *db;
NSString *dbPath;
}

@property sqlite3 *db;
@property (retain,nonatomic) NSString *dbPath;

-(id)init;
-(BOOL)openDataBase;
-(BOOL)createTable;
-(BOOL)insertData;
-(void)closeDataBase;
-(void)errDataBase;
@end

//TestTable.m
#import "TestTable.h"


@implementation TestTable

@synthesize db;
@synthesize dbPath;

-(id)init{
self = [super init];

//dbが存在しているかどうかの確認
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.db"];

//ファイルが存在しない場合
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) {
//ファイルを作成する
BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath contents:nil attributes:nil];
//ファイル作成が失敗した場合
if (!result) {

}
//BOOL sql_exec_ok = NO;
//sqliteをオープンする
if([self openDataBase]){
//テーブルの作成
if ([self createTable]) {
if([self insertData]){
NSLog(@"正常終了しました。");
}
};

//テーブルのクローズ
[self closeDataBase];
}

}
return self;
}

//sqliteをオープンする
-(BOOL)openDataBase{
int ret;
ret = sqlite3_open([dbPath UTF8String],&db);
//正常終了
if(ret == SQLITE_OK){
return YES;
//異常終了
}else {
//エラーが発生してしまったので、クローズを行う
sqlite3_close(db);
return NO;
}
}

//tableの作成
-(BOOL)createTable{
//sqlの設定
char *sql = "CREATE TABLE test(column_no1,column_no2)";
//各関数の戻り値
int ret;
//sql文を実行するための変数
sqlite3_stmt *sqlstmt;

ret = sqlite3_prepare_v2(db,sql,-1,&sqlstmt,NULL);
//実行準備おk
if(ret == SQLITE_OK){
//sqlの実行を行う
ret = sqlite3_step(sqlstmt);
//sql文の解放
sqlite3_finalize(sqlstmt);

//sqlの実行が正常終了した場合
if(ret == SQLITE_DONE){
return YES;
}
}

//エラーメセッドをコール
[self errDataBase];
//dbクローズ
[self closeDataBase];
return NO;

}

-(BOOL)insertData{
BOOL q_Ret = NO;

//各関数の戻り値
int ret;

//トランザクションの開始
sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL);

//insert文の作成
char *sql = "insert into test(column_no1,column_no2)values('こんばんわ','abcdef')";
ret = sqlite3_exec(db, sql, NULL, NULL, NULL);
//正常終了(COMMITをして処理を終了)
if(ret == SQLITE_OK){
//COMMIT
sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, NULL);
q_Ret = YES;
//異常終了(ROLLBACKして処理を終了)
}else {
//エラーメセッドをコール
[self errDataBase];
//ROLLBACK
sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL);
}

return q_Ret;
}

//sqliteをクローズする
-(void)closeDataBase{
sqlite3_close(db);
}

//sqliteのエラー処理
-(void)errDataBase{

UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:[[NSString alloc] initWithFormat:@"error:%d",sqlite3_errcode(db)]
message:[[NSString alloc] initWithUTF8String:sqlite3_errmsg(db)]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil
];
[alertView show];
[alertView release];

}

@end

それぞれのメソッドは、
openDataBaseメソッド:dbのオープン
closeDataBaseメソッド:dbのクローズ
errDataBaseメソッド:エラーメッセージをアラートで表示
createTableメソッド:TABLEの作成
insertDataメソッド:TABLEにデータを登録する
です。
twitterでもつぶやきましたが、トランザクションの書き方に時間をくいました。
こうして各作業をメソッド化することで汎用性が高まるのかなと。

ただ気に食わない部分もあり、特にINSERT文のvalues以降を動的に変更することがこの書き方ではできないこと。

for文でまわしながらそういった作業をすることが多いんだけど。もっと改良する点があるのかなと。

後、CREATE文を実行する時も、カラム名やテーブル名を直指定してしまっていること。

引数を元に、動的にTABLEを作りたい場合などには、融通が利かない。

もっと汎用的に変えていきたいと思います。

実行した結果についてですが、正常終了しました。
(ターミナルでも確認済み)

参考:
rktSQLite2:トランザクションの操作
SQLite Tutorial - Adding data

2010/06/22

[iPod touch]今、os4

をダウンロード中です。

知り合いのtweetを読んでみると、2時間かかったそうですが。

結構、時間がかかるんですね。

追記
無料のiBookがすごい。といっても、まだ本を購入していないですが。

フォルダ管理できるのもすばらしい。
弾さんのもOSのアップグレードについてレビューされていました。
iOS4 - 現在使用中のiPhone 3GSが新品同様に

2010/06/21

[Objective-C][sqlite][iPad]CREATE文の発行

今、sqliteを使ってDBの管理を行おうとしているのですが、やっと、CREATE文の発行ができたので、そのプログラムの紹介です。

参考にさせていただいたのは、SQLite Tutorial - Selecting Data

上のエントリーでは、sqliteのdbをfirefoxのアドオンを使って作成して、それをObjective-Cを使ってiPhoneのアプリ内のディレクトリにコピーしているプログラムなのだが、そのやり方になんだか違和感を感じてしまったので、データベースの作成からObjective-Cで始めて、そこから、CREATE文の実行を行い、ターミナルで確認する作業を紹介します。

では、さっそくいきます。

//dbが存在しているかどうかの確認
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.db"];
//ファイルが存在しない場合
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) {
//ファイルを作成する
BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath contents:nil attributes:nil];
//ファイル作成が失敗した場合
if (!result) {

}
BOOL sql_exec_ok = NO;
sqlite3 *db;
int ret;
//sqliteをオープンする
ret = sqlite3_open([dbPath UTF8String],&db);
//sqliteのオープンに成功した場合
if (ret == SQLITE_OK) {
//sqlの設定
const char *sql = "create table test(column_no1,column_no2)";
//実行するsqlを格納する変数
sqlite3_stmt *sqlstmt;
ret = sqlite3_prepare_v2(db,sql,-1,&sqlstmt,NULL);
//sqlの準備完了の場合
if(ret == SQLITE_OK){
//sqlの実行を行う
ret = sqlite3_step(sqlstmt);
//sqlの実行が正常終了した場合
if(ret == SQLITE_DONE){
//sql文の解放
sqlite3_finalize(sqlstmt);
sql_exec_ok = YES;
}
}
}

//sqliteをクローズする
sqlite3_close(db);

//テーブルの作成が正常に完了できなかった場合
if(!sql_exec_ok){

}
}

まず最初の2行で、iPhoneのDocumentフォルダにあるtest.dbというファイルの確認を行います。

ファイルが存在する場合は、何も処理を行いません。

ファイルが存在しない場合は、一つ目のif文を通かした後の、処理でファイルの作成を行います。
(さらなる詳細については、[Objective-C][iPad]ファイルを書き出すを参照のこと)

で、ここからが重要で、まず、sqlite3_open関数を使って、データベースをオープンします。

オープンに成功した場合は、その勢いに乗っかって、sql文を記述します。

記述完了後、今度は、sqliteを実行するぞーっというのをプログラムに伝えるために、sqlite3_prepare_v2関数を使います。
(ここは、sqlite3_prepareもありますが、ドキュメントでは、sqlite3_prepare_v2が推奨されています。)

if文を使って準備がオッケーだった場合、sqlite3_step関数を使って、いざ実行

実行が正常終了した場合、sqlite3_finalize関数を使って、sql文の解放を行います。

そして、最後に、sqlite3_close関数を使って、データベースをクローズします。

script系言語からdbを触ったことがある方には、sql文の解放作業と準備作業というものがあることに少し気持ち悪さを感じるかもしれません。
(それでも、CFデベロッパーよりもましで、CFの場合、sqlのオープン、クローズの概念がないので、おそらくそれ以上に気持ち悪さを感じると思います。)

これを実行すると所定のフォルダに、データベースファイルができており、ターミナルからそのファイルをsqlite3コマンドを使ってオープンすると、確かに、テーブルができていることが確認できました。

ただ、やはりまだプログラム全体に気持ち悪さを感じてしまう。

データベースのオープンや、クローズは、別メソッドにして、そこで管理したりする方が、汎用性が高いかもしれない。
さらに、今回は、CREATE文だけだったから、この量ですんだものの、INSERT文だったり、UPDATE文だったりしたら、もっと増えると考えると、やはり、もっと柔軟に作り返る必要性があるかもしれない。

そこの辺は、また出来次第、改めて、考察していく。

補足;
上で紹介したエントリーに日本語和訳が、あるみたいです。↓で紹介されていました。
■[iPhone]SQLite Tutorialを日本語に訳した 20:22

でも、エントリーをいくら探しても、日本語訳見つからないんだよなー。。。
どうしたもんでしょ?

2010/06/20

[本]本気で稼ぐための「アフィリエイト」の真実とノウハウ

家内が実家に帰っている間に、読了

Prologue アフィリエイトの現実
1. アフィリエイトは理にかなった広告手法
2. ネット上だけで完結して稼ぐなんて怪しい?
3. 1%のアフィリエイターが売り上げの99%を稼ぐ
Column 『アフィリエイトでめざせ! 月収100万円』の紹介
4. 上位のアフィリエイターはどれくらい儲けているのか
5. 実はスーパーアフィリエイターは数字ほど儲かっていない
Chapter 1 アフィリエイトの周りでカモる人たち
1. 素人を狙う詐欺師たち
2. サイト制作会社
3. 情報商材販売者
Column 究極のアフィリエイトで儲ける情報商材
4. アフィリエイトツール販売者
Column なぜ迷惑ブログが増えたのか?
5. アフィリエイトセミナー・塾の主催者
6. 自分が運営するサイトを教えてくれない人のノウハウは信用するな!
Column 事業投資は自分の責任
Chapter 2 悪事を働く広告主!
1. 広告主にも注意が必要!?
2. 成果を承認しない広告主
3. アフィリエイトをすぐやめる広告主
4. ASPをすぐに乗り換える広告主
Column アフィリエイトはコンテンツをゆがめる!?
Chapter 3 深刻なASPの問題
1. ASPすらアフィリエイターの味方ではない!?
2. スパムを指導する団体とつながるASP
3. ASPは大切なことを広告主に教えていない
4. ASPはアフィリエイターをビジネスパートナーとは思っていない
Column アフィリエイターにも問題がある?
5. ASPに取り合ってほしかったら成果を上げろ!
Chapter 4 悪事を働くアフィリエイター!
1. 一番悪いのはアフィリエイター自身!?
2. 掲示板やコミュニティへのスパム行為
3. こっそり違法サイトに広告を掲載する
4. 無意味なサイトを量産する
Column スパムブログを取り締まらないサービス提供企業側
Column 無意味なブログで稼げるのか?
5. 未検証情報の寄せ集めサイトを量産する
6. 引っ越した有名サイト跡地を使う
7. 個人情報を集め、なりすましで会員登録アフィリエイトを繰り返す
8. サービス解除と引き換えに携帯有料サイト登録を迫る
9. ASPに強制退会させられても現れるアフィリエイター
10. 納税しないアフィリエイター
Chapter 5 アフィリエイトで稼ぐための基本思考
1. コソコソ稼げば叩かれる
2. 複数のショップへのリンクを用意する
Column 根強い「嫌儲」意識
3. ダメ元で寄付を募ってみよう
4. リンクが広告かどうかを気にしすぎない
5. 広く浅く知識を付けよ
6. いろんなものを組み合わせてみよう
7. RSSリーダーで情報収集する
8. 改善案を空想して発想力を鍛えよう
9. 枯れた技術の水平思考
10. 価格の分岐点を意識しよう
11. ユーザーが面倒なことをしてあげよう
12. 自分が使いたいサイトを作る
13. 承認率よりEPCを重視せよ
14. 特定広告に依存しない
15. ウェブ制作ができないなら動画を使え!
16. アフィリエイトに超使えるサービス・ツール17選
17. もう作っちゃったサイトにこだわらない
18. アフィリエイトにこだわるな!
19. 無料サイトから収益を上げる、アフィリエイト以外の方法
20. 儲からないなら広告は貼るな!
21. 儲けたかったらコンテンツを作るな!
Column コンテンツを作る企業が儲けるには?
Chapter 6 ブログで稼ぐための考え方
1. ブログ+アフィリエイトは基本的に儲からない
2. ブログで収入を得る方法(1) 有名人になる
Column 小飼弾さんインタビュー
3. ブログで収入を得る方法(2) お役立ち記事を書き続ける
Column コグレさんインタビュー
4. ブログで収入を得る方法(3) 海外の良質記事を翻訳する
5. ブログで収入を得る方法(4) 特定ジャンルのレビューに特化する
Column うかさんインタビュー
6. ブログで収入を得る方法(5) 評判がよい商品を見つけて紹介する
Column こたろうさんインタビュー
7. ブログで収入を得る方法(6) 巨大掲示板の面白いスレッドを紹介する
8. ブログは自己ブランディングのツールと考える
9. ブログに新しい読者を集めるための23の方法
Chapter 7 集客のノウハウ
1. 検索エンジン対策を気にしすぎない
2. 知っておきたいアクセス解析
3. 死ぬほど重要な携帯電話対応
4. パソコンと携帯表示を同じURLにする
5. パソコン向けサイトを簡単に携帯対応する方法
Column 広告主が分断している、PCと携帯電話の壁
6. プレスリリースを打つ
7. アルファブロガーに告知する
Chapter 8 アフィリエイトで使えるプログラミング・テクニック
1. 本気で稼ぎたいならプログラムを使え!
2. プログラムを学ぶ基本姿勢
Column ロプロスさんインタビュー
3. 10週間でプログラミングの基本を身に付けよう
4. プログラムを動かしてみよう!
5. パソコンと携帯で表示を変えてみよう!
6. APIを使ってみよう!
7. 検索エンジンを作ってみよう!
8. 商品検索サイトを作ってみよう!
9. アフィリエイトにおすすめのAPI
10. APIを自分で探してみよう!
11. APIで生きる者はAPIで死ぬ
Column プログラムが組めたら儲かると思ったら大間違い!
Appendix 1 アフィリエイトのよくある相談25本ノック
質問1 アフィリエイトで儲かるという情報商材を買ったが儲かりません。
質問2 アフィリエイトで儲かる方法を教えてくれる塾に入ってサイトを量産しているけれど収入にならない。
質問3 アフィリエイト収入を全部キャンセルされました。どうしてでしょうか?
質問4 他のブログにコメントやトラックバックをたくさん送ってアクセスを稼いでいるのに成果につながりません。
質問5 アフィリエイトをはじめて3週間経つのに、まだ成果は100円しかありません。
質問6 リスティング(PPC)広告を使ってはいけないと聞きましたが本当ですか?
質問7 セミナーや勉強会などのアフィリエイトイベントに参加するにはどうすればよいですか?
質問8 アフィリエイト提携を拒否される理由にはどういったものがあるんでしょうか?
質問9 広告主を選ぶ基準はあるのでしょうか?
質問10 ASPを選ぶ基準はあるのでしょうか?
質問11 無料ブログはどこを選ぶのがよいのでしょうか?
質問12 サイトテーマはどのように選べばよいのでしょうか?
質問13 できるだけ早く収入を得たいのですが、どう行動するのがベストでしょうか?
質問14 本人申し込みでもアフィリエイト報酬は獲得できるのでしょうか?
質問15 ブログ自動更新ソフトを購入してアフィリエイトに取り組むのはアリでしょうか?
質問16 アフィリエイトのノウハウを学びたいのですが、おすすめのスクールや塾はありますか?
質問17 アフィリエイト成果の高いサイトにはどういった特徴があるのでしょうか?
質問18 月数十万の収入を目指す場合、アフィリエイトサイトはどれくらい運営するのがよいのでしょうか?
質問19 ASPの管理画面画像を自分のブログやサイトに掲載したいのですが可能でしょうか?
質問20 カリスマアフィリエイターを名乗る方からアフィリエイトで稼ぐコツを教えてあげると連絡がきましたが、教わって大丈夫でしょうか?
質問21 アフィリエイトは初心者でも楽して稼げると聞きましたが、本当でしょうか?
質問22 ある程度アフィリエイトに予算を使おうと思うのですが、まずはどこにお金をかけるのがよいでしょうか?
質問23 アフィリエイトにかけるお金と時間はどれくらいがよいのでしょうか?
質問24 アフィリエイトで友人や知り合いを増やしたいのですが、どうすればよいでしょうか?
質問25 成果の高いベテランアフィリエイターの方々に共通していることは何かありますか?
Appendix 2 アフィリエイトの未来を語る座談会
情報商材と電子ブック
情報商材のネーミングが変わってイメージも変わるのか
アフィリエイターのモラル
ASPに登録するハードルは上げられるのか
試験制度を導入してみてはどうか
アフィリエイトの裾野はまだ広げるべきなのか
アフィリエイト初心者への教育
お小遣い稼ぎ意識とビジネス意識のギャップ
アフィリエイターの本人確認
携帯アフィリエイトの影響
これからのインターネットユーザーは
ますます携帯に移行する?
リダイレクト問題の解決
Appendix 3 ASPは諸問題をどう捉えているのか?
リンクシェア・ジャパン株式会社
株式会社ファンコミュニケーションズ(A8.net)
バリューコマース株式会社
株式会社インタースペース(アクセストレード)
株式会社アドウェイズ(JANet、Smart-C)
Column アフィリエイトに関する諸問題の解決方法
Appendix 4 広告主のカモられ方

via:目次

どうやってアフィリエイトで稼ぐかということよりも、今現実問題として、アフィリエイトでこういう問題があって、実際に問題が発生しているということに、約半分以上のページが割かれていました。

なので、本書を通して、月収100万円狙うぞーっとか、そういうことを考えている方には、まるで向かいない本であります。
むしろ、アフィリエイトで損をしないための方法を知りたい場合は、本書は良書と言える存在。

本書を読んですっきりしたのは、アフィリエイトで稼ぐことができるビジネスモデルを他のブログやサイトを見て思考していたのですが、そのビジネスモデルが本書で紹介されており読みが当たったこと。

空想したビジネスモデルの妥当性が検証できたので、その点、自信を持つことができたなーっと。

他は、すでに実戦していることばかりだし、プログラムに関しては、がっつり本ブログで書いているからなー。
本書を通して、PHPプログラマーが増えそうだな。

最後に、Appendix 4で広告主のカモられ方が紹介されていたのですが、ここまでさらけ出してしまっていいのだろうか?というぐらいの内容だったのですが、これって本当?

これが真実だとするとものすごく怖いことであり、今後のASPの各社の改善活動、啓蒙活動に注目したいです。

本書は、NETAFULLさんの本気で稼ぐための「アフィリエイト」の真実とノウハウ、という本の帯を書きましたのエントリーに興味が沸き手に取りました。

2010/06/19

[本]Ajaxアプリケーション & Webセキュリティ

時が過ぎていくのを忘れてしまうほどのめり込んでしまった。

はじめに

1章 Webの進化

2章 Webセキュリティ

3章 Web関連の技術のセキュリティ

4章 サーバーの保護

5章 基盤技術の弱さ

6章 Webサービスの保護

7章 Web経由のAPI

8章 マッシュアップ

索引

via:目次

実は、とても幸運なことに本書籍は、仕事のお客様から頂いたのです。

この場を借りてありがとうございます。

本書は、タイトル通りAjaxアプリケーションの構成とWebセキュリティについて書かれているのですが、そのカバーしている範囲が広いのなんのって。

脆弱性を突く攻撃の解説一つとってみても、XSSやSQLインジェクションといった最新のものからバッファオーバーフローなどの古典的な攻撃などの解説や、AjaxもRESTだけではなくSOAPやRPCなど一通りの説明が網羅されており、さらにそれだけではなく、httpプロトコルやインターネットにまつわる歴史、変遷など、どうしても本書のタイトルを理解する上で必要となる基盤となる技術もきちんと解説しているので、本書は、まさに、これからWebアプリケーションにセキュリティを導入する上で道しるべとなる一冊だと思いました。

Ubuntuサーバーを使ったwebサーバーの構築方法を解説してくれているのも、なんともたまらない。

サーバーをたてるときは、ガシガシ参考にするぞ〜。

2010/06/18

[sqlite]は、[mac]にビルドインされていた

やはり、予想とおり、初期インストールされていた。

Mac OSX 10.6 Snow Leopardには、SQLiteという軽量データベースがはじめからインストールされています。

via:Mac OS X. 10.6 Snow LeopardでSQLite3を動かしてみたよ。

そう思ったのは、とても単純な理由からでPHPが初期インストールされているから。

PHPをインストールするとsqliteがバンドルされているので、ターミナルからおそらく実行できることは、容易に想像できた。

しかし、問題は、どうやって実行するのかというところ。

SQLite3を終了する

.exitまたは.quitで終了することができます。

・・・省略・・・

sqlite> .quit

・・・省略・・・

データベースの作成

・・・省略・・・

$ sqlite3 hoge.db

・・・省略・・・

via:Mac OS X. 10.6 Snow LeopardでSQLite3を動かしてみたよ。

これで、iPhoneで作成したsqliteに本当にデータが登録されているか確認することができるぞと。

2010/06/17

[Python]2.5.2をインストール

話が、前後してしまいましたが、windows xp上で、python 2.5のインストール方法について。

snow leopardの場合、すでに、Python 2.6がインストールされているので。

ここから、2.5.2をダウンロード

後は、ダウンロードしたファイルをダブルクリックして、下記の画面の流れに従っていきます。

Photobucket
すべてのユーザーで使う必要がなかったので、2番目にチェックを入れて「Next」を押します。

Photobucket
ここは、そのまま「Next」を押します。

Photobucket
ここも、そのまま「Next」を押します。

Photobucket
じーと待ちます。

Photobucket
「Finish」ボタンを押してインストールが完了です。

2010/06/16

[sqlite][C]言語を使った処理の流れ その1

現在、iPadアプリでsqliteを使う方法を模索しているのですが、調査の結果として、C言語を使ってsqliteのsql文を実行すればいいことまでたどりつき、そもそもC言語の場合におけるsqliteの処理の流れがわかっていないので、その確認から。

An Introduction To The SQLite C/C++ Interfaceを読むと、

sqlite3_open()

sqlite3_prepare()

sqlite3_step()

sqlite3_column()

sqlite3_finalize()

sqlite3_close()

という流れになっています。

まず、sqlite3_open関数を使って、databaseをオープンします。

次に、sqlite3_prepare関数(sqlite3_prepare_v2が、現行では推奨されている。)を使って、今度は、実行対象となるsql文の準備を行います。

で、sqlite3_step関数(fetch作業に相当)を使って、sql文の実行を行い、sqlite3_column関数で、各カラムの値を取得します。

最後に、sqlite3_finalize関数で、sql文のクリアーを行い、sqlite3_close関数で、databaseのクローズをします。

だいたい大まかな流れとしては、こんな感じ。

しかし、若干、必要される処理が多い気がするのですが。。。

上記を簡便するために、sqlite3_exec関数が用意されているようなのですが、うーん、まだ実行していないので、実際ところはどうなのでしょうか?

引き続き、調査を行います。

2010/06/15

[Objective-C][iPad]ファイルを書き出す

前回、iPhoneの直下のディレクトリフォルダに、[Objective-C][iPhone sdk]Documents内にテキストファイルを書き出すというタイトルで、テキストファイルを吐き出す方法について書きましたが、今日は、前回、紹介した方法と違う方法を発見したので、紹介します。

前回は、NSStringを使ってなか強引に空文字列を作り出すことによってファイルを作成しました。
今回は、もっとスマートにいきたいと思います。

//dbが存在しているかどうかの確認
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.db"];
//ファイルが存在しない場合
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) {
//ファイルを作成する
BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath contents:nil attributes:nil];
//ファイル作成が失敗した場合
if (!result) {

}
}

前回と違うのは、NSFileManagerクラスのcreateFileAtPath:contents:attributesメソッドを使ってファイルを作成したところ。
もともと、NSFileManagerクラスは、ファイルのコピー、削除、作成ということに特化したクラスなので、きっとこれだけで作成できるだろうと思って調査したら案の定、空ファイルを作ることができました。

戻り値が、BOOL型なので、成功した場合と、失敗した場合とで処理を切り分ければ後はオッケーなのかと。

しかし、BOOL型は、C言語にビルトインされた型ではなくて、Objective-Cで実装された型なんですね。

そこら辺については、↓に書いてありました。こういう時に、すぱっとわかる書籍が手元にあると大変助かる。

[本]詳解 Objective-C 2.0

参考
[Objective-C][iPhone sdk]Documentsディレクトリを取得

2010/06/14

[iPhone][Objective-C]ピンとannotationを表示

今日は、地図上にピンとannotationを表示するプログラムを掲載します。
//MapTestAppDelegate.h

#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MapViewController.h"
#import "MapView.h"
#import "AnnotationToMap.h"
#import "MapViewDelegate.h"

@interface MapTestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;

@end

//MapTestAppDelegate.m
#import "MapTestAppDelegate.h"

@implementation MapTestAppDelegate

@synthesize window;


- (void)applicationDidFinishLaunching:
(UIApplication *)application {

CLLocation *location =
[[CLLocation alloc] initWithLatitude:35.660262 longitude:139.729548];
CLLocationCoordinate2D mapcenter = location.coordinate;
[location release];

MKMapView *mapview =
[[MKMapView alloc] initWithFrame:
[[UIScreen mainScreen] applicationFrame]];
MKCoordinateSpan CoordinateSpan = MKCoordinateSpanMake(0.005,0.005);
MKCoordinateRegion CoordinateRegion =
MKCoordinateRegionMake(mapcenter,CoordinateSpan);
[mapview setRegion:CoordinateRegion animated:YES];

MapViewDelegate *mapviewdelegate = [[MapViewDelegate alloc] init];
mapview.delegate = mapviewdelegate;

AnnotationToMap *annotationtomap =
[[AnnotationToMap alloc] initWithCoordinate:mapcenter];

[mapview addAnnotation:annotationtomap];
[annotationtomap release];

MapViewController *mapviewcontroller =
[[MapViewController alloc] initWithNibName:nil bundle:nil];
mapviewcontroller.view = mapview;

[window addSubview:mapviewcontroller.view];
[mapview release];
[window makeKeyAndVisible];

}


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


@end

//MapViewController.h
#import <UIKit/UIKit.h>

@interface MapViewController : UIViewController {

}


@end

//MapViewController.m
#import "MapViewController.h"


@implementation MapViewController


- (id)initWithNibName:(NSString *)nibNameOrNil
bundle:(NSBundle *)nibBundleOrNil {
if (self =
[super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {

}
return self;
}


- (void)loadView {
}

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

- (void)viewDidUnload {
}


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


@end

//MapView.h
#import <MapKit/MapKit.h>

@interface MapView : MKMapView {

}

@end

//MapView.m
#import "MapView.h"


@implementation MapView


- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}


- (void)drawRect:(CGRect)rect {
// Drawing code
}


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


@end

//MapViewDelegate.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import "AnnotationToMap.h"

@interface MapViewDelegate : NSObject <MKMapViewDelegate>{
AnnotationToMap *annotationtomap;
}

- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation;
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView;
@end

//MapViewDelegate.m
#import "MapViewDelegate.h"

@implementation MapViewDelegate

- (MKAnnotationView *)mapView:(MKMapView *)mapView
viewForAnnotation:(id <MKAnnotation>)annotation{

MKPinAnnotationView *pinannotationview =
[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:@"pin"];
pinannotationview.pinColor = MKPinAnnotationColorPurple;
pinannotationview.animatesDrop = NO;
pinannotationview.multipleTouchEnabled = NO;
pinannotationview.canShowCallout = YES;
pinannotationview.enabled = YES;

annotationtomap = annotation;
return pinannotationview;
}

- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView{
[mapView selectAnnotation:annotationtomap animated:YES];
}

@end

//AnnotationToMap.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface AnnotationToMap : NSObject <MKAnnotation>{
CLLocationCoordinate2D coordinate;
}

-(id)initWithCoordinate:(CLLocationCoordinate2D) coord;
-(NSString *)title;
-(NSString *)subtitle;

@property (nonatomic, readonly) CLLocationCoordinate2D coordinate;

@end

//AnnotationToMap.m
#import "AnnotationToMap.h"


@implementation AnnotationToMap
@synthesize coordinate;

-(id)initWithCoordinate:(CLLocationCoordinate2D) coord{
self = [super init];
coordinate = coord;
return self;
}

-(NSString *)title{
return @"タイトルでぇーす";
}

-(NSString *)subtitle{
return @"サブタイトルでーす";
}

@end

表示結果はこのようになります。
Photobucket

2010/06/13

[本]他人事ではない、ワーキングプアは自己責任か

家内がライブに行ってお留守番をしている間に読了
ワーキングプアは自己責任か
ワーキングプアは自己責任か
門倉 貴史

第1章 フリーター漂流時代の悲劇
第2章 諸外国でも増える絶望する若者たち
第3章 ワーキングプアから脱出できない現実
第4章 「心のワーキングプア」になる正社員
第5章 ワーキングプアの連鎖を断ち切るために
おわりに

via:目次

本書は、弾さんの「弾言」の中で紹介されていたので、読んでみました。

全体を通して暗〜い、話で、何一つ明るい話題がありませんでした。
逆にいうと、それだけ問題が深刻で、一人一人がきちんと考えなくてはいけないことなのだと。
ただ唯一の救いなのかなーっと思ったのが、総務省が発表したジニ係数を見ると、普段、実感している以上に格差は開いていないということが書かれていた。
後、厚生労働省が調査した結果によると、一ヶ月以上、えっちをしていない夫婦が3割ぐらいいたのですが、該当しないので、よかったなーっと。

所得格差が開いた原因として、プログラマーやSEの給料が他と比べて高いからと書かれていたが、現在はどうなのだろう?
IT業界にいるものとして、SEやプログラマーの中でもできる人とできない人での格差が広がってきているんじゃーないのかなーっと実感しています。

現代の女性は、働いていてある程度も収入を得ているので、自分自身以上に収入が多い男性を選ぶ傾向があり、よって、低所得者の男性が選ばれず結婚できず、そんでもって、セックスレス化に発展しているとあったが、学生の時に、今の家内と出会ってよかったなーっと安心しました。というのも、学生当時、収入もろくすっぽなかったので、そういった年収ベースで選んでくれたわけではないからだ。

本書が下流社会のようなクソ本と一線を画しているのは、まず現状の日本のワーキンプアや非正社員の状況を説明し、さらに正社員の問題、世界各国によるワーキンプアの問題なと問題毎にきちんとわかりやすくまとまっている点であります。

2章では、韓国の所得格差の問題について触れているが、日本以上に深刻だったのでびっくりしてしまった。
東方神起が好きなのと、新大久保でおいしいお菓子を買っているので、そんなことはないだろーっと、先入観を持っていたのが、そもそも間違っていた。
(こうして文字として起こしてみると、意味不明な先入観ですが。。。)

同様に、昨年、台北に行って夜市が、ものすごい賑わいだったので、きっと景気がいいんだろうなーっと思っていたのだが、それも間違っていて工場が次々と人件費の安い中国に移って空洞化が起きた結果、所得格差が開いてしまっているということが書いてあって、やはり観光だけではどうしても見えない部分があるんだなーっと。
(観光だけで把握しようとするのが安易な考えかもしれないのですが。。。)

話は、日本に戻りますが、現在、引きこもっている方の中に、30代や40代の方もいるというのに驚きを隠せなかった。
この時点で、もはや、ワーキンプアは、世代間を問わない問題なのだと改めて思いました。

また、本書では、いろいろな概念の言葉の勉強になりました。

ワークフェア

トリクルダウン

クズネッツの逆U字仮説

アノミー理論

などなど。

さらに、門倉onベーシック・インカム - 書評 - ワーキングプアは自己責任かにて、弾さんも、触れていますが、ベーシックインカム、ベーシックキャピタルという概念についても知る事ができます。

最後の一点ほど、反論が。

第5章で、「自分の子供が「ワーキンプア」にならないようにするためには」、ということで、その方法が記載されていましたが、その中で、就職して2年たってもすぐに会社を辞めさせないようにするということが書かれていましたが、全員が、全員、辞めさせないようにしなくてもいいんじゃーないのかなーっと。

その会社で何もすることがなく、自己の成長も見込めず、仕事ができると思うのながら、先に転職先をみつけてから、さっさと会社をやめるのもありだと思いました。

上のような反論はあるけれど、それでも、本書は、現在の日本、いや世界が抱えている問題を知るにはいい一冊であることには間違いない。