반응형
블로그 이미지
개발자로서 현장에서 일하면서 새로 접하는 기술들이나 알게된 정보 등을 정리하기 위한 블로그입니다. 운 좋게 미국에서 큰 회사들의 프로젝트에서 컬설턴트로 일하고 있어서 새로운 기술들을 접할 기회가 많이 있습니다. 미국의 IT 프로젝트에서 사용되는 툴들에 대해 많은 분들과 정보를 공유하고 싶습니다.
솔웅

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

코로나에서 SQLITE DB 이용하기

2011. 10. 17. 22:40 | Posted by 솔웅


반응형
오늘은 코로나에서 데이타베이스를 이용하는 방법을 보겠습니다.
안드로이드나 아이폰에서 SQLite라는 DB를 쓰니까 코로나에서도 당연히 SQLite 연동 기능을 제공 하겠죠?

기본적으로 코로나는 아이폰에 맞는 SQLite built-in을 실행합니다. 그리고이것을 안드로이드의 SQLite 버전으로 컴파일 하게 되는데요. 이것은 안드로이드 바이너리 파일(apk 파일)의 사이즈를 약 300k 정도 커지게 만듭니다.

SQLite 은 코로나 시뮬레이터에서도 제공 되므로 시뮬을 통한 테스트도 가능합니다.
(지금 Spin the Bottle 을 코로나 버전으로 옮기고 있는데요. text field, text box 같은 것들은 시뮬에서 제공이 안 되더라구요. 그래서 소스 고친 다음에 빌드하고 디바이스에 인스톨 해서 테스트 해야 하니 많이 번거롭습니다.)

아래 샘플을 보세요.

require "sqlite3"  -- SQLite 3 를 import 한다.
local db = sqlite3.open_memory() -- 메모리에 디비를 만든다.
 
db:exec[[  -- 테이블을 생성한다.
  CREATE TABLE test (id INTEGER PRIMARY KEY, content);
  INSERT INTO test VALUES (NULL, 'Hello World');
  INSERT INTO test VALUES (NULL, 'Hello Lua');
  INSERT INTO test VALUES (NULL, 'Hello Sqlite3')
]]
 
print( "version " .. sqlite3.version() ) -- SQLite의 버전을 터미널에 프린트한다.
 
for row in db:nrows("SELECT * FROM test") do  -- 모든 데이터를 화면에 출력한다.
  local t = display.newText(row.content, 20, 30 * row.id, null, 16)
  t:setTextColor(255,0,255)
end

소스 설명은 옆에 주석으로달았습니다.

두번째 줄에서 보시듯이 이 소스는  디비를 메모리에서 만들도록 했습니다.
그래서 재 실행하면 디비가 없어지고 다시 새로 만들기 때문에 항상 저 위에 3개의 문자만 나옵니다.

아래 샘플 코드는 메모리가 아니라 디바이스에 디비를 만듭니다.

--Include sqlite
require "sqlite3"
--Open data.db.  If the file doesn't exist it will be created
local path = system.pathForFile("data.db", system.DocumentsDirectory)
db = sqlite3.open( path )  
 
--Handle the applicationExit event to close the db
local function onSystemEvent( event )
        if( event.type == "applicationExit" ) then             
            db:close()
        end
end
 
 
--Setup the table if it doesn't exist
local tablesetup = [[CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, content, content2);]]
print(tablesetup)
db:exec( tablesetup )
 
--Add rows with a auto index in 'id'. You don't need to specify a set of values because we're populating all of them
local testvalue = {}
testvalue[1] = 'Hello'
testvalue[2] = 'World'
testvalue[3] = 'Lua'
local tablefill =[[INSERT INTO test VALUES (NULL, ']]..testvalue[1]..[[',']]..testvalue[2]..[['); ]]
local tablefill2 =[[INSERT INTO test VALUES (NULL, ']]..testvalue[2]..[[',']]..testvalue[1]..[['); ]]
local tablefill3 =[[INSERT INTO test VALUES (NULL, ']]..testvalue[1]..[[',']]..testvalue[3]..[['); ]]
db:exec( tablefill )
db:exec( tablefill2 )
db:exec( tablefill3 )
 
