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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

FAQ Wednesday: iPhone 5 와 iOS 6

2012. 9. 21. 11:28 | Posted by 솔웅


반응형
Posted on . Written by


FAQ 시간인 수요일입니다. iOS 6 가 오늘 릴리즈 됐고 아이폰 5 는 금요일에 릴리즈 될 겁니다. 요즘 이슈가 되는 이 두가지의 릴리즈와 관련되서 많이 질문되는 것들을 오늘 다루겠습니다. 아직 Walter가 올린 iPhone 5와 iOS 6를 지원하는 것과 관련된 글을 보지 못하신 분들은 여기를 들러서 먼저 봐 주세요.


1. Will my existing apps working on the new iPhone 5?


예 여러분의 기존 앱은 iPhone 5나 iOS 6로 업데이트 된 디바이스에서도 지금처럼 작동될 겁니다. iPhone 5와 관련된 이슈는 여러분의 unmodified app 이 Retina device (640 X 960) 에서 작동되는 걸로 생각할 거라는 겁니다. iPhone 5는 640 X 1136 입니다. 여러분의 기존 앱은 iPhone 5에서 아래 위가 검정색으로 나타나는 letterbox 모드로 표시 될 겁니다. (아래 위로 길 경우)





2. Do I have to resubmit my app for iPhone 5?


위에서 얘기한 것처럼 여러분의 기존 앱이 iPhone에서 아래위로 검은처리 된 상태로 작동되는게 문제가 없으시다면 굳이 여러분 앱을 iPhone 5로 업그레이드 하실 필요는 없을 겁니다. 여러분이 iPhone 5를 가지고 있지 않더라도 iOS Simulator에서 확인하실 수 있으니 한번 확인해 보세요. 이 iOS 시뮬레이터를 이용하시려면 Xcode 4.5를 다운 받으셔야 한다는 것 알고 계시죠? 만약 여러분의 기존 앱을 iPhone 5용으로 업그레이드 하고 싶으시다면 iOS 6에 맞게 다시 빌드 하셔야 됩니다.


한가지 유념하실 부분이 있는데요. 만약 여러분의 앱이 애플의 GameCenter를 사용한다면 아래 Question #4 를 꼭 읽어 보세요.



3. How can I make my app use the full iPhone 5 screen?


기존의 여러분 앱이 iPhone 5에서 좀 더 잘 보이게 하는 방법이 몇가지 있습니다.


첫번째는 new splash 파일을 여러분의 프로젝트에 추가하는 겁니다 : Default–568@2x.png. 이것은 640 X1136  크기의 이미지 입니다. 이 이미지는 여러분 앱이 iPhone 5 device에서 로딩이 시작될 때 보여질 이미지 입니다. 이 파일은 iOS6에게 여러분의 앱이 full iPhone 5 screen을 지원한다고 통보할 겁니다. ("tall" mode). 그래도 여러분 앱은 letterbox로 보일겁니다. 하지만 status bar는 맨 위에 제위치로 가게 될 겁니다.


display.pixelWidth and display.pixelHeight. 이 API들은 스크린의 실제 가로 세로 값을 보여줄 텐데요. 이 new splash screen을 사용한 후의 화면을 보세요. iOS 6가 Corona에게 이것은 640 X 1136 디바이스라고 얘기합니다. 이 splash screen 이 없으면 그 값은 640 X 960 (iPhone 4 mode)가 표시 될 겁니다.




이 새로운 디폴트 splash file을 추가한 후에 여러분은 display.setDefault API를 사용하실 수 있습니다. 배경색을 넣을 수 있는 겁니다. 이 API로 시꺼먼 letterbox area를 다른 색으로 채우실 수 있습니다.


display.setDefault( "background", 200 )





또 다른 옵션은 배경 이미지를 로드 하는 방법입니다. 이 이미지는 letterbox area 까지 extend 될 겁니다. 여러분 앱이 iPhone 과 iPhone 5만을 타게팅 한다면 이 이미지는 320 X 568 이 될 겁니다. 이 이미지의 y 포지션을 offset 하셔야 이 이미지가 스크린의 맨 위에서부터 시작할 겁니다. y 포지션을 지정하실 때는 display.screenOriginY를 사용하셔야 합니다.


display.newImage( "background568.png", 0, display.screenOriginY )




(저는 스크린에 가득차게 보이도록 이미지 둘레에 yellow/green border를 추가했습니다.)

config.lua file 에서 zoomEven scaling mode를 사용해 보세요. 이 zoomEven은 여러분 앱의 크기를 가로 세로 똑 같은 비율로 화면에 꽉 찰 때까지 늘릴겁니다. iPhone 5의 portrait 모드에서는 여러분 앱이 아래위로 늘어나는 만큼 좌우도 늘어나기 때문에 일부가 화면 밖으로 사라질 겁니다. (아래 screen shot을 보세요.)





위 예제는 dynamic scaling 이 320 X 480 이고 target을 iPhone, iPhone4, iPhone 5 디바이스로 했을 경우를 가정해서 얘기한 겁니다. 만약 안드로이드도 지원할 필요가 있다면 안드로이드 디바이스의 크기도 같이 고려해서 이러한 것들을 정해야 할 겁니다. (최신 CoronaSDK builds는 여러분의 content 가 제대로 표시되도록 도와주는 새로운 시뮬레이터 스크린 사이즈를 제공하고 있습니다.)


4. Why does my GameCenter crash when running on iOS 6?


만약 여러분 앱이 Apple’s GameCenter를 사용한다면 그리고 그 앱이 오직 landscape mode로만 작동이 된다면 그 상황에서 발생하는 bug 가 있습니다. 뭐냐하면 여러분 앱은 landscape 인데 GameCenter의 Sign-on Screen 은 portrait mode로 표시하려고 하기 때문에 충돌이 일어납니다. 이 상황은 여러분 앱을 iOS 6 용으로 빌드하고 그 앱을 iOS 6 device에서 작동할 때 발생합니다.


