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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

Storyboard: Scene Purging vs. Removal

2012. 8. 2. 11:01 | Posted by 솔웅


반응형

Storyboard: Scene Purging vs. Removal


Posted on . Written by


코로나 SDK 의 storyboard API에서 혼동되는 부분 중 하나가 scene을 purging 하고 removal 하는 겁니다. purging과 removing의 차이점은 무엇일까요? 그리고 scene을 purge 한다는게 무슨 의미죠? 이런것들이 우리가 자주 받는 질문들 중 일 부분입니다.


오늘은 이런 의문점을 깨끗하게 날려드리기 위해 purging과 removal이 되면 scene들 뒷편에선 어떤 일들이 일어나는지에 대한 high-level overview를 알려드리겠습니다. 그리고 몇가지 예제들도 보여드릴거구요.


Memory Consumption


Corona display object가 생성 됐을 때 이 객체는 texture 메모리 (graphics)와 Lua 메모리 (테이블과 변수 같은 데이터)를 차지하게 됩니다. scene 모듈 같은 모듈이 로딩 될 때 이것은 메모리에 저장돼 있는 단순한 테이블입니다. 그래서 좀 더 빠르게 메모리에서 로딩 할 수 가 있습니다. 그렇지만 한번에 메모리에 너무 많은 것들이 있으면 퍼포먼스에 지장을 줄 수 밖에 없겠죠. 이것 때문에 저희는 개발자들이 메모리에 무엇을 남길지 그리고 어떤 것들을 unload 시키거나 freed 시킬지의 여부에 대해서 전적으로 콘트롤 할 수 있도록 하자고 정했습니다. 


이러한 배경을 염두에 두신후 아래 스토리보드 scene들에 서 purging과 removing이 무엇인제에 대한 기본 개요를 보시기 바랍니다.


Purging은 scene에서 display object들만 remove 시키는 겁니다. 그렇게 되면 texture memory는 freeing 되겠죠. 그리고 이 scene이 external module에 의해 represent 되면 이 모듈은 계속 메모리에 남아있는 상태가 될 겁니다. 여러분이 만든 custom 변수들이 모두 메모리에 있게 된다는 겁니다.


scene을 Removing 한다는 것은 display 객체든 루아 객체든 모두 remove 한다는 의미 입니다. 그 결과로 texture 메모리 뿐만이 아니라 루아 메모리도 모두 freed 되게 됩니다.



So why purge at all?


만약에 유저가 나갔다가 다시 돌아올 것으로 예상되는 scene이 있다면 그런데 그 scene이 아주 많은 texture 메모리를 가지고 있다면 이 scene은 purge 시키는 것이 좋을 겁니다. 그러면 다른 scene이 로드될 떄 퍼포먼스에 지장을 주지 않겠죠. (그 모듈-scene-은 계속 메모리에 남아 있는 겁니다.)


예를 들어 action arcade 게임을 만든다고 했을 때, 그 게임은 아주 많은 physics와 아주 빠르게 움직이는 수 많은 객체들을 사용하게 될 겁니다. 두말 할 것도 없이 그 게임 scene은 아주 많은 texture 메모리를 필요로 하게 되죠.


이 game screen 구석에는 pause 버튼이있습니다. 그 버튼을 누르면 pausegame 이 로드 되죠. 유저기 이 scene을 자주 들락거려야 한다면 이 scene을 purge 하는게 훨씬 나을 겁니다. 유저는 이 scene에 다시 돌아올 가능성이 많을 겁니다. 그러니까 다른 scene의 퍼포먼스에  부담을 덜기 위해서 pause를 사용해서 texture 메모리를 절약하고 다시 돌아올 경우에 빨리 로드되게 하기 위해서 루아 객체는 메모리에 그대로 두는 pause가 유용하게 이용될 수 있을 겁니다


Functions for Purging


scene purging을 handle 하는 스토리보드의 function에는 두가지가 있습니다.



첫번째 함수는 single argument를 받습니다. sceneName을 받게 되죠. purge 할 특정 scene을 지칭하는 겁니다. purged 될 scene이 external module과 correspond 된다면 이것은 module name이 되겠죠. (.lua 확장자를 뺀 나머지 부분)

이렇게 purging이 되면 해당 scene의 display object들은 destroy 될 겁니다. 더이상 display object들이 화면에 display 될 필요가 없을 떄 사용하는 것이죠. 이 작업을 하기에 가장 알맞는 이벤트는 didExitScene 입니다.

scene이 완전히 screen에서 사라졌을 떄 그 scene을 purge 하는 예제가 아래에 있습니다.


-- scene1.lua
local storyboard = require "storyboard"
local scene = storyboard.newScene()

-- createScene event simply creates a background image
function scene:createScene( event )
    local bg = display.newImage( self.view, "background.png" )
end
scene:addEventListener( "createScene" )

function scene:didExitScene( event )
    storyboard.purgeScene( "scene1" )
end
scene:addEventListener( "didExitScene" )

return scene


어떤 scene에서 menu.lua로 전환한다고 칩시다. 이 경우 menu.lua로 되돌아 오는 다른 scene들은 여러경우가 있습니다. 이럴 경우 그 이전 scene이 어떤건지 확실히 모를 때 어떻게 이전 scene을 pause 하는지에 대한 예제가 아래에 있습니다.


-- menu.lua
local storyboard = require "storyboard"
local scene = storyboard.newScene()

-- createScene event simply creates a background image
function scene:createScene( event )
    local bg = display.newImage( self.view, "background.png" )
end
scene:addEventListener( "createScene" )

function scene:enterScene( event )
    local prior_scene = storyboard.getPrevious()
    storyboard.purgeScene( prior_scene )
end
scene:addEventListener( "enterScene" )

return scene


여러분들은 현재 작동중인 scene을 제외한 모든 scene들을 purge 시키기 위해 storyboard.purgeAll()를 사용하실 수 있습니다.  scene이 purge 될 때는 destroyScene 이벤트가 dispatch 될 겁니다. 그 이벤트를 이용해서 Runtime listener를 remove 한다던가 하는 last minute action들을 처리하실 수 있습니다.


Functions for Removing


scene을 removal 하는 것을 처리하기 위한 스토리 보드 함수에는 두가지가 있습니다. 아래 두 함수중에 하나가 call 되면 해당 scene은 우선 purge 하고 그 다음에 remove 될 겁니다.


첫번째 함수는 single argument를 받습니다. sceneName 인데요 remove 할 scene을 말하는 것이죠. 이 remove 될 scene이 external module 이면 그 모듈 이름이 되겠죠. (.lua 확장자를 제외한 부분)

remove 되기 전에 해당 scene이 purge 되면 destroyScene 이벤트가 해당 scene에 dispatch 될 겁니다.


Automatic Purging