--print the sqlite version to the terminal
print( "version " .. sqlite3.version() )
 
--print all the table contents
for row in db:nrows("SELECT * FROM test") do
  local text = row.content.." "..row.content2
  local t = display.newText(text, 20, 30 * row.id, null, 16)
  t:setTextColor(255,0,255)
end
 
--setup the system listener to catch applicationExit
Runtime:addEventListener( "system", onSystemEvent )

이렇게 디바이스에 디비를 만들면 맨 마지막 줄처럼 앱이 끝날 때 디비를 close 시키기 위해 리스너를 달고 onSystemEvent( event ) 함수처럼 db를 close 시킵니다.


코로나에서는 이 SQLite 관련해서 자세하게 사용법을 알려주지 않더라구요.
그리고 SQLite의 여러 신택스들도 사용하면서 잘 실행이 안되는 것 같구요.

그래서 저는 데이터를 다룰 때 select * 을 해서 모든 데이터를 가져오고 이 데이터들을 코로나의 배열(테이블)에 넣어서 사용했습니다.

function fetchAll()
    local r = {}
    local i = 1;
   
    for row in db:nrows("SELECT * FROM table") do
        --print("id = " .. row.id .. " content = " .. row.content );
        local id = row.id;
        local contnt = row.content;

        r[i] = {}
        r[i].id = id
        r[i].content = contnt
        i = i+1;
    end

return r; -- 모든 데이터와 count(*) 값을 리턴한다.   
end

이렇게 데이터를 r이라는 테이블(배열) 에 담아서 리턴하는 함수 하나 만들어 놓고 사용합니다.
코로나는 간편하게 테이블(배열)을 control 할 수 있어서 이게 더 편하더라구요.

물론 SQLite를 통해서 제공하는 기능을 잘 알면 그걸 쓰면 더 편할 수도 있겠지만요.

신택스는 제가 보니까 아래 처럼 두가지가 있더라구요.
    db:exec[[
        INSERT INTO table VALUES (NULL, 'contents contents contents');
    ]]