한 유저가 그 해결책을 Corona의 Forums에 올리셨는데요. content를 landscape로 세팅하고 앱은 landscape와 Portrait 모두를 지원한다고 세팅 해 놓는게 그 해결방법 입니다. 이렇게 하면 GameCenter sign-on 화면은 portrait으로 뜨고 여러분 앱은 landscape 모두에서 작동하도록 할 겁니다. 폰이 rotate 될 때 status bar 도 자동으로 rotate 될 텐데요. 대부분의 게임에서 status bar를 표시하지 않으니까 이 부분은 그리 크게 신경쓰지 않으셔도 될 것 같습니다.

아래 처럼 build.settings 파일에 코딩을 해 넣으시면 됩니다.


orientation =
{
default = "landscapeRight",
content = "landscapeRight",
supported = { "landscapeLeft", "landscapeRight", "portrait" },
},



Note: 이 이슈가 iOS 6에서 빌드하고 iOS6 device에서 앱을 구동시킬때 발생하는 유일한 이슈 입니다. 만약 여러분의 기존 앱이 iOS 5.1용으로 만들었다면 이 부분은 신경 안 쓰셔도 됩니다.


5. Why don’t I see any of my print messages in the Xcode Console?


iOS 6에서 애플은 Lua print message가 보여지지 않거나 internal Corona runtime 에러가 표시되도록 바꾸었습니다. iOS 6 에서는 Xcode Console과 맥 콘솔 앱에 여러분의 iOS 6나 iOS 6 시뮬레이터로부터 더이상 메세지를 받지 않습니다.


build 915에서 코로나 런타임 에러를 메세지로 restore 하도록 바꾸었습니다. 하지만 Lua print API 관련해서는 아직 해결책을 마련하지 못했습니다. 지금으로서는 런타임 에러 메세지는 보일것이지만 print로 출력하는 디버그 메세지는 표시되지 않을 겁니다. print 함수를 임시파일에 저장하도록 redirect 해서 나중에 확인하실 수 있을 겁니다. 이게 좋은 solution은 못 되지만 여러분이 현재로서는 여러분이 device에서 테스팅하면서 디버깅할 때 사용할 수 있는 방법중의 하나입니다.

iOS 6의 변화로 인해서 저희도 맥 시뮬레이터에 에러와 메세지를 표시하는 방법을 바꾸어야 했습니다. 메세지 앞에 date/time 을 추가하는 메세지를 표시하기 위해 지금은 NSLog를 사용합니다. 이 방법이나 혹은 다른 방법으로 iOS 6 print issue를 해결해야만 합니다. 또한 맥 시뮬레이터 콘솔에 어떻게 정보를 출력할 것인지도 영향을 받을것입니다.  또한 우리의 콘솔과 에러메세지를 이용하는 3rd party 코로나 프로그램도 영향을 받을 겁니다. 이 변화의 잇점으로는 이제 맥 콘솔 앱이 코로나 시뮬레이터와 iOS 시뮬레이터 모두로부터 Corona runtime data를 받는다는 것입니다. (조만간 print 도 가능할 겁니다.) 코로나 시뮬레이터와 빌드 메세지를 보기 위해 터미널 윈도우를 ipen 해야 하는 수고를 안해도 되게 됐죠.



That’s it for today’s questions. I hope you enjoyed it and even learned a few things.

반응형


반응형

FAQ Wednesday: native.newTextField and native.newTextBox Events


Posted on . Written by


It’s Wednesday and time for another FAQ session. Here are five frequently asked questions (FAQ).


1. Why is the “submitted” event phase missing for native.newTextField on devices but it’s working on the Mac Simulator?


“submitted” phase는 유저가 키보드의 “return” or “done” key 를 눌렀을 때 보내 집니다. 이것은 유저가 텍스트 입력 작업을 끝마치고 해당 정보를 “submitted” 했다는 것을 가리키는 것이죠. 유저가 다른 필드를 클릭해서 포커스가 바뀔 경우는 보내지지 않을 겁니다. build 904 버전 이전에는 맥 시뮬레이터는 항상 “submitted” and “ended” phases 가 같이 보내졌습니다. (submitted key 가 클릭되지 않았을 때도요). build 904 부터 맥 시뮬레이터는 iOS와 Android가 작동되는 것과 비슷하게 작동하게 됐습니다.




2. I’m confused about the “ended” and “submitted” phases for native.newTextFields.


TextField events가 작동하는 과정을 요약해 보겠습니다. 유저가 textfield를 클릭(터치)하면 “began” phase가 보내지고 키보드가 보여집니다. 타이핑이 일어나면 “editing” phase가 발생하죠. return/done button 이 클릭되면 ended” phase 가 보내진 다음에 “submitted” phase가 보내집니다. 만약 유저가 다른 Textfield나 다른 TextBox를 터치했다면 “submitted” phase는 보내지지 않고 “ended” phase만 보내지겠죠.


iOS에서는 number 를 넣을 TextField를 생성했을 경우 return key 가 없는 키보드가 나올 겁니다. 그러니까 유저가 일을 마쳤을 때 누를 버튼을 제공해 줘야 합니다. 키보드를 감추려면 native.setKeyboardFocus를 nil 로 하셔야 됩니다. 이렇게 키보드를 숨길 때 TextField 객체에 대한 “ended” phase 가 생성됩니다.

Note: 위의 상황은 build 904 버전 이후의 맥 시뮬레이터에서만 작동됩니다.



3. What happened to the “submitted” event phase on native.newTextBox?


newTextBox에는 submitted event phase가 없습니다. 이유는 return 키를 누르면 입력한 값이 submit 되는 것이 아니라 다음 줄로 가기 때문이죠. 이전 질문에서 언급됐듯이 유저가 작업이 끝났을 때 누를 수 있는 버튼을 생성하셔야 합니다.



4. When using native.newTextField, how do I hide the keyboard?


native.newTextField or native.newTextBox에서 키보드를 숨기려면 native.setKeyboardFocus 를 nil 로 하시면 됩니다. 역으로 native.setKeyboardFocus를 이용해서 포커스를 줄 수도 있습니다.



5. How can I edit text in the native.newTextBox?