iOS에서는 디폴트로 OS가 Low memory warning을 issue 하면 least-recently-used scene이 자동적으로 purge 됩니다. 이 purge가 자동적으로 이뤄지도록 하고 싶지 않으면 storyboard.disableAutoPurge 프로퍼티를 사용하시면 됩니다.


storyboard.disableAutoPurge = true


디폴트 값은 false 입니다. 그러니까 여러분이 true로 세팅하시면 더이상 필요하지 않거나 여러분 앱의 texture memory 소비를 많이 잡아 먹는 scene 이 있으면 여러분이 직접 pause 해 주셔야 합니다. 이 자동 pause 기능은 안드로이드 디바이스에서는 작동되지 않습니다.


만약 매뉴얼 purging 도 원하지 않고 automatic scene purging 도 원하지 않으면 storyboard.purgeOnSceneChange 프로퍼티를 true로 해 놓으세요. 그러면 scene이 바뀔 때마다 전환될 scene을 제외한 모든 scene들이 purge 될 겁니다.


좀 더 자세한 내용은 storyboard.* API documentation을 보세요.


반응형


반응형

Corona: WebViews on Android!

Posted on . Written by


월요일입니다. 업데이트 날이죠.


지난주 저는 Mountain Lion 과 관련된 여러 어려움들을 얘기 했었습니다. Mountain Lion은 Mac OS 10.8에 대한 코드 네임이죠. 여러곳에서 report 를 해준 분들에게 감사드립니다. 저희는 이 부분과 관련해서 여러 문제점들을 해결해 나가고 있습니다. 최근의 daily build (868 버전 이후) 들은 10.8 에서 안정적으로 돌아 갑니다.


이렇게 Mountain Lion과 관련해서 작업을 하고 있는 사이에도 우리는 feature cycle 작업을 계속 해 나가고 있습니다. 이 cycle의 우선 순위에 있던 것 중 하나가 안드로이드의 native display object 관련 된 것 입니다. 예를 들어 textfield 처럼 안드로이드 native display에서는 alpha가 지원되지 않았었습니다. 지금은 그것을 지원하도록 만들었습니다.

안드로이드의 WebViews는 아주 중요한 이슈였습니다. 안드로이드에서는 그동안 웹 팝업을 지원했었죠. 하지만 이 팝업만으론 부족했습니다. 이제 그것을 일반 display object 처럼 사용가능합니다. 최금의 builds 에서 안드로이드에서 native display 로서 Webview를 제대로 사용하실 수 있습니다. 지금까지 iOS에서 사용했던 것 처럼요. 이 의미는 여러분은 이제 OpenGL/HTML5 hybrid 앱을 iOS와 안드로이드 모두에서 사용하실 수 있다는 겁니다.


이 웹뷰 기능과 관련해서는 저희들이 특별히 중점을 두고 관리를 했고 그렇게 해서 안드로이드의 웹뷰와 iOS의 웹뷰의 일관성을 유지하는데 많은 노력을 기울였습니다.


이 일들을 하면서 여러 Android 버그들때문에 고생을 했고 또 그것들을 극복해 나갔습니다. 그 버그 중 하나는 HW-accelerated web views와 관련된 아주 치명적인 겁니다. 여러분이 웹뷰에 alpha를 세팅하면 안드로이드에서는 제대로 작동을 하지 않았었습니다. 이것을 제대로 작동시키기 위해서 여러 안드로이드 버그들을 컨트롤 해야만 했었죠. 이제는 HW-acceleration 과 함께 alpha를 콘트롤 할 수 있습니다.


다음에는 뭘까요?


이번주내에 오랫동안 저희의 발목을 잡아왔던 안드로이드의 Mapview와 관련해서 계획이 있습니다. 또한 Box2D library를 최신버전으로 업데이트 할 거구요 그렇게 함으로서 새로 선보이는 최근의 모든 joint type들을 지원하게 될 겁니다.

다음주에는 우리가 Mountain Lion 과 관련해서 일하면서 배운 것들에 대해 얘기를 해 드리겠습니다. 저희는 항상 안드로이드나 iOS 나 그 OS가 업그레이드 됨에 따라 여러분들에게 문제 없이 기능을 사용할 수 있도록 하기 위해 열심히 노력하고 있습니다.


==================================================================


이번주가 지나면 안드로이드에서도 Webview와 Mapview 모두 사용 가능해 지겠군요.

지금은 Corona SDK 프로젝트를 하고 있지 않아서 손 놓은지 오래 됐는데...

갑자기 이 기능을 이용해서 앱을 하나 만들어보고 싶네요.

마침 지금 하는 프로젝트가 Web App 작업이나까 같이 접목해서 여러 시도를 해 볼 수 있을 것 같은데요.

jQuery Mobile과 같이 작업을 할 수도있겠구요.


항상 열정을 가지고 발전하는 Corona SDK 화이팅 입니다.


반응형


반응형

7 Great Tools to Build a Mobile App


HTML5를 잘 알고 있던지 하나도 모르던지 상관없이 여러분의 모바일 앱 개발을 도와줄 툴들이 있습니다.


올 초에 올린 아티클에서 얘기했듯이 스마트폰이나 태블렛 유저들중 49%는 local 정보를 찾기 위해 앱을 사용합니다. 그러니까 사업에 도움이 된다면 앱을 만들려고 하는 사람들이 많이 있겠죠. 단지 사람들이 좋아하는게 아니라 사업에 도움이 되는것 말이죠. 잘 디자인 된 비지니스 앱은 고객들에게 잘 홍보를 할 테고 그리고 앱을 통해 거래도 할 수 있겠죠.

앱을 만드는 건 간단한 일은 아닙니다. 돈도 많이 들구요. 그런데 이제 그런 시대는 갔습니다. 여러분들이 모바일 앱을 빨리 그리고 저렴하게 만들 수 있도록 도와주는 개발 플랫폼들이 많이 나왔습니다. 여기 7가지를 소개합니다. 다른것들도 아신다구요? 댓글에 달아 주세요.


Tiggzi



Tiggzi는 cloud-based HTML5 앱 빌더 입니다. iOS,ANdroid 그리고 모바일 웹앱 같은 거를 개발할 수 있죠. 드래그 앤 드롭 형식을 만들 수 있습니다. Tiggzi는 앱을 어떻게 생성하는지 interactive online tutorial을 통해 정보를 제공합니다. 또한 고객 서비스도 하고 있구요, 추가적인 리소스들과 관련해서 블로그들도 있습니다. non-developer 들에게는 아주 희소식이죠. Tiggzi Platform으로 개발해서 여러 store들에 앱을 업로드 하세요.

가격 : Tiggzi로 빌드하는 첫번째 앱은 무료입니다. 그 다음부터는 한달에 15불을 내면 3개의 프로젝트를 만들 수 있고 한달에 50불을 내면 무제한으로 만들 수 있습니다.





Buzztouch