이렇게 직접 쿼리를 실행하는 것 하구 아래처럼 변수에 쿼리를 담아서 실행하는 것도 있습니다.

    local insertRule =[[INSERT INTO table VALUES (NULL, ']]..contents..[[');']]
    db:exec( insertRule )

    local updateRule =[[update table SET content = ']] ..content .. [['WHERE id = ']].. id .. [[';']]
    db:exec( updateRule )

자 이렇게 DB control에 필요한 connect, select,insert,update,delete,drop, db close 기능에 대해서 배웠구요.
이 데이터들을 코로나 배열(테이블)에 넣어서 사용하는 법도 배웠습니다.

다음 시간에는 file control에 대해서 살펴 볼께요.

반응형


반응형
어제에 이어서 계속 하겠습니다.

어제까지 한 소스는

--import the table view library
local tableView = require("tableView")
display.setStatusBar( display.HiddenStatusBar )

--local background = display.newImage("hutbg.png")

function listButtonRelease( event )
    self = event.target
    local id = self.id
    print(self.id)
end

local data = {
"감자떡",
"생선구이",
"된장찌개",
"막걸리",
"소주",
"동동주"
}

local myList = tableView.newList{
    data = data,
    default="listItemBg.png",
    onRelease=listButtonRelease,
}

여기까지 였습니다.

오늘은 여기에 이미지를 넣어 보겠습니다.
아래 이미지들을 받으세요.

제가 먹고 싶은 것 들인가 봐요.


이 그림들을 다 받으셨으면 이제 코딩을 시작하겠습니다.



우선 data 부터 바꾸겠습니다.
local data = {감자떡,생선구이,된장찌개,막걸리,소주,동동주}

이것을
local data = {}

--setup each row as a new table, then add title, subtitle, and image
data[1] = {}
data[1].title = "감자떡"
data[1].subtitle = "100% 감자로 만든 강원도 특산품"
data[1].image = "potato.png"

data[2] = {}
data[2].title = "생선구이"
data[2].subtitle = "맛있는 고갈비"
data[2].image = "grillfish.png"

data[3] = {}
data[3].title = "된장찌개"
data[3].subtitle = "구수한 된장찌개"
data[3].image = "soy.png"

data[4] = {}
data[4].title = "막걸리"
data[4].subtitle = "몸에 좋은 막걸리"
data[4].image = "mak.png"

data[5] = {}
data[5].title = "소주"
data[5].subtitle = "짜르르 몸에 퍼지는 소주"
data[5].image = "soju.png"

data[6] = {}
data[6].title = "동동주"
data[6].subtitle = "고향의 맛 동동주"
data[6].image = "dong.png"

이렇게 바꿔주세요.

이렇게 하고 실행 하면 아래와 같이 에러가 납니다.

잘 보시면 아시겠지만 첫번째 줄 디폴트 이미지를 뿌려주고나서 데이터를 뿌릴때 에러가 납니다.
데이터가 여러개라서 그런데요.
이렇게 한 row에 여러 텍스트라든지 혹은 텍스트 + 이미지를 표시하시려면 callback을 사용합니다.
그리고 이 callback에 있는 object들은 하나의 group으로 관리하게 됩니다.
그럼 myList를 아래와 같이 고쳐 보세요.

local myList = tableView.newList{
    data = data,
    default="listItemBg.png",
    onRelease=listButtonRelease,
    callback = function( row )
        local g = display.newGroup()
        return g  
    end
}

이제 에러는 안 나죠?
대신 callback 안에 어떤걸 표시할지 알려주지 않아서 그냥 row 배경이미지만 6개 나옵니다.

callback을 아래와 같이 채워주세요.
    callback = function( row )
        local g = display.newGroup()
            local img = display.newImage(row.image)
            g:insert(img)
            img.x = math.floor(img.width*0.5 + 6)
            img.y = math.floor(img.height*0.5)

            local title =  display.newText( row.title, 0, 0, native.systemFontBold, 14 )
            title:setTextColor(255, 255, 255)
            g:insert(title)
            title.x = title.width*0.5 + img.width + 6
            title.y = 30

            local subtitle =  display.newText( row.subtitle, 0, 0, native.systemFont, 12 )
            subtitle:setTextColor(255,255,255)
            g:insert(subtitle)
            subtitle.x = subtitle.width*0.5 + img.width + 6
            subtitle.y = title.y + title.height + 6
        return g  
    end

우선 이미지를 표시하고 group에 insert시키고 x,y 좌표를 설정해 줍니다.
title과 subtitle도 마찬가지로 합니다.

자 이제 제대로 ListView(TableView) 가 나오죠?

여기다가 배경 화면을 은은하게 깔겠습니다.

local background = display.newImage("hutbg.png")
background.alpha = 0.4

이렇게 간단하게 이미지 하나 불러오고 투명도를 약간 줬습니다.



이번 TableView 모든 소스와 이미지 파일 입니다.

받으셔서 참고 하세요.

그럼 더 신나는 코딩을 위해 다음 시간에도 새로운 걸 배울께요....
반응형


반응형
원래 오늘은 SQLite를 할 까 했는데요.
이건 나중에 하고 우선 List View (Table View)를 할께요.
제가 했던 안드로이드에서는 이걸 List View라고 했는데 아이폰쪽에서는 Table View라고 하나봐요.

우선 List View에서는 아래와 같은 파라미터들이 사용 됩니다.
data. 값들을 가지고 있는 테이블. 각 row별로 표시될 값들
default.  row의 배경 화면이 될 이미지. touch 영역 설정 가능
backgroundColor. R,G,B 값으로 배경 색을 정할 수 있음
callback. 각 row에 데이터를 어떻게 display할까를 정의하는 함수. 테이블의 각 값들은 callback함수의 할당 된 'item' 인자와 관련되서 사용됨.
over. 터치 시 보일 이미지
onRelease(optional). row가 tap된이후에 일어날 action을 정의한 함수의 이름
top. list의 위쪽 영역. 리스트가 시작하고 다시 돌아오는 포지션
bottom. 리스트의 아래쪽 영역. 스크롤이 초과해서 진행 되면 이쪽으로 돌아온다.
cat. 각 아이템의 카테고리 값을 저장하기 위해 사용되는 테이블 키 이름.
order. cat의 option 항목. 임의의 정렬을 지정할 수 있다.

아래와 같은 메소드들이 있습니다.

* myList:addScrollBar() and myList:removeScrollBar()
스크린에 스크롤바를 넣거나 없앤다.

* myList:addOnTop(object, xVal, yVal)
리스트에 처음에 object를 추가한다. (search bar나 text 같은)

* myList:addOnBottom(object, xVal, yVal)
리스트의 마지막에 object를 추가한다.

* myList:scrollTo(yVal, timeVal)
리스트를 다이나믹하게 움직이도록 한다.

* myList:cleanUp()
리스트를 없애고 메모리를 풀어준다. 그리고 모든 이벤트 리스너들을 정지시킨다.

그럼 이제 실제로 table view (List View)를 사용해 보겠습니다.
우선 tableView.lua 파일이 있어야 됩니다.
아래 파일을 다운 받으세요.

그리고 이 파일이 있는 폴더에 main.lua 파일을 만드세요.
우선 아래와 같이 tableView.lua 파일을 사용하겠다고 선언합니다.

--import the table view library
local tableView = require("tableView")

일단 여기서 편의상 아이폰의 statusbar를 없앨께요.
display.setStatusBar( display.HiddenStatusBar )

아주 간단한 테이블을 만들어 보겠습니다.
local data = {
"감자떡",
"생선구이",
"된장찌개",
"막걸리",
"소주",
"동동주"
}

이 데이타들을 아래와 같이 해 보세요.
그리고 tableView.lua에 있는 List View 메소드를 선언합니다.
local myList = tableView.newList{data=data}

실행해 보면 이렇게 나옵니다.
글자를 누르고 드래그 하듯이 움직이면 터미널처럼 touch: began moved, ended 가 나옵니다.
이걸 보면 touch 리스너가 달려있고 began,moved,ended 이벤트시 어떤 동작을 지정할 수 있다는 걸 알 수 있겠죠?
그리고 드래그를 하지 않고 그냥 tap 만 하면 아래와 같이 나옵니다.

터미널에 보면 onRelease 필드가 nil 이라고 하면서 에러메세지가 나오죠?

그럼 이 newList안에 아래와 같이 추가 하겠습니다.
onRelease=listButtonRelease,
그리고 그 위쪽에 listButtonRelease 함수를 아래와 같이 만들어 주세요.
function listButtonRelease( event )
    self = event.target
    local id = self.id
    print(self.id)
end

이렇게 하면 각 row를 클릭하면 에러가 나지 않고 그 id가 터미널에 출력 됩니다.
여기까지 하면 가장 간단한 Table View(List View)가 완성 된 겁니다.

좀 더 그럴듯 하게 리스트 뷰를 만들어 볼까요?
아래 이미지를 다운 받으세요.

그리고 myList 에 default="listItemBg.png", 를 추가해 보세요.
local myList = tableView.newList{
    data = data,
    default="listItemBg.png",
    onRelease=listButtonRelease,
}

그럼 이와 같이 그럴듯한 ListView (TableView) 가 됩니다.

자 오늘은 코로나 SDK에서 ListView(TableView) 표시하기 가장 기초적인 부분을 다뤄봤습니다.

다음시간에는 이 글 첫번째에서 소개했던 여러 파라미터들하고 메소드들을 사용해서 좀 더 다이나믹한 효과를 내는 방법을 알아보겠습니다.


반응형