디폴트로 native.newTextBox 는 editable이 아닙니다. object.isEditable = true를 하셔서 edit mode를 enable로 바꾸실 수 있습니다.


That’s it for today’s questions. I hope you enjoyed it and even learned a few things.



반응형

선그리기 기초 부터

2012. 9. 9. 22:01 | Posted by 솔웅


반응형

웹앱 프로젝트를 하느라고 오랫동안 코로나 개발에서 손 뗐었는데요.

너무 오래 안하다 보니까 그립네요.


써핑하다가 코로나 팁을 공유한 파일이 있어서 정리해 봅니다.


가장 기초적인 기능인 선 그리기 입니다.


일단 코드부터 볼까요?


display.setStatusBar( display.HiddenStatusBar ) -- Hide the status bar
 
local bx, by=0, 0
local lines={}
local p=1
 
local function drawALine(event)
    if "began"==event.phase then
        bx, by=event.x, event.y
       
    elseif "moved"==event.phase then
        lines[p]=display.newLine(bx, by, event.x, event.y)
       
        --Width
        lines[p].width=12

        --Alpha
        lines[p].alpha=1
       
        --Color
        lines[p]:setColor(255,255,255) -- White       
       
        bx, by=event.x, event.y
        p=p+1
       
        print(p);
       
    end    
end
 
Runtime:addEventListener("touch", drawALine)


맨 첫번째 줄은 아이폰에서 status bar를 없애는 코드입니다.

그리고 무엇인가를 그리려면 좌표가 필요하니까 x,y 좌표를 담을 변수를 만들었구요.

그 다음에 line 이라는 배열을 만들었습니다.


여기서 선 그리기는 시작점과 끝점을 찍어서 그 두 점을 연결하는 직선을 만드는게 아니라

손가락이 움직이는대로 따라서 선이 그어지도록 하는거거든요.


그러면 손가락을 따라 계속 선을 그어서 그 촘촘하게 그려진 선들이 결국에는 하나의 선처럼 보이게 하는 겁니다.


그래서 lines[] 라는 배열 만들었습니다.

그리고  p 는 변수에 차례대로 선들을 담기 위한 숫자로 쓰일 변수이구요.


이렇게 변수 선언 한 다음에는 drawALine 이라는 함수가 있는데요.


이 함수 건너뛰고 이벤트 리스너 부터 보겠습니다.

touch 에 반응하도록 했고 drawALine을 call 합니다.

그리고 어떤 객체에 이벤트 리스너를 단 것이 아니라 Runtime에 달았으니까 앱이 시작하면서 끝날 때까지 계속 활성화 되 있게 됩니다.


이제 핵심 부분인 함수를 볼까요?


우선 매개변수로 이벤트를 받습니다.


touch 이벤트에는 began, moved, ended 같은 phase들이 있습니다.


여기서는 began과 moved 라는 phase를 이용합니다.


우선 began 일 때는 그 이벤트가 일어난 지점 즉 손가락으로 터치한 지점의 x,y 좌표를 위에 선언했던 변수에 담습니다.


그리고 손가락이 조금이라도 움직일 때 발생하는 moved 일 때 drawLine을 사용해서 선을 긋죠.

began에서 저장했던 x,y 좌표에서 현재 움직인 지점의 x,y 까지 선을 긋습니다.

이 첫번째 line은 lines[] 배열 첫번째에 담기겠죠.

아마 코로나는 배열이 1부터 시작할 겁니다. PHP나 JAVA는 0부터 시작을 하죠.


그 다음은 이 그려진 선을 꾸미는 부분 입니다.

첫 부분은 width 를 사용해서 선의 두께를 정하구요. 그 다음은 투명도(alpha)를 정합니다.

그리고 setColor로 색을 정하구요.


이렇게 처음에 그려진 선을 다 꾸몄으면 다음 선을 준비하기 위한 작업을 합니다.

뭐냐하면 bx,by 값을 현재의 x,y 값으로 바꾸는거죠.


그러면 현재의 위치가 다음 moved 가 발생했을 때 시작점이 되는겁니다.

(이걸 하지 않으면 처음 touch 했던 부분부터 계속 선이 그어질 겁니다. 한번 해 보세요.)


그 다음에는 첫번째 선이 지정된 배열의 다음에 두번째선을 넣기 위해서 p에 1을 더합니다.

그 밑에는 제가 그냥 p 를 콘솔에 print 한 겁니다.


이렇게 하면 선긋기는 간단하게 끝납니다.


아래는 quinc 라는 친구가 공개한 선에 여러 효과를 줄수 있는 코드들입니다.


우선 width 부터 볼까요?


        lines[p].width=math.random(1, 30) -- Makes for an interesting "backbone" effect
        lines[p].width=12 -- Just a boring old set width
        lines[p].width=-3 -- I've heard of a line with a width of -3!
        lines[p].width=math.abs(event.y/20) -- 3D-ish horizon look


width 부분에 위 예제들을 하나하나 넣어가면서 실행해 보세요.

첫번째는 width가 1에서 30까지 랜덤하게 설정되는 겁니다. quinc 는 이것을 척추 모양을 내는 효과라고 했네요.

12는 일반적인 효과고 -3도 있네요. 이건 어떨까요?

그리고 y 좌표를 20으로 나눠서 그 절대값을 width 로 하는 것도 있네요.

이것도 효과가 어떨지 궁금한데요.


이렇게 수학 공식을 사용하다 보면 아주 좋은 효과들이 나옵니다.

프로그래밍을 하면 할 수록 수학을 배우고 싶은 마음이 마구 생겨납니다.


누가 수학은 배워봤자 사회에서 써 먹을 일이 없다고 그러는지...

이글 보시는 학생분들 계시면 그런 얘기 믿지 마세요.

수학 진짜 필요합니다.


다음은 투명도 효과를 볼까요?


    lines[p].alpha=1 -- Another boring one
    lines[p].alpha=0.5 -- Half strength line
    lines[p].alpha=math.abs((event.y-(1000-event.y))/1000) -- Darker area near the center
    lines[p].alpha=math.abs(event.y/1000) -- Foggy day
    lines[p].alpha=math.abs(event.x/1000) -- Foggy day...to the side?
    lines[p].alpha=(math.random(100, 1000))/1000 -- Random