새로운 개발자들을 위한 유저 코뮤니티가 아주 강력합니다. Buzztouch 플랫폼은 유저가 선택하면 independent로 있을 수도 있습니다. 웹 기반 소프트웨어는 Buzztouch를 이용해서 앱을 host 할 수 있습니다. 그들의 사이트를 사용할 수도 있고 Dropbox 같은 클라우드 스토리지 서비스 등을 사용할 수도 있습니다. 개발자들은 이 플랫폼을 이용해서 간단한것에서부터 복잡한 앱을 만들 수 있는데요. 아마 objective C나 Java 지식이 있으면 더 빨리 배울 수 있을 거예요.


가격: 얼마나 많은 앱을 빌드하고 필요한 기능이 무엇인지에 따라 무료에서부터 월 $9.99, $19.99, or $29.99 의 상품들이 있습니다. Buzztouch는 앱스토어나 마켓에 앱을 submit 하지는 않습니다. 그 과정은 여러분이 스스로 하셔야 합니다.



Titanium by Appcelerator


자바스크립트나 HTML5에 대해 아주 기초적인 지식만 가지고 있는 개발자도 Appcelerator의 Titanium을 사용할 수 있습니다. 이 툴은 native iOS, 안드로이드 앱 그리고 HTML5 모바일 웹 앱을 만드는데 도움을 줍니다. 이 플랫폼은 다양한 소스로부터 데이터, 콘텐트, 서비스등을 쉽게 통합할 수 있도록 해 줍니다. Appcelerator Cloud Service는 social, location, communication 그리고 content feature 등을 제공합니다. Titanium Studio는 앱 스토어에 submit 하도록 어플리케이션 패키지를 만드는 과정을 step by step으로 알려주는 wizard를 제공합니다. 


가격: www.appcelerator.com에서 무료 버전의 Titanium 을 다운 받으 실 수 있습니다. 추가적인 기능이나 support는 다양한 premium package로 제공하고 있습니다.




EachScape


EachScape는 초보자도 쉽게 iOS, Android, HTML5 앱을 빌드하고 매니지 할 수 있도록 도와주는 드래그 앤 드롭 플랫폼입니다. EachScape client는 NBC,CBS E!, Nivea와 켈로그 같은 top company들이 포함돼 있습니다. 이 플랫폼은 수 많은 3rd party 제품들을 활용할 수 있으며 비디오, overlay, social sharing, augmented reality, location, 광고, analytics 등등을 include 할 수 있습니다. Full-service 받으면 회사차원에서 앱을 빌드하는 것을 도와 줍니다. EachScape는 앱스토어에 올리거나 client에게 resell (영업) 하는 것 등을 도와 줄 겁니다.


가격 : Enterprise version은 월 2500 불서부터 시작됩니다. 보다 싼 lite 버전도 조만간 출시 될 겁니다.



TheAppBuilder


누구든이 이 툴을 이용하면 iOS, 안드로이드, 윈도우즈 폰 앱이나 모바일 웹 앱을 빨리 만들 수 있습니다. TheAppBuilder는 어떤 종류의 business인지 또는 어떤 종류의 organization인지에 따라 거기에 맞는 다양한 종류의 앱에 대한 탬플릿을 제공합니다. 여러분은 그냥 여러분이 넣고 싶은 contents, integrate social media feeds 등을 클릭하시면 됩니다. 몇분 후에는 웹앱을 publish 하실 수 있습니다. 앱스토어에 publish 하시려면 TheAppBuilder가 앱스토어에 올릴 수 있는 파일을 만들어 줄 겁니다.


가격 : HTML 웹 앱을 만들고 업데이트 하는 것은 공짜입니다. 앱스토어에 올리시려면 code files에 대해 $499불을 내셔야 합니다. 앱스토어에 있는 앱을 업데이트 하시려면 한달에 29불을 지불하셔야 합니다.



AppExpress


프로그래밍 경력이 없어도 AppExpress 를 이용하시면 앱을 만들 수 있습니다. 모듈을 선택하시면 여러분이 customize 해서 몇분안에 앱을 만들어 publish 할 수 있습니다. Small business를 위해 만들어 졌습니다. AppExpress는 여러분의 고객이 schedule appointment, 인보이스 지불, 거래하기 등등을 할 수 있도록 하는 앱을 만들 수 있게 해 줍니다. 리스트 내의 특정 고객이나 모든 고객에 메세지 보내기 등등의 기능도 있습니다. 유저나 벤더들도 파일등을 첨부해서 메세지를 보낼 수 있습니다. 예를 들어 유저는 사진을 첨부해서 여기에 설명을 달거나 그림을 그릴 수 있습니다.


가격: AppExpress.com에서 처음에 셋업 하는 비용 $199 하고 나면 월 $75 씩 냅니다.

Spaweek, User Friendly Media 같은 reseller를 통해서 셋업 하셔도 됩니다.



Corona SDK



Corona Lab's의 Corona SDK는 개발자들이 high-quality 앱을 만들도록 도와 줍니다. 그리고 iOS, 안드로이드, Kindle Fire, Nook 디바이스에서  사용할 수 있는 앱, 게임, eBook 들을 만들 수 있습니다. 코로나 SDK는 Lua 언어를 사용합니다. 배우기 쉽고 interactive 한 graphical content를 만드는 데 아주 좋은 언어죠. 150,000 명의 개발자가 전세계적으로 있고 활발한 커뮤니티 활동을 하고 있습니다. 코로나 SDK는 또한 회사 싸이트에 in-depth tutorial을 매주 post 하고 있습니다.


가격 : 무료 trial 버전이 있습니다. 가격을 지불하면 앱스토어 (마켓)에 publish 할 수 있습니다. 코로나 SDK는 연회비를 받고 있습니다. 이 연회비를 지불하면 여러분은 앱을 빌드하고 publish 할 수 있습니다. 연회비 $199 불을 내면 앱스토어나 구글 플레이 스토어 중 한군데에 업로드 하는 권한을 받고 $349 를 지불하면 두곳 모두에 업로드 할 수 있습니다.



반응형


반응형
Posted on

. Written by



수요일 입니다. FAQ 시간이죠. 아래 5가지 자주 나오는 질문을 모아봤습니다.


1. What is the proper way to use Facebook.showDialog?


showDialog API는 어떤 것이 sent/posted 되는지에 대해 유저가 메세지를 넣을 수 있도록 dialog screen을 불러 옵니다. 이 API는 action 파라미터를 필요로 하죠. 이 파라미터는 feed나 apprequests 중 하나가 될 수 있습니다. 만약 apprequests가 사용된다면 message 파라미터가 있어야 됩니다. 아니면 fail 되죠. 아래 예제가 있습니다.


facebook.showDialog( "apprequests", {
    message = "Example message."
} )


2. The Single Sign On (SSO) for iOS is not working. What can cause this?


