2011.05.23 10:17

iPhone (아이폰개발시 DB를 위한 Sqlite3 다루기 (2)

 

개발환경 : Mac OS X 10.6.3, Simulator - 3.1.3

 

전편에서 작성한 sqlite3 파일을 어떻게 프로젝트에 넣고 사용하는지에 대한

설명을 했었다이번에는 여기에 테이블을 만들고 데이터를 집어 넣은후

그 내용을 가져와서 테이블 형태로 보여주는 프로그램을 구현해볼 것이다.

 

퀴즈 관련 테이블을 만든다.

CREATE TABLE "quiz" ("no" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL ,

"title" VARCHAR, "question" VARCHAR, "answer" VARCHAR, "level" VARCHAR)

 

이 테이블의 용도는 퀴즈 문제를 DB 에 넣어두고 문제풀이를 위한 어플을 만드는데

쓰일것이다아무것도 없으므로 샘플데이타를 집어넣어 준다.

[샘플 insert 쿼리문]

insert into quiz (title, question, answer, level) values ('title', '질문이다', '대답이다', '1')

insert into quiz (title, question, answer, level) values ('title2', '질문이다2', '대답이다2', '2')

insert into quiz (title, question, answer, level) values ('title3', '질문이다3', '대답이다3', '3')

 

데이터베이스 테이블에 매칭되는 모델클래스를 하나만든다. Subclass  NSObject 

된다.

테이블을 표시할 UIViewController 의 첫 로딩함수에 데이터베이스 생성과 데이터를

불러올 함수를 집어넣는다.

dbName 은 sqlite3 파일명을 말하며, dbPath 는 파일이 있는 위치를 저장한다.

quizs 는 quiz 모델객체가 저장될 클래스 이다그리고 함수가 2개 있는데

checkAndCreateDatabase 는 지정한 DB 파일명이 있는지 체크하고 있으면

그냥넘어가지만 없으면 에러를 출력하게 되어있다두번째 readFromDatabase

현재 quiz 테이블에 저장된 데이터를 모두 가져와 quizs 에 저장하는

임무를 맡고 있다.

 

MainXib.h

01 @interface MainXib : UIViewController {
02     NSString *path;
03     NSString *dbName;
04     NSString *dbPath;
05      
06     NSMutableArray *quizs;
07 }
08  
09 @property(nonatomic, retain)NSMutableArray *quizs;
10  
11 - (void)checkAndCreateDatabase;
12 - (void)readFromDatabase;
13  
14 @end

UIViewController 을 상속받아 만든 클래스이므로 화면이 로딩되면 처음으로

실행되는 함수가 viewDidLoad 이다여기에 데이터베이스를 체크하고

내용을 가져오는 내용이 들어가 있다.

MainXib.m

01 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
02 - (void)viewDidLoad {
03     dbName = @"success.sqlite";
04  
05     // Get the path to the documents directory and append the databaseName
06     NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
07                                       NSUserDomainMask, YES);
08     NSString *documentsDir = [documentPaths objectAtIndex:0];
09     dbPath = [documentsDir stringByAppendingPathComponent:dbName];
10      
11     // Execute the "checkAndCreateDatabase" function
12     [self checkAndCreateDatabase];
13      
14     // Query the database for all animal records and construct the "animals" array
15     [self readFromDatabase];
16     [super viewDidLoad];
17 }

이제 테이블에 내용을 뿌려보도록 한다인터페이스 빌드에서 UITableView 를 넣고

델리게이트와 데이터소스를 연결 했다면 필수 구현함수 두가지를 작성해야한다

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section


아래의 내용은 그 두개의 함수에 구현된 내용이다소스를 보면 알겠지만

행에 집어넣을 데이터는 quiz 테이블의 title 필드이다.