여러 효과들이 있는데요. 처음에 알파를 1로 설정한 것은 그냥 투명도 없이 진하게 표시하는 겁니다.

0.5는 반쯤 투명하게 하는 거구요. 다음엔 수학공식을 사용해서 여러 효과를 주었네요.

세번째는 호면 중앙으로 올 수록 진해 지는 건가 봅니다.

그 다음은 아래 윗부분으로 갈 수록 연해지는 효과고 그 다음은 좌우로 갈수록 연해지는 효과 입니다.

그 다음은 그냥 랜덤하게 투명도를 주는거네요.

해 봤는데 별 효과는 없습니다. 그냥 무책임한 랜덤일 뿐이네요.


다음은 색 지정부분 입니다.


        --Flat color
        --lines[p]:setColor(255,255,255) -- White
        --lines[p]:setColor(255,255,0) -- Yellow
        --lines[p]:setColor(255,0,0) -- Red
        --lines[p]:setColor(0,255,0) -- Green
        --lines[p]:setColor(0,0,255) -- Blue
        --lines[p]:setColor(255,0,255) -- Purple
       
        --Interesting color effects
        --lines[p]:setColor(math.random(255)) -- Grayscale
        --lines[p]:setColor(math.random(255), math.random(255), math.random(255)) -- Rainbow
        --lines[p]:setColor(event.x/5, event.x-20/5, event.x+20/5) -- Really odd effect...
        --lines[p]:setColor(event.x-event.y, 0, event.x-event.y) -- Pretty cool, works best with slow movement


첫 부분은 그냥 단색으로 흰색,노랑,빨강,초록,파랑,보라 이렇게 선 색이 주어집니다.

그 다음엔 수학 공식을 사용한 효과로 처음엔 흑백화면처럼 라인 색이 나오면서 진해지고 옅어지고의 변화만 있습니다.

그 다음은 랜덤하게 색을 표시하는 거구요. 그 다음엔 진짜 이상한 효과라고 하네요. 한번 해 보세요.

그 다음엔 천천히 움직이면 아주 좋은 효과가 나온다고 합니다.


그 다음에는 아래 for 문도 하나 예제로 주었습니다.


        for i=1, p do
                lines[i].xScale=lines[i].xScale-0.12; lines[i].yScale=lines[i].yScale-0.12
        end


분석해 보니까 선을 그을 때마다 lines[] 배열에 담겨있는 선들의 크기를 조금씩 크게 만드는 거네요.


이것도 괜찮은 효과 입니다.


이 width, alpha, setColor 효과들을 다양하게 조합해 보면 재밌을 거예요.




위 이미지가 그 중 하나입니다.


아래 quinc 가 올린 파일 원본 소개 합니다.



main.lua


반응형


반응형

Posted on . Written by


수요일 FAQ 시간이 다시 돌아 왔습니다. 아래 자주 반복되는 질문 5가지가 있습니다. 오늘은 Event Listeners와 Display Objects를 어떻게 remove 하는지에 대해 알아보겠습니다.


1. I’m confused about when I need to call removeEventListener?


대표적인 경우는 Runtime:addEventListener를 사용해서 이벤트 리스너를 생성했다면 Runtime:removeEventListener를 call 하셔야 합니다. 만약 object event listener를 생성했다면 그 object를 remove 할 때 object event listener도 remove 해야 합니다.


--------------------------
-- Runtime Listener
--------------------------

function myFrame( event )
    print( "enterFrame", event.time )
end

Runtime:addEventListener( "enterFrame", myFrame )

-- Some time later ...
Runtime:removeEventListener( "enterFrame", myFrame )

--------------------------
-- Object Listener
--------------------------

local rect = display.newRect(10, 40, 100, 50)

function rect:touch( event )
    if event.phase == "began" then
        print( "Rect touched", event.target )
    end
end

rect:addEventListener( "touch" )

-- Some time later ...
rect:removeSelf()
rect = nil


 



2. I see code using “self”. What is that?


self 는 루아 메소드의 hidden 파라미터 입니다. 함수를 call 할 때 그 object에 접근하기 위해 사용하죠. 아래에 그 예제가 있습니다.


local rect1 = display.newRect(10, 100, 100, 50)
function rect1.touch( self, event )
    if event.phase == "began" then
        print( "Rect1 touched", event.target, self )
    end
end

rect1:addEventListener( "touch" )


local rect2 = display.newRect(10, 160, 100, 50)
function rect2:touch( event )
    if event.phase == "began" then
print( "Rect2 touched", event.target, self )
    end
end

rect2:addEventListener( "touch" )
 

두 예제의 메소드 모두 제대로 작동합니다. 그런데 하나는 "." 를 사용했고
다른 하나는 ":"를 사용했습니다.

콜른(:)을 사용하면 메소드에 hidden self 파라미터를 전달합니다.
그리고 점(.) 을 사용한 것은 이 self를 전달하지 않습니다.
그러니까 점을 사용하면 반드시 첫번째 파라미터로 self를 전달해야 합니다.

코로나는 다른 많은 Display Object API들에 (e.g., object:removeSelf, object:setFillColor, etc.) 이 Lua 기능을 사용하고 있습니다.


이벤트 리스너와 self 를 사용하는 것은 그렇게 유용하지 않을 겁니다. 왜냐하면 대부분의 object listener들은 객체의 handle을 지원하기 위해  event.target 파라미터를 제공하기 때문이죠. 이 파라미터는 self와 같습니다. 여러분이 만든 메소드에는 이 self를 사용할 수 있을 겁니다. 여러 객체에서 같은 메소드를 call 할 때 아주 유용하겠죠.


3. Do I really need to set display objects to nil after I remove them?