build.settings 파일 안에 있는 UIApplicationExitsOnSuspend key가 false 로 세팅돼 있어야 합니다. false 가 디폴트 입니다. 그런데 어떤 유저들은 이 key를 include 해서 true로 세팅하기도 합니다. 그렇게 되면 SSO fail이 일어나는 거죠.

그리고 build.settings 파일 안에 Facebook App ID 도 있어야 합니다. 어떻게 하는지에 대한 것은 Jonathan’s blog post 를 봐 주세요.


3. My users are having to re-logon every few hours into Facebook from my app. Is there anything I can do to extend the time?


예 페이스북 앱 set-up 페이지에서 “Remove offline_access permission”를 enable 하도록 만들 수 있습니다. https://developers.facebook.com/apps/ 로 가셔서 페이지 우상단에 있는 “Edit App” 버튼을 클릭하세요. 이제 Setting 메뉴 아래에 있는 Advanced 를 클릭하세요. 아래 화면을 보실 수 있을 겁니다. “Remove offline_access permission” 이 enabled 돼 있는지 확인하세요. 그러면 logon token을 60일동안 연장해 줄 겁니다.





4. How can I tell when the Facebook token will expire?


Corona Facebook API listener는 event.phase == “login” 일 때 event.expiration 안의 token expiration time을 return 합니다. 아래 코드대로 하면 expire 될 때까지 며칠이 남았는지 표시해 줄 겁니다.


print( ">>> Token expires in " ..
    os.difftime( event.expiration, os.time() )/86400 .." days" )


5. I’m getting a log-on error when I enable Facebook’s Single Sign On (SSO) for Android. How do I generate the “Android Key Hash?”


만약 안드로이드 앱에서 Single sign on (SSO)이 enable 돼 있다면 이것은 fail 될 겁니다. 왜냐하면 맞는 hash key를 supply 하지 않았기 때문입니다. 이러면 아마 logon 하려고 할 때 ADB logcat에 다음과 같은 메세지가 뜰 겁니다. 

“invalid_key:Android key mismatch. Your key “PGv8R2vDQ/w6hexLxdefWKxcYLS” does not match the allowed keys specified in your application settings. Check your application settings at http://www.facebook. … “


당신의 key가 뭐가 되야 되는지는 ADB를 이용해서 알아낼 수 있습니다. 더 간단하게 하려면 그냥 logcat terminal window에 있는 key string을 복사해서 여러분의 안드로이드 key hash를 필요로하는 페이스북 앱 페이지에 붙여 넣으세요.  그냥 123을 입력하고 앱을 돌리면 logcat이 맞는 hash key를 output 해 줄겁니다.

https://developers.facebook.com/apps/ 로 가셔서 페이지 우상단에 있는 “Edit App” button을 클릭하세요.  그러면 Android SSO 세팅과 관련 된 Basic 페이지로 가게 될 겁니다.






SSO를 지원하지 않는 디바이스에 있는 옛날 페이스북 앱이 있다면 log-in call은 페이스북 앱을 call 하는 대신에 로컬 웹 팝업이 뜰 겁니다. 이 경우에는 hash key가 사용되지 않습니다.


만약 유저가 SSO를 지원하는 것으로 그들의 페이스북 앱을 업그레이드 했다면 그 유저는 여러분 앱에서 로그아웃을 해야 합니다. 안 그러면 token 은 incorrect 되고 request/dialog API 은 fail 되겠죠. 왜냐하면 invalid token 때문입니다. (코로나는 그 token을 바로 직전의 성공한 로그인에서 저장하고 이것을 모든 API call 에 사용합니다.)


여기까지가 오늘의 내용입니다. 즐거우셨길 바라고 뭔가 모르는 부분을 알게 되는 기회가 됐기를 바랍니다.



반응형


반응형

Detecting Object and Screen Taps

Posted on

. Written by



이전에 touch 이벤트를 이용해서 Corona SDK에서 어떻게 detect touches를 하는지 보여드렸었습니다. 아실 지 모르겠지만 quick touch나 quick tap을 감지하는 훨씬 간단한 이벤트가 있습니다. 이 기능은 다양한 시나리오나 게임 또는 테스트 등에 아주 유용하게 사용될 수 있습니다.


The “tap” event


Tap은 touch와는 다르게 한번 손가락이 움직이면 이 이벤트는 cancelled 됩니다. 이것은 quick touch로도 설명될 수 있죠. 이런 경우는 multiple quick tap들을 detect 해야 될 경우에 필요합니다. (예를 들어 특정 객체나 스크린에 double-tap을 하는 경우)


Event Listener


오브젝트에 이벤트 리스너를 추가하기 전에 (혹은 global Runtime object에 추가하기 전에) 여러분은 tap이 일어나면 어떤 일이 발생하는지에 대해서 정하셔야 합니다. 다른 이벤트들과 마찬가지로 이 부분에서 이벤트 리스너 함수가 나오게 되거든요. 아래 예제가 있습니다.


local function onImageTap( self, event )
    print( self.id .. " was tapped." )
end


그 다음으로는 객체에 tap 이벤트 리스너를 추가하시면 됩니다.


local object = display.newImage( "image.png" )
object.id = "myObject1"
object.touch = onImageTap  -- the function we created previously
object:addEventListener( "tap" )

아래는 똑같은 기능을 하는 건데요. 객체가 아니라 전체 스크린에서 tap 이벤트를 감지할 겁니다.


local function onScreenTap( event )
    print( "The screen was tapped." )
end
Runtime:addEventListener( "tap", onScreenTap )


touch 이벤트와 비교한다면  리스너 함수 부분이 훨씬 간단한 걸 느끼실 겁니다. 왜냐하면 이벤트 phase 부분을 체크할 필요가 없으니까요. 그리고 focus나 return value 등도 체크할 필요가 없습니다. 이렇기 때문에 여러분은 간단하게 테스트를 해야 될 때 touch event를 적용하기 이전에 이 기능을 활용하실 수 있습니다.






event.numTaps


이 tap 이벤트를 touch 이벤트 대신에 사용하시게 되면 event.numTaps 프로퍼티를 통해서 몇번의 탭이 일어났는지를 쉽게 알아낼 수 있습니다. touch event로 구현하려면 훨씬 더 복잡하게 해야 되는 부분이죠.

대개 체크하는 touch 수는 1이나 2 입니다. 하지만 tap이 충분히 빠르다면 3도 체크할 수 있겠죠. 짐작하시겠지만 이 기능은 double-tap을 감지하는데 사용됩니다. 예를 들어 double-tap 했을 경우에만 어떤 동작을 하는 객체가 있다면 이 event.numTaps를 사용하시면 좋을겁니다. 아래 예제 처럼요.


local object = display.newImage( "image.png" )

function object:tap( event )
    if (event.numTaps >= 2 ) then
        print( "The object was double-tapped." )
    end