01 // 셀을 넣는다
02 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
03     static NSString* cellIdentifier = @"cell";
04      
05     UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
06      
07     // 이셀객체를 생성한다.
08     if (cell == nil) {
09         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
10         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
11     }
12      
13     QuizDTO *quiz = [quizs objectAtIndex:indexPath.row];
14     cell.textLabel.text = quiz.title;
15      
16     return cell;
17 }
18  
19 // 각테이블의 섹션을 리턴한다.
20 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
21     return quizs.count;
22 }

소스가 다 작성이 되었다면 실행을 시켜본다첫번째 그림은 파이어폭스에서

select 쿼리를 날려 본 데이터이고 두번째는 프로그램을 돌렸을 때 화면에 표시된

내용이다
저작자 표시
신고
Posted by 우엉 여왕님!! ghostkyow
2011.05.23 10:16

iPhone (아이폰개발시 DB를 위한 Sqlite3 다루기 (1)

 

개발환경 : Mac OS X 10.6.3, Simulator - 3.1.3

 

아이폰을 개발하다보면 DB 관리는 필수가 된다안드로이드에서도 쓰고 있는

sqlite3 를 아이폰에서도 차용해 쓰고 있다간단한 내용은 xml로 파일입출력을

통해 개발할수도 있겠지만 저장해야되는 데이터가 복잡해지고 내용이 많아지면

파일로 관리하기엔 한계가 있다.

 

SQLite 라는 이름처럼 일반 RDBMS 관계형 DB 보다 가볍고 사용하기 편한

데이터베이스이다반면 간단한 기능만 제공한다하지만 데이터 검색과 저장관리를

위한 도구로 사용하기에는 크게 무리가 없다그리고 iPhone 2.2 SDK 이상이어야

지원을 한다.

 

(1) sqlite3 를 사용하기 위한 환경설정

 

sqlite3 를 이용해 데이터베이스 프로그램을 하기 위해서는 라이브러리를 추가해야

한다그 라이브러리는 libsqlite3.0.dylib 인데 프로젝트 > Frameworks  폴더에서

오른마우스 클릭후 Add > Existing Frameworks.. 를 선택한다.

리스트중 libsqlite3.0.dylib 를 선택하고 Add 를 클릭해 추가한다.

이제 프로그램을 할수 있는 환경은 갖추어졌다사용할 sqlite 파일을 만들어서

Resources 폴더에 추가하면 된다그것은 2번에서 다룰것이다.

 

(2)  sqlite3 DB 다루기

 

일반 RDBMS 를 다루기 위해 DB 툴을 많이 사용하게 된다내가 지금까지

유용하게 사용해온 툴로는 토드가 있는데 sqlite3 를 위한 토드는 아직까지

본적이 없다하지만 토드 이외에 누군가는 만들어 놓았을 것이라는 예상을

하며 검색해 보니 SqliteSpy 라는 델파이로 만든 프로그램을 많이 사용하고 있었다.

홈페이지 주소 : http://www.yunqa.de/delphi/doku.php/products/sqlitespy/index


SqliteSpy 간략한 내용이다.

- License

   개인적인 용도 및 비영리,비밀 교육용으로는 자유롭게 사용할 수 있으나상업적인

용도로는 사용할 수 없음.

- Version

   : Version 1.8.13, 15 Apr 2010 (2010년 6 14일 기준)

- SQL 쿼리 문장을 직접 사용하여 SQLite DB 에 삽입삭제수정을 할 수 있다.

메모리DB 를 사용하여 적은 데이터에 한해 빠른 속도의 DB 작업을 할 수 있다.

   하지만 DB의 크기가 크면 사용하는 메모리DB의 크기가 커진다.

- SQLite 가 지원하지 않는 SQL 문장을 사용할 수 없다.

 

오라클이나 MSSQL 을 위한 DB 툴을 다뤄본사람이라면 쉽게 사용할수 있다.

아주 직관적이고 기능이 간단한것들 밖에 없으며 설치 과정없이 exe 만 실행

하면 된다.

Mac 용이 없어서 아쉽다그래서 윈도우에서 작업한후 sqlite3 DB 파일만 mac 으로

옮겨 사용해야 되는 불편함이 있을 것 같다.

위의 툴보다 Mac 에서 아이폰을 개발하며 바로바로 사용할수 있는 것이 있다면

더 좋을 것이다그것이 파이어폭스에서 제공하는 유틸을 사용하는 방법인데

브라우저에서 제공하는 유틸이라니 좀 놀랍다

일단 Mac 에 파이어폭스를 설치하자그리고 실행한후 위 상단에 도구 > 부가기능을

클릭해 들어간다그리고 전체검색 탭을 눌러 SQLite Manager 0.5.15 검색해 설치한다.

설치가 되었다면 도구 > SQLite Manager 를 실행시킨다.

데이터베이스를 만든다상단 아이콘에서 왼쪽에 New Database 를 누른다.

이름을 입력하고 확인을 누르면 생성이 된다.

데이블을 만들려면 제일 왼쪽 테이블 그림 아이콘을 클릭하면 에디터 창이 나온다.

테이블명을 입력하고 각각의 필드들에 대한 내용을 채워넣는다.

이제 만들어진 sqlite 파일을 프로젝트에 넣고 사용해 본다프로젝트 Resources

폴더에서 오른마우스클릭후 Add > Exist Files.. 실행해 저장된 sqlite 파일을

추가한다

신고
Posted by 우엉 여왕님!! ghostkyow
2011.05.23 10:15

iPhone(아이폰) DB 개발시 Sqlite3 용 클래스 FMDB

 

개발환경 : Mac OS X 10.6.3, Simulator - 3.1.3

 

FMDB 를 사용하기 위한 클래스를 다운받아야 하는데 기존 링크는 전부

깨져서 받을 수가 없었다검색해보니 누군가 구글코드 프로젝트에 올려놓은

곳이 있었다여기서 소스를 다운받는다. fmdb클래스는 예제를 실행한

내용으로 유용한 소스가 많이 들어가 있다참고 하기 바란다.

http://code.google.com/p/flycode/source/browse/trunk/fmdb#fmdb/src


받은 파일은 Classes 폴더에 넣어둔다. FMDB 에서 제일 중요한 파일은 FMDatabase,

FMResultSet 이다클래스 이름에서도 알수 있듯이 FMDatabase 는 데이터베이스

접속을 유지하고 SQL문장을 실행시켜준다그리고  FMResultSet  SELECT 쿼리를

수행한 결과를 담을 그릇이다이 객체에 데이터를 담은후에 소스에서는

하나하나 꺼내어 쓰게 된다.

 

간단한 사용법 예제를 보고 구현한 소스를 보는 것이 이해하기 편할 것 같다.

데이터베이스 수행의 기본은 CRUD 이다 CRUD 에 대한 간단한 예제들을

어떻게 수행하는지 볼텐데 데이터베이스 구현을 위한 함수는 크게 세가지로 보면

된다먼저 DB 접속을위한 FMDatabase 객체생성데이터를 읽어오는 executeQuery,

삭제업데이트입력을 수행하는 executeUpdate 가 그것이다.

 

위에 flycode 구글 프로젝트에서 fmdb.m 는 FMDB 를 어떻게 사용하는지에 대한

구체적인 예제 코드를 구현해놓았다.

처음 DB 를 열때는 NSAutoreleasePool 로 DB pool 을 생성한다그리고 FMDatabase

객체를 사용하여 DB 열고 Open 에 실패 했을때는 Pool release 하고 리턴한다.

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

FMDatabase* db = [FMDatabase databaseWithPath:@"success.sqlite"];

if (![db open]) {

           NSLog(@"Could not open db.");

           [pool release];

           return 0;

}

 

쿼리를 제대로 작성해서 실행을 했는지도 체크가 가능하다. FMDatabase 

hadError 함수로 제대로 수행되었는지에 대한 내용을 Bool 값으로 리턴하게

되는데 false 일 경우 lastErrorCode  함수로 그 내용을 알수 있다.

// create a bad statement, just to test the error code.

[db executeUpdate:@"blah blah blah"];

          

FMDBQuickCheck([db hadError]);

 

if ([db hadError]) {

           NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);

}

 