그 객체와 관계된 Lua 메모리를  clean up 하기 위해 사용하지 않는 객체에 nil을 할당해야 합니다. display object를 remove 할 때마다 (object:removeSelf) 그 객체의 texture 메모리와 관련된 메소드 그리고 그 객체와 관련된 이벤트 핸들러들은 remove 될 겁니다.  그렇게 되면 그 객체는 일반적인 Lua 테이블로 됩니다. 여기에 nil을 할당함으로서 그 테이블에 대한 reference 까지 remove 하게 됩니다. 그리고 나서 Lua Garbage Collector에 의해 그 테이블이 사용했던 메모리가 free 됩니다.


4. What is the best way to remove display objects from a Display Group?


display group에서 removeSelf 를 하면 그 그룹의 모든 display object들을 remove 할 겁니다. 그 그룹의 각 객체별로 따로따로 removeSelf  할 필요는 없습니다. group에 있는 객체들을 따로 nil 처리할 필요는 없습니다. 그룹 안에 있는 객체가 다른 변수에 의해 reference 된다면 그 variable을 nil로 세팅해야 합니다.


5. How can I tell if a display object was removed?


display object는 table입니다. 그리고 그것과 연관된 texture memory와 메소드들이 있죠. 그러니까 어떤 display object 메소드가 그 object와 아직까지 연관이 돼 있는지 여부를 체크함으로서 해당 display object가 아직까지 존재하는지를 알아 낼 수가 있습니다.


local rect1 = display.newRect(10, 100, 100, 50)
if type( rect1.setFillColor ) == "function" then
print( "rect is still a display object" )
end


위 예제는 rect1 객체에 setFillColor 메소드를 적용할 수 있는지 여부를 체크하고 있습니다.
어떤 객체에 removeSelf 를 call 하면 그 객체로부터 모든 메소드가 removed 된다는 것을 기억해 두세요.

여기까지가 이번주 QNA 내용이었습니다.

즐거운 주말 되세요.



반응형


반응형
Posted on

. Written by


적어도 50만개가 넘는 앱들이 앱스토어와 구글 플레이에 있습니다. 이러한 수많은 앱들 속에서 아주 좋은 앱일지라도 찾지 못하고 넘어가기가 아주 쉽습니다. 이 앱 시장에서는 마케팅할 수 있는 방법이 아주 제한되어 있고 시간에 제약도 있으니까요. 여러분은 앱을 어떻게 알리고 또 필요한 이용자가 다운로드 받을 수 있도록 할 수 있을까요?

화요일 저녁에 저는 샌프란 시스코의 App discovery event에 참가 했었습니다.  Free App A DayTapjoyAppsfire, 그리고 Iddiction 등에서 연사들이 왔었습니다. 거의 12페이지 가까이 열심히 적었는데요. best app 찾는 방법과 배포하는 방법에 대해 정리한 것을 아주 간략하게 정리해서 공유할께요. 이건 특별한 기준에 의한 정리가 아닌 빙산의 일각일 뿐 이겠죠. 여러분만의 앱 홍보나 마케팅 방법이 있으면 공유해 주세요. 저희는 여러분의 소중한 경험을 듣는 것을 듣고 싶습니다.





1.     Get your app localized. 중국어나 일본어, 독일어, 프랑스어 이탈리아어, 러시아어, 포프투갈어, 인도어 등의 현지어를 추가하는 것은 마케팅 전략상 아주 중요한 부분입니다.


2.     Word of mouth = the best form of marketing.  다른 개발자나 출판물, 혹은 개인 등을 통해서 입에서 입으로 광고 되는 것이 마케팅의 가장 좋은 방법입니다.


3.     Assemble a comprehensive press kit. review 싸이트나 Tech 블로그 같은 곳에서 다뤄지도록 하세요. 앱의 개요나 screenshot, 그리고 사용법을 설명하는 비디오나 promo codes 등을 같이 넣어 주세요. 글을 쓰는 사람들은 특종같은 뭔가 구별되는 것들이 있는 글을 선호합니다. 그러니까 앱이 출시 되기 전에 미리 한번 사용해 봐 달라고 (TestFlight) 하는것도 좋은 방법이겠죠.


4.     Skip paying for services if you get featured by Apple.  우선 jackpot을 터트린 것을 축하드립니다. 두번째로 마케팅이나 publishing services 등등 에 낭비하지 마세요.  일반적으로 애플 친화적이고 애플 앱스토어에 올리시면 더 많은 다운로드를 기록 하실 수 있습니다.


5.     Generate buzz by dropping price. 특정기간 앱 가격 할인 행사를 하는 것은 소문을 내고 다운로드를 늘리는 좋은 방법입니다.


6.     Get on Apple’s radar by uploading screenshots to TouchArcade’s forum.   애플 앱 reviewer들은 일반적으로 이 포럼(TouchArcade’s forum)을 체크합니다. 블로거들도 마찬가지구요. 그러니까 이 포럼에 screenshots들을 업로드 하세요.


7.     Build analytics into your app. 이건 여러분 유저에게 actionable intelligence를 얻도록 하는 아주 필수적인 사항입니다. 앱에 analytics를 넣으세요.


8.     Get creative and optimize for less popular keywords.  예를 들어 가장 자주 검색되는 단어들 중 하나는 "free" 입니다. 이 단어로 검색되는 그 수많은 앱들과 경쟁하기를 원하지는 않을 겁니다. 그러니까 창조적이고 앱에 딱 맞고 사용자들의 검색에 잘 걸릴 수 있는 여러분의 홍보 키워드를 만드세요.


9.     Most discovery and distribution happens in the “free” category.  많은 개발자들이 자신들이 만든 앱의 free 버전과 유료 버전 두가지를 만들죠. 보다 홍보가 많이 되도록요. 왜냐하면 free 카테고리에 있는 앱들은 유저들이 더 많이 찾아보거든요.


10.  Combine your marketing channels. Facebook, Twitter, Google+, blog posts 나 여러분의 앱을 홍보할 수 있는 다른 활자화된 홍보수단을 총 동원해서 활용하세요.





반응형


반응형
Posted on . Written by


수요일 FAQ 시간입니다. 이번주는 Mac Simulator와 native text objects들의 displaying fonts에 대한 다섯가지 질문을 다루겠습니다.


1. How can I keep the (Mac) Simulator window from resizing when I relaunch my app?