end

object:addEventListener( "tap" )


또한 여러분은 tap event가 일어난 위치를 알기 위해 event.x, event.y 를 사용할 수 있습니다.

좀 더 자세한 내용은 tap event documentation 를 참조하세요.



반응형


반응형

코로나를 듣긴 들었는데 아직 한번도 코로나로 작업해 보지 않으신분 혹은 제대로 입문을 해 보고 싶으신 분들에게 좋은 소식이 있습니다.


Corona Labs에서 "Intro to Corona SDK" 라는 코로나 입문과정 Webinar를 준비했습니다.


미국 시간(Pacific Time)으로 7월 27일 금요일 아침 9시부터 10시까지 진행합니다.

미국 동부시간으로는 27일 오후 12시부터 1시까지 진행 되구요.


한국시간으로는 7월 28일 새벽 1시부터 2시까지 진행 됩니다.


이거 들으시려면 토요일 밤 잠은 설치셔야 되겠는데요.


코로나로 앱을 만드는 과정을 직접 배우고 싶으신 분들은 등록하시고 그 시간에 Webinar에 참가 하시면 됩니다.


등록은 아래 링크에서 하시면 됩니다.


Intro to Corona SDK Webinar





미리 준비해 두셔야 될 것은 Corona SDK 하구요.

텍스트 에디터 아무거나 하시면 됩니다.

울트라 에디터나 아크로 에디터, Notepad ++ 같은 것들이요.


그리고 질문거리도 있으시면 준비하시구요.

영어로 진행될 거라서 영어로 준비하셔야 되요.


위 웹페이지로 가셔서 이름, 성, 이메일주소, 도시, 주(도), 나라, 회사이름, 직원수 뭐 이런걸 넣고 Register Now 버튼을 누르면 되네요.


코로나 SDK에 관심이 있으셨는데 아직 직접 접할 기회를 갖지 못하신 분들 이번 기회에 좋은 입문 강좌 무료로 들어보세요.




반응형


반응형
Posted on . Written by


요즘 점점 관심을 모으고 있는 것 중에 "놓고 간 곳에서 pick up" 하는 기능이나 멈추고 다시 시작하는 과정에서 매끄럽게 동작이 이뤄지는 것이 있습니다. 점점 앱이 이전에 stop 했던 곳에서 다시 시작하는 기능이 많아 졌습니다.

유저가 마지막에 있었던 곳에서 다시 앱을 시작하도록 하는것은 state saving 로 불리기도 하고 이 주제가 오늘 제가 다룰 주제입니다. 이곳에 포스트된 튜토리얼들은 여러분이 앱을 개발하면서 필요로 하는 부분에 대해 어떻게 해야 하는지를 알려주는 튜토리얼이 되도록 구성하고 있습니다.





Resuming Suspended Apps


디폴트로 앱이 suspended 됐을 때 (예를 들어 유저가 폰의 홈버튼을 눌렀을 때 등) 여러분 앱은 실제로 중지된것이 아닙니다. 그 앱은 suspended state로 됩니다. 그리고 유저가 간 곳에서 떠날 때 (left off) 그 앱은 다시 실행됩니다. 이렇게 suspended 상태에서 앱이 끝나는 경우는 너무 많은 앱을 띄워서 메모리가 부족할 때 device의 operating system이 suspended 상태의 앱을 quit 시킬 때 입니다.

이런 default로 설정된 상황을 바꾸려면 iOS 앱의 경우는 build.settings에서 UIApplicationExitsOnSuspend 를 true로 놓으면 됩니다. 디폴트는 fault 인데요. 그 의미는 이 앱이 left off 상황일 때 자동적으로 재시작 되도록 한다는 의미입니다. (OS가 이 앱을 quit 하는 경우는 해당이 안 되겠죠.)


iphone = {
  plist = {
    UIApplicationExitsOnSuspend = true
  }
}


대부분 유저는 본인의 의지로 앱을 떠납니다. 하지만 가끔 그렇지 않을 때도 있습니다. (전화가 걸려 온다던지 하는 경우) 그래서 그런 경우 user's experience를 깨지 않도록 재시작(resume) 상황에서 뭔가를 작동하도록 만드는 것은 개발자의 판단에 달려있습니다. 이 상황에 딱 맞는 예는 게임하는 상황입니다.
예를 들어 두들 점프 (Doodle Jump)를 하고 있는 중간에 앱을 닫았고 나중에 다시 돌아올 때 이 게임을 pause screen으로 할 수 있습니다. 만약 전화통화가 끝났는데 바로 character가 점프 해 있는 상황이 된다면 그 판은 여러분의 high score를 깨기 힘든 상황이 될 겁니다. pause screen으로 재시작하는 것은 user-experience 관점에서 훨씬 좋은 흐름일 것입니다.

다행히도 코로나 (Corona)는 여러분의 앱이 suspend 됐거나 resume 될 때 system events를 사용할 수 있도록 합니다. 아래에 앱이 suspend 됐을 때 어떻게 게임을 pause 시키는지를 보여주는 예제가 있습니다.


local function onSystemEvent( event )
    if (event.type == "applicationSuspend") then
        pause_game()
    end
end
Runtime:addEventListener( "system", onSystemEvent )


pause_game() 함수가 무슨일을 하는지는 여러분이 구현하기 나름이지만 대략 어떤 일을 해야 될지는 알겠죠? 일단 global Runtime객체에 리스너를 추가했습니다. 그리고 이 이벤트가 call 됐을 때 실행 될 특정 함수를 지정했습니다.

그 함수안에서는 event.type 이 "applicationSuspend" 인 것을 체크해서 그럴 경우 실행할 함수를 명시했습니다.


Resuming from a “cold” start


지금 다룰 시나리오는 조금 어렵습니다. 여러분 앱이 cold로 시작 됐을 때 (예를 들어 suspended가 아니라 closed나 quit 상태에서 시작됐을 때) 디폴트 behavior는 처음 (main.lua) 부터 새로 시작하는 것일 겁니다.

첫번째로 하셔야 될 일은 현재 상태를 save 하셔야 되는 겁니다. 어떤 방법으로 저장할지는 여러분 마음이지만 table 형태로 데이터를 저장하고 이것을 JSON 스트링으로 converting 하고 file로 저장한 다음에 나중에 로드하시기를 권고 드립니다. (이런 경우 코로나에서 file 읽고 쓰기 부분을 참조하세요.)

다음으로 파일을 파일을 로드하고 앱에게 시작됐을 때 이 데이터를 근거로 어떤 일을 하라고 알려 주어야 합니다. 이럴 경우 suspended 상태이건 cold 상태이건 앱이 새로 시작할 때 이전 상황과 이어지는 상황에서 앱을 다시 시작할 수 있을 겁니다.