아래 예제는 테이블 생성과 여러 입력 쿼리 실행시 트랜잭션을 걸수 있는 내용이

포함 되어있다.

[db executeUpdate:@"CREATE TABLE quiz (no INTEGER PRIMARY KEY  AUTOINCREMENT  NOT

NULL , title VARCHAR, question VARCHAR, answer VARCHAR, level VARCHAR)"];

          

[db beginTransaction];

int count = 0;

while (count++ < 3) {

[db executeUpdate:@"insert into quiz (title, question, answer, level) values (?, ?, ?, ?)" ,

                      @"hi again'", // look!  I put in a ', and I'm not escaping it!

                      @"dadfasdfasdf",

                      @"sdfasfasdf",

                      @"1"];

}

[db commit];

 

다음은 데이터를 select 했을때 가져와서 어떻게 꺼내 사용할지에 대한 예제이다.

FMResultSet *rs = [db executeQuery:@"select rowid,* from test where a = ?", @"hi'"];

while ([rs next]) {

           // just print out what we've got in a number of formats.

           NSLog(@"%d %@ %@ %@ %@ %f %f",

                       [rs intForColumn:@"c"],

                       [rs stringForColumn:@"b"],

                       [rs stringForColumn:@"a"],

                       [rs stringForColumn:@"rowid"],

                       [rs dateForColumn:@"d"],

                       [rs doubleForColumn:@"d"],

                       [rs doubleForColumn:@"e"]);

          

          

           if (!([[rs columnNameForIndex:0] isEqualToString:@"rowid"] &&

                       [[rs columnNameForIndex:1] isEqualToString:@"a"])

           ) {

                     NSLog(@"WHOA THERE BUDDY, columnNameForIndex ISN'T WORKING!");

                                return 7;

           }

}