Daily Build 883에 새로 시작할 때 디바이스 윈도우를 resizing에 대해 Mac 시뮬레이터의 크기를 유지하는 옵션이 들어갔습니다.  Corona Simulator/Preferences… 로 가서  “Automatically scale simulator to fit screen.”의 선택을 해제 하세요.







2. Why does my app start up in a (Mac) Simulator with a window that is larger than my display?


작은 display들에 큰 디바이스 윈도우 (iPad나 iPad Retina 같은) 를 display 할 떄 맥 시뮬레이터는 relaunch 된 이후에 zoom을 하는 경우가 있습니다. 그래서 실제 스크린크기보다도 더 큰 device window가 나오기도 합니다. Zooming out(Cmd-) 는 display back을 합니다. 새로 zoom out된 것을 재 조정했다고 하더라도 다음번에 relaunch 하게 되면 똑 같은 현상이 일어납니다.


build 883 에서 이 부분에 대해 수정했습니다. 스크린에 맞게 조정할 뿐만 아니라 이전에 유저가 zoom 했던 세팅을 기억해서 다음에 relaunch 할 때 시뮬레이터의 위치와 zoom level을 유지하도록 합니다.


또한 Window 메뉴에 center 라는 옵션을 추가했습니다. 이 옵션을 추가하면 현재 display window의 중심에 위치 시키게 됩니다. 만약 여러분이 여러 디스플레이를 사용한다면 아주 유용할 겁니다. display를 바꾸게 되면 화면 밖으로 나가게 되는 경우도 있죠. 이 기능에 대한 hot key 는 Shift Cmd UpArrow 입니다.


맥 시뮬레이터에는 또 다른 기능이 추가 됐는데요. 디바이스의 테두리를 없앨 수 있습니다.

디바이스 창의 테두리를 없애면 더 여유로운 screen 공간을 사용할 수 있고 스크린에 딱 맞는 디바이스 창을 더 수월하게 해 줍니다. 이 기능은 특히 큰 태블릿 디바이스를 display 할 때 유용합니다.