데이터를 저장하는 시기는 조금 전에 셋업한 시스템 이벤트 리스너에서 event.type이 applicationExit 일 경우를 체크해서 수행하시면 도비니다. 그리고 나서 event.type이 applicationOpen일 경우 저장해 뒀던 데이터를 로드하고 그것을 근거로 어떤 일들을 수행하면 됩니다.


local function onSystemEvent( event )
    if (event.type == "applicationExit") then

        save_state()    

    elseif (event.type == "applicationOpen") then

        load_saved_state()

    elseif (event.type == "applicationSuspend") then

        pause_game()

    end
end
Runtime:addEventListener( "system", onSystemEvent )


예제를 보니 그렇게 복잡해 보이지 않죠?

save_state()나 load_saved_state() 함수와 관련해서는 더이상 자세한 내용을 언급하지는 않겠ㅅ브니다. 왜냐하면 이것은 앱마다 다 다를 테니까요. 적어도 특히 게임에서는 객체들이 화면상에 있는 정보인 프로퍼티들과 위치들 같은 데이터들을 저장해야 할 겁니다. (그래야지 load_saved_state() 함수에서 그 객체들을 이전에 있던 위치에 display 할 수 있으니까요.)

유저들은 마음대로 그 앱을 열었다 닫았다 할 겁니다. 그리고 그러한 상황에서 유저들에게 자연스러운 앱의 진행상황을 제공하려면 여러분은 그 앱이 suspended나 cold state에서 다시 재시작할 때 유저들이 아무런 끊김없는 혹은 뭔가 당황스러운 상황이 없는 화면 전개를 보여주는데 신경을 쓰셔야 될겁니다.

반응형

Best Practices for Organizing Projects

2012. 7. 11. 11:33 | Posted by 솔웅


반응형
Posted on

. Written by


샘플코드나 다른 예제 혹은 이 웹사이트의 튜토리얼을 포함해서 코로나를 배우는데 명료하게 알기 힘든것이 바로 프로젝트를 어떻게 organize 할 것이냐 입니다. 알려 드릴 사항은 모든것이 여러분의 project 폴더 아래로 가게 된다는 거고 나머지는 여러분 취향대로 하시면 되는겁니다. 그리고 sub folder 도 지원 됩니다. 여기까지가 지금까지 이 주제와 관련해서 저희가 한 말이죠.


그런데 여러분의 프로젝트가 규모가 더 커지면 이 지식만 가지고는 organize 하기가 좀 부족합니다. 점점 더 많은 리소스들이 여러분 프로젝트에 추가 될 겁니다. 오디오 파일이나 이미지, 비디오, 루이 모듈 같은 것들이요. 이걸 제대로 정리하지 못하면 개발하는데 아주 복잡하게 만들죠.


이 튜토리얼은 코로나 SDK 프로젝트 organization 테크닉의 전부를 말하지는 않습니다. 단지 좀 더 효율적으로 관리할 수 있는 방법을 제안할 뿐입니다.




Project Structure


모든걸 간단하게 가지고 가는 것은 여러분의 프로젝트가 잘 organize 되어야하고 그로 인해 유지 관리하는 것이 쉽도록 하는 겁니다. 제가 소개할 이  organization technique 은 대부분의 프로젝트에서 쉽게 셋업하고 쉽게 이해하고 쉽게 scale (여러분의 프로젝트가 점점 더 커지게 될 때를 대비해서) 하는데 충분히 도움이 될 겁니다.


프로젝트 폴더를 구성할 때 여러분이 따라야할 기본적인 전제는 비슷한 파일들을 다른것과 별도로 보관하라는 겁니다. 비슷하고 다르다는 기준은 type 이나 그 종류를 말할 수도 있습니다. 아래 샘플로 제공하는 프로젝트 hierarchy 구조가 있습니다.


  • Project_Folder/ (top-level)
    • images/ (folder)
    • audio/ (folder)
    • videos/ (folder)
    • data/ (folder)
    • scripts/ (folder)
    • main.lua
    • config.lua
    • build.settings
    • Default.png
    • Default@2x.png
    • Icon.png
    • Icon@2x.png


위의 폴더 구조 예제에서 top-level 디렉토리(폴더) 에 있는 것은 가장 중요한 것은 main.lua 입니다. 다른 config.lua, build.settings 같은 파일들도 top-level에 있어야 된는 겁니다.

이 top 에 있는 폴더들은 그 이름만 봐도 어떤 것들인지 쉽게 이해가 갈 겁니다. 아래 간단히 설명을 덧 붙이겠습니다.

  • images – image files with the extension of (most-likely) .png or .jpg.
  • audio – audio files (.caf, .mp3, .ogg, etc.)
  • videos – video files (.avi, .mp4, etc.)
  • data – read-only data files used by your app. They can really be any format, but common ones include .json and .xml.
  • scripts – other Lua files (apart from main.lua). More on this in a moment.


더 이상의 설명은 필요 없겠죠? script 폴더만 제외하고는요.

여러분이 util.lua를 사용해야 한다고 가정해 봅시다. 일반적이로 이 파일을 top-level에 위치시키는데요. (main.lua 하고 같은 위치에요). 만약 그렇게 할 경우 아래처럼 불러올 수 있습니다.


local util = require( "util" )


만약 이 util.lua를 scripts 폴더 아래에 넣었다면 위와 같이 하면 작동하지 않을 겁니다. 폴더이름에 점을 붙이고 모듈 이름을 넣으셔야 합니다. 아래처럼요.


local util = require( "scripts.util" )


이미지를 불러올때는 폴더 이름을 쓰고 / 를 넣고 이미지 이름을 넣으셔야 합니다. script에서는 .을 사용했는데 여기서는 /를 사용해야 합니다. 사실 스크립트만 다릅니다. 아래 그 예제가 있습니다.


local obj = display.newImage( "images/corona.png" )


Scaling Projects

여러분의 프로젝트에 더 많은 이미지나 스크립트 그리고 다른 파일들이 추가되면 이 sub directory 만으로도 충분하지 않게 되죠. 그렇게 되면 서브 디렉토리 안에 또 다른 서브디렉토리를 넣어야 겠죠. 아래 depth 가 더 늘어나도 그 안에 있는 파일이나 스크립트를 require 하는 방법은 위에서 설명한 것과 같습니다. 아래는 몇단계의 level 이 있는 게임을 상상하고 폴더 구조를 구성해 봤습니다.


  • Project_Folder/ (top-level)
    • images/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • audio/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • videos/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • data/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • scripts/ (folder)
      • level-001/ (folder)
      • level-002/ (folder)
      • level-003/ (folder)
    • main.lua
    • config.lua
    • build.settings
    • Default.png
    • Default@2x.png
    • Icon.png
    • Icon@2x.png