// close the result set.

// it'll also close when it's dealloc'd, but we're closing the database before

// the autorelease pool closes, so sqlite will complain about it.

[rs close];

 

이것은 테이블에 BLOB 형태로 이미지를 넣는 예제이다어플리케이션의 특정아이콘

이미지를 집어넣는것이다.

[db executeUpdate:@"create table blobTable (a text, b blob)"];

// let's read in an image from safari's app bundle.

NSData *safariCompass =

[NSData dataWithContentsOfFile:@"/Applications/Safari.app/Contents/Resources/compass.icns"];

if (safariCompass) {

           [db executeUpdate:@"insert into blobTable (a, b) values (?,?)", @"safari's compass",

safariCompass];

 

           rs = [db executeQuery:@"select b from blobTable where a = ?",

@"safari's compass"];

           if ([rs next]) {

                     safariCompass = [rs dataForColumn:@"b"];

                     [safariCompass writeToFile:@"/tmp/compass.icns" atomically:NO];

                    

                     // let's look at our fancy image that we just wrote out..

                     system("/usr/bin/open /tmp/compass.icns");

                               

                     // ye shall read the header for this function, or suffer the consequences.

                     safariCompass = [rs dataNoCopyForColumn:@"b"];

                     [safariCompass writeToFile:@"/tmp/compass_data_no_copy.icns"

 atomically:NO];

                                system("/usr/bin/open /tmp/compass_data_no_copy.icns");

                     }

           else {

                     NSLog(@"Could not select image.");

           }

           [rs close];

}

else {

           NSLog(@"Can't find compass image..");

}

 

이외에도 몇가지 더 있는데 비슷한 내용이라 생략한다.

fmdb.m 클래스를 참고 하게 되면 왠만한 DB 관련로직은 쉽게 구현하리라 생각된다.

트랜잭션처리와 DB 풀을 유지하며 작업을 할수 있다는점여러가지 에러체크 함수등은

FMDB 를 사용할 수밖에 없는 중요한 요소이다.

-출처-
http://mainia.tistory.com/546 

신고
Posted by 우엉 여왕님!! ghostkyow

티스토리 툴바