Corona Simulator/Preferences…로 가셔서 “Display device border (takes effect on next simulator relaunch”를 체크하세요. 말씀드렸듯이 바뀐 기능을 적용하려면 시뮬레이터를 재시작(Cmd r) 하시면 됩니다.


3. Why does the Mac Simulator keep crashing on Mountain Lion (10.8) when I relaunch my app a few times?


맥 시뮬레이터에서 약간의 메모리 누수를 찾았는데요. 여러분이 앱을 relaunch 할 때마다 발생하더라구요. 여러분 시스템의 메모리 여유가 별로 없다면 그리고 앱의 relaunch를 자주 하다보면 시뮬레이터가 crash를 일으 킬 수 있습니다. simulator가 close 되면 누수된 메모리가 다시 해제 됩니다. 이 이슈는 Lion (10.7) 에서도 발생하는데요. 10.8 버전에서는 더 많은 메모리를 사용하는데요 그래서 이러한 일들이 10.8 시스템에서 더 많이 보고 됩니다.


좋은 소식은 daily build 883에서 이 에러를 수정했다는 겁니다. 이 버그는 애플의 Image Kit code 내의 internal bug 때문에 일어난다는 원인을 발견했고 이 문제를 해결하기 위해 애플의 기능이 아는 우리의 routine들을 사용하도록 고쳤습니다. (애플에 bug report 도 했습니다.)


조만간에 public release 에서도 이 수정된 사항이 적용되도록 하겠습니다.


4. Why don’t the fonts in native TextFields and TextBoxes scale correctly on different devices?


config.lua 에서 dynamic scaling을 enable 하면 코로나는 모든 vector, 이미지 그리고 native 객체들을 scale 해서 현재 display에 맞게 맞출 겁니다. 이때 scale 하지 않는 것들은 native.newTextFieldnative.newTextBox에서 사용하는 폰트들입니다. 폰트를 scaling 하게 되면 다른 display 객체들의 scaling이 제대로 작동 안할 때도 있습니다. 각 폰트들 마다 차지하는 공간들이 다르기 때문에 이런 일들이 발생하는데요. native 텍스트 필드에서 폰트를 scale 하려면 여러분이 사용하는 폰트가 있는 코드 부분에서 하셔야 합니다.


여러분이 네이티브 텍스트 필드에 14 포인트의 폰트를 지정했다면 그 텍스트는 scaling facor와 관계 없이 모든 디바이스에서 14 포인트로 display 될 겁니다.

이러한 현상은 오직 native text object에만 해당됩니다. display.newText를 사용한 폰트는 bit 이미지로 랜더링 되기 때문에 제대로 scaling 됩니다.


5. Why don’t the fonts in native TextFields and TextBox scale correctly in the Simulator?


시뮬레이터에서도 4번과 비슷한 현상이 발생하는데요. 시뮬레이터는 zoom in, zoom out을 할 수 있고 시뮬레이션 되는 디바이스를 바꿀 수 있습니다. 하지만 native text object의 폰트 사이즈는 언제나 같습니다. 그러니까 14포인트의 폰트는 zoom level 과 관계없이 항상 14 포인트로 보이게 되는 것이죠. 실제 디바이스에서 display.newText로 생성된 텍스트는 제대로 scale 될 겁니다.



여기까지가 오늘의 FAQ 입니다.

유익한 시간이셨기를 바랍니다.



반응형


반응형
Posted on . Written by


또 다시 돌아왔습니다. FAQ 시간 입니다. 아래 자주 나오는 질문 5가지가 있습니다. 오늘은 Display object를 Lisener로 pass 하는 방법과 off-line에서 CoronaSDK document에 접근하는 방법에 대해 얘기하겠습니다.



1. How can I access the display object in the “transition.to” listener?

"tween" 이 finish 할 때 call 되는 리스너 함수로 transition.to과 transiditon.from 파라미터가 있습니다. 

리스너에 보내지는 파라미터는 transition에 의해 콘트롤 되는 Display Object(target)의 reference 입니다. 이것은 여러분에게 multiple transition들에 대해 일반적인 리스너를 이용할 수 있도록 해 줍니다.


local square = display.newRect( 0, 0, 100, 100 )
local w,h = display.contentWidth, display.contentHeight


local function listener1( target )
        print( "Transition 1 completed on object: " .. tostring( target ), target.x, target.y )
end


transition.to( square, { time=1500, alpha=0, x=(w-50), y=(h-50), onComplete=listener1 } )



Note 제가 onComplete=listener1()를 사용하지 않고 onComplete=listener1를 사용했죠? 둘 이 다른 점은 onComplete=listener1는 리스너의 함수에 레퍼런스를 passing 한다는 겁니다. onComplete=listener1()는 리스너를 initialization 할 때 call 하죠 그리고 transition (화면전환)이 끝났을 때 call 되는 함수처럼 리스너로부터 return 되는 것을 사용합니다.


2. I need to cancel the “transition” for multiple display objects. Is there an easy way to find the transition ID for each object?


transition을 cancel 하려면 transition.cancel을 call 해야 되요 이때 transition ID로 call 해야 됩니다. 이 transition ID는 transition이 처음 생성될 때 return 됩니다. 이 ID는 어딘가에 저장해 놔야 됩니다. 로컬 변수나 테이블에 저장할 수 있겠죠.


그런데 더 쉬운 그리고 더 편한 방법은 그 객체 자체에 attach 하는 겁니다. 코로나에서는 display object에 custom property들을 추가 할 수 있는 기능을 제공합니다. transitionID라는 custom property를 만들어서 여기에 저장하면 좋습니다.


저는  display의 이름을 저장하는데도 사용합니다. 그러면 디버깅할 때도 편리합니다. (e.g., object.name).

아래 transitionID를 어떻게 저장하는지 보여주는 예제가 있습니다



local square = display.newRect( 0, 0, 100, 100 )
local w,h = display.contentWidth, display.contentHeight


local function listener1( target )
        print( "Transition 1 completed on object: " .. tostring( target ), target.x, target.y )
end


square.transitionID = transition.to( square, { time=3000, alpha=0, x=(w-50), y=(h-50), onComplete=listener1 } )
timer.performWithDelay( 1500, function() transition.cancel( square.transitionID ) end )



위 코드는 transition 이 반쯤 됐을 때 cancel 하는 timer 함수를 추가했습니다. 나머지는 첫번째 예제와 비슷하고 움직이죠. 여기서는 이 transition을 cancel 하기 위해 필요한 ID를 save 하기위해 square.transitionID를 사용했습니다.



3. How can I pass the display object to a function when I’m using “timer.performWithDelay”?


비슷한 질문에 대한 대답을 FAQ #3에서 했었습니다만 어떻게 Display Object를 listener로 pass 하는지에 대해 보여 드리겠습니다.

timer.performWithDelay는 보통 listener의 address(reference)와 함께 call 됩니다. 그러니까 delay가 finish 된 후에 call 될 수가 있죠. 

여기서 함수가 call 됐을 때 pass 되는 display object에 대한 reference를 hold 할 로컬 변수를 생성하기 위해 루아의 closures를 사용할 수 있습니다. 아래 그 예제가 있습니다.



local rect = display.newRect( 0, 0, 100, 100 )


local function timerListener( object )
    return function()
        print( "Rect x,y = ", object.x, object.y )
    end
end


timer.performWithDelay( 1000, timerListener( rect ) )



timerListener “listener”는 함수에 대한 reference 대신에 call 되는 함수 입니다. 이 함수를 call 하는것은 저장된 object 변수에 접근할 수 있는 anonymous 함수의 reference를 return 하도록 합니다. 그 object는 timerListener에 pass 됩니다. 그 시기는 timer가 첫번째로 initialized 될 때이고 return 된 anonymous 함수는 delay time이 종료 된 이후에 call 된 함수처럼 사용 됩니다.

오직 한 객체에 대해서만 리스너를 사용할 거라면 이 방법은 그리 유용하지 않을 겁니다. 이 기능의 장점은 리스너가 많은 객체들을 다룰 때 그 진가가 나타날 겁니다. 그 리스너는 deplay object에만이 아니라 테이블, 스트링 그리고 number에도 적용 됩니다.


4. I’m confused about what parameters are available in event listeners.


리스너에 보내지는 이벤트 파라미터가 무엇인지 이해하시려면 CoronaSDK documentation를 참조하세요.  그리고 리스너에 어떤것이 pass 되는지도 확인하세요. event 정보는 파라미터들의 table 입니다. 이 table을 dump 하는 간단한 예제가 이것을 이해하는데 그리고 디버깅 하는데 도움을 드릴 겁니다. 아래 제가 찾아낸 유용한 디버그 코드가 있습니다. 어떻게 동작하는지 보여주기 위해 touch 리스너를 사용했습니다.



local function touchListener( event )
--- Debug Event parameters printout --------------------------------------------------
print();print( "Listener events:" )
for k,v in pairs( event ) do
print( " " .. tostring( k ) .. "(" .. tostring( v ) .. ")" )
end
--- End of debug Event routine -------------------------------------------------------
return true
end
Runtime:addEventListener( "touch", touchListener )


아래가 스크린을 touch 했을 때 화면에 출력되는 event 파라미터들입니다.


Listener events:
y(66)
x(193)
time(84950.623)
id(userdata: 0x1000df3e0)
phase(began)
yStart(66)
xStart(193)
name(touch)
Listener events:
y(68)
x(193)
time(86388.318)
id(userdata: 0x1000df3e0)
phase(moved)
yStart(66)
xStart(193)
name(touch)
Listener events:
y(68)
x(193)
time(86746.278)
id(userdata: 0x1000df3e0)
phase(ended)
yStart(66)
xStart(193)
name(touch)


5. Sometimes I don’t have an Internet connection. Is there a way to access CoronaSDK documentation off-line?


만약 질문자께서 CoronaSDK subscriber라면 Daily Build page 로 가면 off-line 버전 CoronaSDK API document를 다운 방으실 수 있습니다. CoronaApiDocs file 각 daily build 마다 하나씩 가지고 있습니다. 다운받아서 여러분 컴퓨터에 unzip 하시기만 하면 됩니다. api 폴더를 열고 index.html을 double click을 하세요. 그러면 브라우저에 CoronaAPI document가 열릴겁니다.





여기까지가 오늘의 questions 입니다. 유익한 시간이셨기를 바랍니다.



반응형


반응형
Posted on

. Written by


수요일입니다. 수요일의 FAQ 시간이죠. 아래에 자주 질문되는 (FAQ)것들에 대한 답변들이 있습니다.


1. Is CoronSDK 840 (Release) compatible with Mountain Lion?


예 2012.840 버전은 OSX 10.8 (Mountain Lion) 에서 잘 작동합니다. Mac Simulater가 unsigned 인 상황에서는 신뢰할 수 없는 문제가 발생했고 프로그램이 작동하지 않을 거라는 메세지를 보실겁니다. 이럴 때는 앱을 작동시키기 위해서 Gatekeeper 안에 security 세팅을 하셔야 합니다. System Preferences/Security & Privacy/General로 가세요. 그리고 Anywhere 옵션을 클릭하세요.



한번 퍼미션을 세팅해 두고 CoronaSDK가 한번 실행하고 나면 여러분은 다시 돌아가셔서 여러분의 시스템을 보호하기 위해 다시 reset 하실 수 있습니다. 이 이슈가 현재 release 된 버전에 있는 유일한 이슈입니다. 지금 현재 나와있는 daily builds를 사용하시면 이 과정도 필요없고 아무런 문제 없이 사용하실 겁니다.


2. Does CoronaSDK work with the new MacBook Retina?


코로나 SDK는 new retina display 에서 잘 작동을 하지만 low resolution 모드라야 합니다. 이 모드는 현재 daily builds 버전 (2012.865 이후 버전)에서는 세팅돼 있지만 2012.840 버전에서는 여러분이 세팅을 하셔야 합니다.

이 release build 버전을 사용하시고 low resolution으로 모드가 세팅돼 있지 않다면 text가 있어야 할 자리에 black block이 나타나는 것 같은 여러 display 문제들을 보실 수 있을 겁니다.

CoronaSDK에서 이 모드를 세팅하시려면 Finder app을 사용하셔서 CoronaSDK 폴더로 가 주세요. Corona Simulator.app을 마우스 오른쪽 클릭을 하시고 (Corona Terminal 이 아님) Get Info를 선택해 주세요. 그리고 Open in Low Resolution 옵션을 선택해 주시면 됩니다.


3. What build can I use to build for an older iOS (e.g, iOS 3.1.3)?


현재의 release (840) 버전은 iOS 4.3 대 버전만 지원합니다. 그 이유는 애플이 다른 IOS 버전의 지원을 중단했기 때문이죠. 여러분 앱의 최신 CoronaSDK를 필요로 하지 않으면 2012.704b 버전을 다운받아서 사용하세요. 이것은 Daily Build 페이지에 있는데 유료 등록자로 로그인을 해야지 접근 하실 수 있습니다. 이것은 iOS 3.1에서 5.1 버전 까지 지원하는 SDK입니다. 그러니까 iPad Retina 까지 지원되죠. 2012.704a 는 iPad Retina를 지원하지 않습니다.


4. Why don’t I see any errors when I run the Mac Simulator?


시뮬레이터를 돌릴때 터미널에는 에러나 wornings 그리고 print messages들이 보여집니다 윈도우즈에서는 시뮬레이터를 실행하면 터미널이 자동으로 open 됩니다. 맥에서는 Corona Terminal을 따로 오픈해야 합니다. Corona Simulator.app 이 아닙니다. 두 프로그램 모두다 CoronaSDK 폴더에 있습니다. 여러분이 coronaSDK를 인스톨 할 때 그 폴더는 Application 폴더 아래에 위치하게 됐을 겁니다.


여러분이 Corona Terminal을 시작하면 Terminal window가 열리고 Corona Simulator가 시작합니다. Corona Simulator 앱만 running  하는 것은 그냥 앱이 동작하는 것을 보이기만 하고 터미널에 뜨는 정보들이 필요 없는 경우에 유용할 겁니다.


Mac CoronaSDK와 관련된 팁을 하나 알려드리자면 여러분은 여러개의 인스톨 된 CoronaSDK 카피들을 가질 수 있습니다. 시스템에서 코로나가 running 할 때도요. 아마 build 버전 840 과 현재 daily build 버전을 여러분 맥 컴퓨터에 인스톨 할 수 있습니다. 이렇게 하면 여러 버전의 코로나로 테스트 할 수 있겠죠. 새로운 Mac CoronaSDK를 다운로드 받아서 인스톨 할 때마다 저는 CoronaSDK 폴더에 build number를 추가합니다. 그러니까 release build 인 경우에는 CoronaSDK를 CoronaSDK-840 으로 이름을 바꾸죠. 여러분 시스템에서 running 하는 모든 CoronsSDK 들은 같은 preference file들을 공유합니다. 그러니까 최근의 히스토리와 preferences 세팅이 모든 버전에 apply 될 겁니다.


5. What are the keyboard shortcuts for the Simulator?


맥이나 윈도우지 시뮬레이터 모두 다양한 키보드 shortcut들이 있습니다. 여기 제가 찾은 유용한 shortcut들이 있습니다. 윈도우즈에서는 control 키를 누르고 Mac 에서는 command 키를 누르고 아래 키들을 눌러 보세요.


R               Relaunch the simulator with the current project
O               Open an existing project
B               iOS Build window
Shift B         Android Build window
+               Zoom In (makes the "skin" larger)
-               Zoom Out (makes the "skin" smaller)
Left arrow      Rotate the "skin" left
Right arrow     Rotate the "skin" right
Up arrow        Simulate device "shake"
Down arrow      Suspend/Resume simulator



여기까지가 오늘의 질문과 답변들입니다. 유익한 시간이었기를 바랍니다.



반응형


반응형
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 에 사용합니다.)


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



반응형

수요일의 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

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

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



반응형
이전 1 2 3 4 5 6 ··· 8 다음