위의 구조와 다른 점은 이미지,오디오, 비디오, 스크립트 디렉토리들이 이제 그 안에 또 sub-directory들을 가지고 있다는 겁니다. 각각의 레벨 별로 구분되는 서브 폴더들을요. 10단계 20단계 되는 게임을 상상해 보시면 이런식으로 개발하는 것이 훨씬 더 간편하겠죠? 오랫동안 유지 관리하는데 훨씬 유리하게 잘 조직화 돼 있다고 할 수 있습니다.


50단계가 있는 게임인데 모든 리소스를 top-level  프로젝트 디렉토리에 보관하고 있다고 상상해 보세요. 유지 관리하는 관점에서 보면 악몽이 되겠죠?


이 튜토리얼에서 소개한 대로 프로젝트 구조를 관리하시던지 아니면 여러분만의 방법을 사용하시던지 Corona SDK 프로젝트를 시작할 때 프로젝트의 파일구조를 충분히 고민하시고 난 후 시작하는것이 나중에 가서 훨씬 더 도움이 되실 겁니다.



반응형

수요일의 FAQ - 070412 -

2012. 7. 8. 00:44 | Posted by 솔웅


반응형
Posted on . Written by


오늘은 수요일이자 독립기념일입니다. 독립기념일의 FAQ를 시작하겠습니다. 아래에 자주 나오는 질문 5가지와 그 답변이 있습니다.


1. ‘require(“file”)’ 과 ‘require “file”의 다른 점이 뭔가요?


여러분은 require API 에서 아래 두가지 방법을 보셨을 겁니다.

-- Example #1
local json = require( "json" )

-- Example #2
local json = require "json"


일반적으로 함수는 pass 하게 될 인자(argument)들을 요구합니다. 하지만 루아에서는 약간의

예외가 있습니다. 만약에 함수가 단 한개만의 인자만 가지고 있다면 (그것이 스트링이던

테이블이던) 괄호는 옵션 사항입니다. 이 규칙은 print 구문이나 한개의 인자(스트링이든

테이블이든) 를 받는 다른 함수에도 마찬가지로 적용됩니다.



2. 우리는 코로나의 변수와 관련해서 많은 complain을 받습니다.

분명히 변수에 값을 대입했는데 인덱스나 함수에서는 nil이라고 하니까

분명히 버그가 있을 거라는 겁니다.

 

코로나에서 사용하는 루아라는 언어로 프로그래밍을 하다보면 가장 흔하게 부딪히는 문제점이

nil 에러입니다.

다른 언어와는 다르게 루아는 변수를 사용하기 전에 선언해야 하지 않습니다.

변수에 값을 대입하지 않으면 루아는 그 값을 그냥 nil로 처리합니다.

nil 에러가 일어나는 일반적인 원인은 변수나 함수가 out of scope 일 경우가 많습니다.

여러분이 변수나 함수를 local로 정의해서 메모리를 점유하게 만들면 이런 경우가 종종

발생할 수 있습니다.

루아에서 로컬 변수의 scope은 그것이 선언된 곳 (예 main.lua)에 한정돼 있습니다.

다른 lua 파일에서 그 로컬 변수에 접근하려고 할 경우 이 nil 에러가 발생합니다.

또한 로컬 변수는 그것이 정의(선언)된 이후에 참조가 가능합니다. 변수가 선언되기 이전에

이 변수를 참조하려고 한다면 여기서도 nil 에러가 일어납니다.

 

저는 대개 로컬 변수를 루아 파일의 맨 첫 부분에 정의를 합니다. 그러면 나중에 그 변수에

접근이 가능하니까요.


-- This code block won't work because the addNumbers
-- function is called before it's been defined

local addNumbers -- forward reference

print( addNumbers( 5, 6 ) )

function addNumbers( num1, num2 )
return num1 + num2
end


-- This code block works because the addNumbers
-- function is called after it's been defined

local addNumbers -- forward reference

timer.performWithDelay( 1, function()print( addNumbers( 5, 6 ) ) end )

function addNumbers( num1, num2 )
return num1 + num2
end

 

timer.performWithDelayaddNumbers 함수가 정의 된 후에 execution code에서 addNumbers

함수를 call 합니다. 여기서 그 함수로 포인터가 access 하기 위해local addNumbers 구문이

필요합니다.


한번 변수 선언할 때 local을 없애고 어떻게 되는지 보세요. 그것이 정의 되기 전에 함수를

call 하게 되면 마찬가지로 에러가 날 겁니다. 그 변수나 함수가 nil (out of scope)인지

아닌지 체크해 보기 위해서 print 구문을 사용하셔도 됩니다. 에러가 났을 경우 정확히

어디에서 에러가 났는지 찾아보는데 도움이 될 겁니다. 변수나 함수들을 print out 할 때

콤마 , 를 사용하세요. 콤마와 함께 프린트 하게 되면 nil 밸류와 함께 함수와 테이블

addresses를 보여 줄 겁니다.



3. Facebook 인터페이스에 대한 문서는 어디에서 볼 수 있죠?


코로나의 페이스북 인터페이스는 Facebook Graph API를 사용합니다.

여기에서 코로나 페이스북 문서에 대한 인터페이스 정보를 찾아보실 수 있습니다.

Facebook API페이지의 페이스북 파라미터 정보도 찾아 보실 수 있습니다.
그리고 우리의 Jonathan Beebe의 아주 훌륭한 페이스북 튜토리얼도 참조하세요.
Implementing Facebook Single Sign-on and Uploading Photos to Facebook.

코로나 SDK에 포함된 페이스북 샘플 앱도 잊지 마시구요.



4. baseDirectory에 subdirectory 이름을 add 해서 이미지를 로드하려고

합니다.그런데 제대로 로드되지가 않네요. 뭐가 잘못된거죠?


baseDirectory
인자(argument)는 Corona API에서 아주 많이 사용되는데요.

이는 asset들에 대한 base directory를 가리키고 있습니다.

이 base directory는 사전 정의된 아래 3개 constants (상수) 중에 하나이어야 합니다.

system.ResourceDirectory,system.TemporaryDirectory, system.DocumentsDirectory

아무것도 특정하지 않으면system.ResourceDirectory 가 디폴트로 사용됩니다.


그 subdirectory에 있는 asset에 접근 하시려면 이 subdirectory는 파일 이름에 추가

하셔야 합니다. baseDirectory에 추가하시면 안 됩니다.


아래 예제가 있습니다.

local IMG_DIR = "images/"
-- Loads image from Resource directory
local image = display.newImage( "apple.png", 50, 50 )

-- Loads image from Resource directory
local image = display.newImage( "apple.png", system.ResourceDirectory, 50, 50 )

-- Loads image from images subfolder in Resource directory
local image = display.newImage( IMG_DIR .. "apple.png", 50, 50, true )

-- Loads image from images subfolder in Documents directory
local image = display.newImage( IMG_DIR .. "apple.png",
system
.DocumentsDirectory, 50, 50 )

subfolder 이름을 구분하는 구분자로는 . 가 아닌 / 를 사용한다는 것을 기억하세요.

. 는 require 에서 사용됩니다. 그리고 그 나머지에서는 / 를 사용합니다.



5. 이건 질문은 아닌데요. Lua 에만 있는 특별한 기능입니다.
함수에서 return 하는 return 값이 복수개가 될 수 있는 기능입니다.


루아는 함수에서 multiple value들을 return 할 수 있는 몇 안되는 언어중 하나입니다.

에러 메세지같은 multiple value들을 return 해야 할 때 편리하게 사용됩니다.

이 기능을 이용해 여러 진보된 기능의 루아 함수들을 많이 보실 수 있을 겁니다.

-- The string.find API returns the start and end of the found string
print( string.find( "Hello Corona user", "Corona" ) ) -- prints 7 and 12

여러분이 만드는 함수에도 이 기능을 사용하실 수 있습니다.

myRect = display.newRect( 0, 0, 25, 50 )

local function getWidthHeight( object )
return object.width, object.height
end

print( getWidthHeight( myRect ) ) -- print 25 and 50

여기까지가 오늘의 질문들입니다.

조금이라도 새로운 것을 배울 수 있는 유익한 시간이었길 바랍니다.



반응형


반응형
Posted on . Written by

필요없는 객체를 제거하고 변수를 처리하는것은 사소한 일 처럼 느껴지지만 코로나의 신규 개발자이든 경력이 있는 개발자이든 항상 질문하는 내용 중 하나입니다. 이 일을 처리한 결과 일어나는 일은 아주 간단합니다. 하지만 이 일을 제대로 처리하지 않아서 일어나는 메모리 손실이나 속도저하 그리고 crash 같은 것들은 아주 큰 영향을 미칩니다.


Removing display objects


코로나 display object(그리고 다른 타입들의 객체들)은 object:removeSelf()메소드를 사용해서 remove될 수 있습니다. 이 메소드를 call 하는 것은 쉽습니다. 이 메소드를 call 해서 얻어지는 결과는 현재 보이는 객체가 보이지 않게 되므로 확인하는것도 쉽습니다. 

이것을 잘못 사용할 수 있는 경우는 단지 그 객체가 스크린에서 없어지느냐 아니면 앞으로 더 이상 사용될 필요가 없는것이냐를 구분해야 되는데 있습니다. 객체에 어떤 참조를 store하기 위해 사용했던 변수는 skeleton 테이블을 가지고 있습니다. 그것은 객체를 remove 한 이후에도 계속 있게 됩니다. 여러분이 object:removeSelf()를 하시고 난 후 그 변수를 print 하면 어떻게 될까요?


-- create the object
local object = display.newImage( "image.png" )

-- remove the object

object:removeSelf()

print( object )



이 변수는 여전히 table value를 가지고 있는것을 보실 수 있습니다. 그러니까 아직까지 그 변수는 empty 가 아닌겁니다. 그 의미는 이 변수가 아직 메모리를 차지하고 있다는 것이고 여러분이 Lua 에게 이 변수는 더 이상 사용하지 않을 것이라는 것을 말해야 된다는 것을 의미합니다. 그 다음에야 clean up 할 수 있죠. 그 방법은 그 변수에 nil을 할당해주기만 하면 됩니다. 그러면 그 변수를 완전하게 remove 하게 되는 겁니다.


object:removeSelf() 문서에서 예제 부분을 보시면 아래와 같이 변수에 nil을 할당하는 부분을 보실 수 있을 겁니다.


object = nil

다른 객체를 참조하고 있는 살아있는 변수를 없애는데도 이와 똑같이 해 주시기만 하시면 됩니다. 살아있는 변수의 의미는 자동적으로 clean up 되지 않는 글로벌 변수이든지 로컬 변수이든지 어떤 객체에 대한 참조를 하고 있어서 완전하게 remove 되어야 할 필요가 있는 변수를 말하는 겁니다.




Local variable gotcha


I touched on it already, but local variables (that is, variables that are declared with the word local preceding the variable name), get cleaned up automatically at the end of their block of code.

로컬 변수는 그 변수를 감싸고 있는 블럭이 사용되지 않는 순간에 자동적으로 clean up 됩니다.


즉 여러분이 어떤 객체를 어떤 독립된 블럭 안에서 생성했다면 이 함수가 실행되고 난 후에 그 객체는 자동적으로 remove 된다는 겁니다. (그 변수 선언은 앞에 local 이 붙어야 합니다.) . 그렇게 remove 되면 여러분은 그 변수에 다시 access할 수 없게 되죠.


아래 그 예제가 있습니다.


local function create_and_abandon()
    local outcast = display.newImage( "image.png" )
    outcast.x, outcast.y = 160, 240
end

create_and_abandon()


위 예제에서 create_and_abandon() 함수는 간단히 하나의 객체를 생성하고 (로컬변수를 사용해서) 그 객체의 위치를 설정해 주는 일을 합니다. 이 함수의 마지막 end 부분에서 이 outcast 변수는 더 이상 access 될 수 없게 됩니다. 그 객체를 내버려 두고 떠나서 더이상 다뤄지거나 remove 될 수 없게 되는 겁니다.

이러한 상황을 방지하기 위해서는 이 변수 선언을 함수 블럭 바깥에서 선언하셔야 합니다. 아래에 그 예제가 있습니다.


local outcast  -- forward declaration

local function create_and_abandon()

    outcast = display.newImage( "image.png" )
    outcast.x, outcast.y = 160, 240
end

create_and_abandon()


-- we can now remove the object

outcast:removeSelf()
outcast = nil



이 예제에서는 이 함수가 끝난 이후에도 우리는 outcast 변수에 access 할 수 있게 됩니다.  객체를 생성할 때 local 이 빠져있죠? 단지 블럭 바깥에서 변수를 생성할 때 local을 붙였습니다. 이 의미는 이 변수가 그 블럭내의 local 이 아니라는 거죠. 이 outcast 변수는 local 변수 입니다. 단지 저 함수 블럭 내의 local 이 아닌 겁니다. 그래서 함수가 다 실행되고 나서도 이 변수를 우리가 접근해서 컨트롤 할 수 있는 겁니다.


여기까지가 코로나에서 변수나 객체를 remove 하는데에서 알아야할 내용 전부 입니다. 이 튜토리얼에 있는 내용은 아주 중요한 부분 입니다. 코로나를 새로 접하시는 분들이 항상 혼동을 일으키는 부분입니다. 이 부분을 잘 이해하셔서 여러분 앱에서 hard-to-trace 문제를 일으키지 않도록 주의하셔야 합니다.

좀 더 많은 정보를 완하시면 Display Objects and Stage 가이드의 Removing Objects Properly  섹션을 보세요.


반응형