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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리

JQuery Mobile 훑어 보기

2012. 4. 30. 10:19 | Posted by 솔웅


반응형

제가 이번에 새로 가게되는 회사는 Kurogo와 JQuery Mobile 을 기반으로 개발한다고 하네요.

JQuery Mobile 보다는 Sencha Touch 쪽으로 공부를 해 왔는데..

일단 JQuery Mobile 쪽으로 Focus를 좀 맞춰야 겠습니다.


JQuery Mobile을 소개하는 파워포인트가 있어서 그 문서를 한번 훑어 보겠습니다.

원본은 여기에 있습니다.


JQuery Mobile Framework 소개


Mark Dalgleish - @markdalgleish


* JQuery Mobile 이란?

  • JQuery를 사용하는 Mobile framework (obviously).
  • 강력한 cross-browser, cross-platform.
  • Native 와 유사한 웹 앱 생성
  • 마크업 기반 코딩, 최소화 한 코딩 
  • Focused on progressive enhancement, graceful degradation.

* Target Platform

  • iOS, Android, Windows Mobile
  • Blackberry, Symbian, webOS
  • Firefox Mobile (Fennec), Opera Mobile / Mini
  • Meego, bada, Maemo...
  • Phonegap!

* Basic Page Elements

  • data-role 어트리뷰트와 DIV를 사용해 정의하는 Custom elements 
  • 최소한 하나의 data-role="page" element 필요
  • 페이지 안에 최소 한개의 data-role = "content" 엘리먼트 필요 
  • 클래스들은 자동적으로 추가 됨 
  • Form elements 와 lists 들은 자동적으로 업데이트가 적용 됨

* Basic Page Markup

<!doctype html>
<html>
 
<head>
 
<title>Page Title</title>
 
<link rel="stylesheet" href="jquery.mobile.css" />
 
<script src="jquery.js"></script>
 
<script src="jquery.mobile.js"></script>
</head>
<body>
<div data-role="page">
 
<div data-role="header">
   
<h1>Page Title</h1>
 
</div>
 
<div data-role="content">  
   
<p>Page content goes here.</p>    
 
</div>
 
<div data-role="footer">
   
<h4>Page Footer</h4>
 
</div>
</div>
</body>
</html>



* Virtual Pages

<div data-role="page" id="page1">
 
<div data-role="header">
   
<h1>Page 1</h1>
 
</div>
 
<div data-role="content">
   
<a href="#page2" data-role="button">Go to Page 2</a>
 
</div>
</div>

<div data-role="page" id="page2">
 
<div data-role="header">
   
<h1>Page 2</h1>
 
</div>
 
<div data-role="content">
   
<a href="#page1" data-role="button">Go to Page 1</a>  
 
</div>
</div>


* Separate Pages with AJAX Loading
<div data-role="page">
 
<div data-role="header">
   
<h1>Page 1</h1>
 
</div>
 
<div data-role="content">
   
<a href="page2.html" data-role="button">Go to Page 2</a>
 
</div>
</div>


* Fixed Footer Navigation

<div data-role="footer" data-id="myfooter" data-position="fixed">
 
<div data-role="navbar">
   
<ul>
     
<li><a href="footer.html" class="ui-btn-active">One</a></li>
     
<li><a href="footer2.html">Two</a></li>
     
<li><a href="footer3.html">Three</a></li>
   
</ul>
 
</div>
</div>

// Second page
<div data-role="footer" data-id="myfooter" data-position="fixed">
 
<div data-role="navbar">
   
<ul>
     
<li><a href="footer.html">One</a></li>
     
<li><a href="footer2.html" class="ui-btn-active">Two</a></li>
     
<li><a href="footer3.html">Three</a></li>
   
</ul>
 
</div>
</div>

// Third page
<div data-role="footer" data-id="myfooter" data-position="fixed">
 
<div data-role="navbar">
   
<ul>
     
<li><a href="footer.html">One</a></li>
     
<li><a href="footer2.html">Two</a></li>
     
<li><a href="footer3.html" class="ui-btn-active">Three</a></li>
   
</ul>
 
</div>
</div>


* AJAX Loading In Depth

  • 모든 페이지가 JQuery Mobile 표준에 맞아야 한다.
  • AJAX를 지원하려면 transition과 함께 DOM에 맞게 페이지들이 구성되어야 한다. 그렇지 않으면 일반 페이지가 로드된다.
  • 페이지 로드가 실패하면 유저는 friendly 한 에러메세지를 받게 된다.
  • 같은 도메인의 모바일페이지가 아닌 페이지로 링크할 때는 rel="external"을 이용한다.
  • 다른 도메인으로 링크되는것은 자동적으로 감지되고 일반적인 로드와 동일하게 작업을 수행한다. 


* Form Elements

  • 일반적인 Form element들은 모바일 usability에 따라 자동적으로 그에 맞게끔 적용된다. 
  • 모든 컨트롤들은 Native와 마찬가지로  gracefully degrade 된다.
  • 디폴트 세팅은 필요하면개발자가 바꿀 수 있다.



* Form Element Markup


<div data-role="fieldcontain"> 
 
<label for="textbox">Textbox:</label>
 
<input type="text" name="textbox" id="textbox" value=""  />
</div>

<div data-role="fieldcontain">
 
<label for="textarea">Textarea:</label>
 
<textarea name="textarea" id="textarea" value=""></textarea>
</div>

<div data-role="fieldcontain">
 
<label for="search">Search:</label>
 
<input type="search" name="search" id="search" value=""  />
</div>

<div data-role="fieldcontain">
 
<label for="slider">Slider:</label>
 
<select name="slider" id="slider" data-role="slider">
   
<option value="0">Off</option>
   
<option value="1">On</option>
 
</select>
</div>

<div data-role="fieldcontain">
 
<label for="range">Range:</label>
 
<input type="range" name="range" value="0" min="0" max="10" />
</div>

<div data-role="fieldcontain">
 
<fieldset data-role="controlgroup">
   
<legend>Checklist:</legend>
   
<input type="checkbox" name="checkbox1" id="checkbox1" />
   
<label for="checkbox1">HTML</label>

   
<input type="checkbox" name="checkbox2" id="checkbox2" />
   
<label for="checkbox2">CSS</label>

   
<input type="checkbox" name="checkbox3" id="checkbox3" />
   
<label for="checkbox3">JavaScript</label>
 
</fieldset>
</div>

<div data-role="fieldcontain">
 
<fieldset data-role="controlgroup" data-type="horizontal">
   
<legend>Horizontal Checklist:</legend>
   
<input type="checkbox" name="checkbox4" id="checkbox4" />
   
<label for="checkbox4">Tea</label>

   
<input type="checkbox" name="checkbox5" id="checkbox5" />
   
<label for="checkbox5">Coffee</label>
 
</fieldset>
</div>

<div data-role="fieldcontain">
 
<fieldset data-role="controlgroup">
   
<legend>Radio Buttons:</legend>
     
<input type="radio" name="radio1" id="radio1a" value="a" />
     
<label for="radio1a">HTML5</label>

     
<input type="radio" name="radio1" id="radio1b" value="b" />
     
<label for="radio1b">Flash</label>

     
<input type="radio" name="radio1" id="radio1c" value="c" />
     
<label for="radio1c">Silverlight</label>
 
</fieldset>
</div>

<div data-role="fieldcontain">
 
<fieldset data-role="controlgroup" data-type="horizontal">
   
<legend>Horizontal Radio Buttons:</legend>
     
<input type="radio" name="radio2" id="radio2a" value="a" />
     
<label for="radio2a">Tea</label>

     
<input type="radio" name="radio2" id="radio2b" value="b" />
     
<label for="radio2b">Coffee</label>
 
</fieldset>
</div>

<div data-role="fieldcontain">
 
<label for="select1" class="select">Standard Select:</label>
 
<select name="select1" id="select1">
   
<option value="1">HTML5</option>
   
<option value="2">Flash</option>
   
<option value="3">Silverlight</option>
 
</select>
</div>

<div data-role="fieldcontain">
 
<label for="select2" class="select">Custom Select:</label>
 
<select name="select2" id="select2" data-native-menu="false">
   
<option value="1">HTML5</option>
   
<option value="2">Flash</option>
   
<option value="3">Silverlight</option>
 
</select>
</div>

<button name="button" name="button">Button</button>
<button type="submit" name="submit">Submit</button>


* List View Markup

<h4>Basic List View</h4>

<ul data-role="listview" data-inset="true">
 
<li>HTML</li>
 
<li>JavaScript</li>
 
<li>CSS</li>
</ul>

<h4>Linked List View</h4>

<ul data-role="listview" data-inset="true">
 
<li><a href="target.html">HTML</a></li>
 
<li><a href="target.html">JavaScript</a></li>
 
<li><a href="target.html">CSS</a></li>
</ul>

<h4>Ordered List View</h4>

<ol data-role="listview" data-inset="true">
 
<li><a href="target.html">HTML</a></li>
 
<li><a href="target.html">JavaScript</a></li>
 
<li><a href="target.html">CSS</a></li>
</ol>

<h4>Nested List View</h4>

<ul data-role="listview" data-inset="true">
 
<li>
    iOS
   
<ul data-role="listview" data-inset="true">
     
<li><a href="target.html">v2.2.1</a></li>
     
<li><a href="target.html">v3.1.3, v3.2</a></li>
     
<li><a href="target.html">v4.0</a></li>
   
</ul>
 
</li>
 
<li>
    Android
   
<ul data-role="listview" data-inset="true">
     
<li><a href="target.html">v1.5, v1.6</a></li>
     
<li><a href="target.html">v2.1</a></li>
     
<li><a href="target.html">v2.2</a></li>
   
</ul>
 
</li>
 
<li>
    Windows Mobile
   
<ul data-role="listview" data-inset="true">
     
<li><a href="target.html">v6.1</a></li>
     
<li><a href="target.html">v6.5.1</a></li>
     
<li><a href="target.html">v7.0</a></li>
   
</ul>
 
</li>
</ul>

<h4>Searchable List View</h4>

<ul data-role="listview" data-inset="true" data-filter="true">
 
<li><a href="target.html">HTML</a></li>
 
<li><a href="target.html">JavaScript</a></li>
 
<li><a href="target.html">CSS</a></li>
</ul>

<h4>Split Button List View</h4>

<ul data-role="listview" data-inset="true">
 
<li>
   
<a href="target.html">HTML</a>
   
<a href="options.html" data-icon="gear">Options</a>
 
</li>
 
<li>
   
<a href="target.html">JavaScript</a>
   
<a href="options.html" data-icon="gear">Options</a>
 
</li>
 
<li>
   
<a href="target.html">CSS</a>
   
<a href="options.html" data-icon="gear">Options</a>
 
</li>
</ul>

<h4>Thumbnail List View</h4>

<ul data-role="listview">
 
<li>
   
<a href="target.html">
     
<img src="thumbnail1.jpg" />
     
<h3>Miles Davis</h3>
     
<p>Kind of Blue<p>
   
</a>
 
</li>
 
<li>
   
<a href="target.html">
     
<img src="thumbnail2.jpg" />
     
<h3>Cannonball Adderley</h3>
     
<p>Somethin' Else</p>
   
</a>
 
</li>
 
<li>
   
<a href="target.html">
     
<img src="thumbnail3.jpg" />
     
<h3>Charles Mingus</h3>
     
<p>The Black Saint and the Sinner Lady</p>
   
</a>
 
</li>
</ul>


* So where's the JavaScript?

Oh yeah, I almost forgot.


* New Events

  • User events: tap, taphold, swipe, swipeleft, swiperight, orientationchange, scrollstart, scrollstop.
  • Page events: pagebeforeshow, pagebeforehide, pageshow, pagehide.
  • $(document).ready()?: pagebeforecreate, pagecreate.

* New Functions!

  • $.mobile.changePage(options)
  • $.fn.listview(), $.fn.selectmenu() etc...
  • $.fn.listview('refresh'), $.fn.selectmenu('refresh') etc...
  • $.fn.jqmData(), $.fn.jqmRemoveData(), and $.fn.jqmHasData()
  • $.mobile.pageLoading(bool)
    Show or, if bool is false, hide loading indicator.
  • $.mobile.silentScroll(y)
  • $.mobile.media() - Run cross-browser media queries!

* Responsive Layout HTML Classes

  • .portrait and .landscape classes.
  • .min-width-x and .max-width-x classes
    (x == 320, 480, 768 and 1024)
  • Create custom width breakpoints with $.mobile.addResolutionBreakpoints()

* Now What?



* 만약 관심이 있으시면...

======= o ====== o ======= o ======= o ======


나름대로 성의있게 잘 정리된 문서 같습니다.

이 문서를 보고 그 다음에 JQuery Mobile 웹사이트에 가서 DOC를 훑어보고 출근해야겠습니다.

앞으로 JQuery Mobile 관련 글들을 많이 올리게 될 것 같네요.


반응형

Grace Church in Nutley (Episcopal)

2012. 4. 30. 07:55 | Posted by 솔웅


반응형

회사를 옮기게 되서 Rhod Island 로 이사가게 됐습니다.

이삿짐 싸고 이사 준비하고 또 새 직장에서 할 일들 준비하고 하느라 정신이 없네요.


오늘은 그동안 다니던 교회를 마지막으로 다녀왔어요.

저는 성공회 신자라서 성공회 교회를 다녔는데요. 교회는 Grace Church in Nutley 입니다.


오늘은 이 교회에서 아주 특이한 행사를 했어요.


가죽 잠바입고 근사한 오토바이를 타는 오토바이 족들을 위한 교회 행사예요.






이 오토바이 가지고 나오신 분들은 다들 40~50 대들 되는거 같애요.

교회에서 이런 행사를 지원하는게 신기하더라구요.


오토바이 가져 오신 분들은 15불씩 Donation 하고 이 행사에 참가하나봐요.

그리고 일반인들이 10불씩 내고 저 오토바이 뒤에 타고 '오빠 달려~~' 할 수 있구요.


교회 잔디밭에는 바베큐 구이도 하고 있었어요.


저는 이사준비를 해야 되서 이 행사에 참석하지는 못하고 이렇게 사진만 몇장 찍고 왔습니다.


저는 5월 10일에 이사가는데 회사에서는 5월 1일부터 출근하라고 해서 그동안은 모텔에서 지내야 합니다.


여러모로 경황이 없어서 한동안 블로그 활동을 잘 할 수 있을지 모르겠네요.

10일에 이사가서 그 다음날 정도에 인터넷이 깔릴테니까 그때나 글을 올릴 수 있을 것 같습니다.


그럼 그때 다시 뵙겠습니다.

반응형


반응형

오늘은 Dallas 지역에서 Corona SDK 명예대사로 활동하고 있는 Charles McKeever 의 글을 소개 합니다.


==== o ==== o ==== o ====


I’m Now A Corona SDK Ambassador

I have great news to share with you. I’m pleased to announce that I am now a Corona SDK Ambassador. What that means to you is that you’ll be hearing a lot more about mobile development on Open Source Marketer and I’ll be letting you know about upcoming Corona SDK events in the Dallas area.

여러분에게 좋은 소식을 알려드립니다. 제가 코로나 SDK 명예대사가 됐다는 것을 알려드리게 되서 기쁩니다. 여러분 이 의미는 뭐냐 하면 여러분들은 오픈 소스 마케터의 모바일 개발에 대한 훨씬 더 많은 소식을 들을 수 있게 될것이며 달라스 지역에 코로나 SDK 이벤트(모임)을 열것이라는 것입니다.

What is the Corona SDK?

Well, essentially Mobile development is clearly the future of computing and it’s where the eyeballs are going. The Corona SDK makes it possible to rapidly prototype and develop mobile apps on iOS, Android, Nook, and Kindle devices without needing to learn a complicated programming language. That means you can spend more time being creative.

기본적으로 모바일 개발은 확실히 컴퓨팅의 미래입니다. 그리고 여러분들도 많은 관심이 있으실 겁니다. 코로나 SDK는 이것을 훨씬 앞당길 수 있는 툴입니다. 코로나는 iOS, 안드로이드, Nook, Kindle Fire 등의 그 복잡한 프로그래밍 언어를 배울 필요없이 간단하게 개발할 수 있도록 합니다. 이 말은 곧 모바일 앱을 개발하면서 여러분은 좀 더 창조적인 생각을 하는데 시간을 더 투자할 수 있다는 얘기입니다.





Last year I joined the Corona community after doing a lot of research on how to develop mobile applications for iOS, Kindle, and Android devices. Ansca Mobile’s Corona SDK was the most attractive solution I found because it uses the Lua programming language which shares a lot the the same syntax and programming style as PHP and JavaScript does, while still maintaining a high level of user experience for the end user. As a WordPress developer, the Corona SDK has allowed me to enter the mobile space without needing to completely retrain or retool. I’m able to reference Ansca Mobile’s documentation during development and use the same development tool that I’m already comfortable using.

저는 작년에 iOS, Kindle Fire, 안드로이드 디바이스를 위한 모바일 앱 개발을 어떻게 할 것인가를 많이 연구한 끝에 코로나 커뮤니티에 가입하게 됐었습니다. Ansca Mobile의 코로나 SDK는 제가 찾은 방법중에 가장 매력적인 것이었습니다. 왜냐하면 이 툴은 Lua 프로그래밍 언어를 사용해 PHP나 JavaScript와 거의 유사한 신택스를 가지고 있고 아주 높은 수준의 user experience를 제공하는 기능이 풍부했습니다. WordPress developer 처럼 코로나 SDK는 저를 뭔가 새로운것을 많이 배우지 않아도 모바일 세계에 입문할 수 있도록 도와 주었습니다. 개발하는 동안 Ansca Mobile의 튜토리얼을 참조할 수 있었고 이미 사용했던 다른 익숙한 툴처럼 이 툴을 사용할 수 있었습니다.

So what does it mean to be a Corona SDK Ambassador?

To me being a Corona SDK Ambassador means that I’ll be doing my part to help promote the Corona SDK and build a strong community of both mobile developers and non-techies. I believe anyone can be a creative person with great ideas and the Corona Community will help connect story tellers, writers, artists, programmers, business types, and others together so we can all use our individual skills to create great things together.

저에게 Corona SDK 명예대사가 된다는 의미는 제가 Corona SDK 의 프로모션을 도와주는 한 사람이 될 거라는 것이고요. 모바일 개발자와 프로그래밍을 모르는 일반인들을 위한 강력한 커뮤니티를 만들 거라는 겁니다. 여러분 모두 좋은 아이디어로 창조적인 사람이 될 수 있다고 믿습니다. 그리고 코로나 커뮤니키는 스토리텔러와 작가, 예술가 그리고 프로그래머들, 비지니스맨 등을 서로 연결시켜주는데 도움을 줄 것입니다. 그래서 우리의 기술들을 이용해서 다 함께 창조적인 결과물을 만들 수 있을 겁니다.

So, if you’re in the Dallas area, be sure to join the first ever Dallas Corona SDK Meetup group. The group is brand new and fully supported by the great folks at Ansca Mobile. Right now there are 19 Corona SDK Meetup Groups and growing. If you can’t join the Dallas Corona SDK Meetup Group, consider joining one close to you or contact Ansca Mobile directly to help them start a group in your area.

그러니까 만약 여러분이 달라스 지역에 계시다면 이 지역에 최초로 만들어진 달라스 Corona SDK 모임에 참가하세요. 이 그룹은 이번에 새로 만들어지는 그룹이고 Ansca Mobile 의 전문가들로부터 적극적으로 지원을 받고 있습니다. 지금까지 전 세계적으로 19개의 코로나 SDK 모임이 이뤄졌고 점점 더 늘어나고 있습니다. 만약 여러분이 달라스 코로나 SDK 모임에 참여할 수 없이시다면 여러분 가까이에 있는 모임에 참여하세요. 아니면 Ansca Mobile에 직접 연락하셔서 여러분 지역에서 모임을 시작하겠다고 말하고 논의하셔도 됩니다.

Let’s build something great together.

우리 함께 뭔가 근사한 일을 해 봐요.

Charles McKeever
Corona SDK Ambassador


=====  o ==== o ===== o ====


Charles 는 http://opensourcemarketer.com 에서 활동하는것 같습니다.  (아마 이 싸이트를 운영하는것 같애요.)


코로나 명예대사가 되어서 이제 모임을 결성하려나 봅니다.

지금 각 지역별로 오프라인 모임이 하나하나 진행중이거든요.


저는 미국에 있어서 오프라인 모임을 진행하는 것은 힘들고...

어떻게 해야 하는지 많이 고민이 됩니다.


제가 요즘 회사를 옮기게 되었습니다.

그래서 다음주에 New Jersey에서 Rhode island 로 이사해야 해서 조금 정신이 없습니다.


그리고 새 회사에서도 적응하는 기간동안에는 마음의 여유가 별로 없을 것 같구요.

그 회사에서는 Kurogo와 JQuery Mobile 기술을 주로 사용하나 봅니다. 그쪽으로다 공부 해야 할 것 같고..


하여간 여러모로 Corona SDK 명예대사로서 해보고 싶은 일이 많은데 좀 한계를 느낍니다.

그래도 하나하나 차근 차근 해 나가다 보면 언젠가는 아주 활성화 된 모임을 가질 수 있겠죠.

여러분들의 조언과 참여 부탁드립니다.


지금은 코로나에서 발표되는 새로운 기술이나 뉴스 등을 이 블로그를 통해서 전달하고 있는 수준인데요. 


우리도 달라스처럼 같이 모여서 뭔가 멋진 일을 한번 해 봐요... ^^


반응형


반응형

Scene Overlays and Parameter Passing

Posted by Jonathan Beebe

Storyboard API에서 가장 요구되어지는 두가지 사항들은 화면 전환하면서 custom data를 전달할 수 있는 기능과 한 scene 이 다른 scnen 위에 표시되는 pop up 기능입니다.

많은 분들이 그런 기능을 기다려왔는데 이제 더 이상 기다리지 않으셔도 됐습니다. Daily build 2012.797에 바로 이 두가지 기능이 모두 추가 됐습니다. 이름은 parameter passing과 scene overlays 입니다. (build 2012.785 에는 이미 parameter passing이 있었습니다.

이 기능들과 관련된 튜토리얼은 storyboard.gotoScene()의 parameter passing 과 storyboard.showOverlay()의 scene overlays 에서 보실 수 있습니다. 이렇게 튜토리얼이 있지만 여러분들의 이해를 돕기 위해 이 글에서 간단히 설명 드리겠습니다.

Parameter Passing

parameter passing은 한 scene에서 다음 scene으로 넘어가면서 custom data (하나의 변수 일 수도 있고 테이블-배열- 형식일 수도 있습니다.)를 쉽게 전달할 수 있도록 해 줍니다.

이것을 사용하게 하려면 storyboard.gotoScene() 의 신택스를 바꿔야만 했습니다. (걱정마세요. 이전 신택스도 계속 사용할 수 있습니다. 그러니 지금 진행하시는 프로젝트에는 아마 문제가 없습니다.) 아래 이 parameter passing을 사용하기 위한 새로운 신택스 예제가 있습니다.

local options =
{
    effect = "fade",
    time = 400,
    params =
    {
        var1 = "custom data",
        sample_var = 123,
    }
}
storyboard.gotoScene( "game_scene", options )


가장 크게 다른 점은 storyboard.gotoScene() 함수의 두번째 인수입니다. 이 인수가 optional key들과 optional table로 이루어져 있습니다. 위 예제에서는 모든 가능한 옵션들을 다 보여 줍니다. (effect,time,params). 새로운 부분은 params option 입니다. 이것은 변수가 될 수도 있고 테이블이 될 수도 있습니다.

이렇게 custom data를 pass 하면 그 다음 화면에서는 createScene이나 willEnterScene 그리고 enterScene event 리스너 등에서 event.params 로 이 데이터에 접근할 수 있습니다.

아래에는 game_scene.lua의 enterFrame에서 custom data를 access 하는 예제를 보여드리고 있습니다.

function scene:enterScene( event )
    local params = event.params

    print( params.var1 )    -- "custom data"
    print( params.sample_var )  -- 123
end





Scene Overlays

scene overlay 는 현재의 scene 위에 overlay 해서 다른 scene을 보여 주는 것입니다. 화면전환 효과를 사용해서 이 다른 scene이 나오지만 그 이전 scene이 없어지지 않고 그 자리에 그대로 있게 됩니다. 이 두 화면(scene)에는 두가지 이벤트가 추가 됩니다. 하나는 scene overlay가 display 됐을 때 dispatch 되는 이벤트하고요 그렇지 않을 때 dispatch 되는 이벤트입니다.

storyboard.showOverlay()

View Documentation

이 함수는 overlay를 보여주는 역할을 합니다. overlay 하기 위해 만든 scene은 다른 scnen과 같은 구조를 가졌을 겁니다. 어느 scene이든지 overlay 하고 싶으면 하시면 됩니다. 사실 overlay 가 display 되면 overlayBegin 이벤트가 현재 active 한 non-overlay scene에 dispatch 되게 됩니다. overlay 가 remove 되면 overlayEnded 가 dispatch 되죠.

아래 예제를 보세요. (scene1.lua에 있는 코드라고 생각해 봅시다.)

local options =
{
    effect = "fade",
    time = 400,
    params = { sample_var=456 }
}
storyboard.showOverlay( "overlay_scene", options )


이 scene1.lua의 어느 부분엔가 여러분은 옵션으로 overlayBegan과 overlayEnded 이벤트를 추가할 수 있습니다.

function scene:overlayBegan( event )
    print( "The overlay scene is showing: " .. event.sceneName )
    print( "We get custom params too! " .. event.params.sample_var )
end
scene:addEventListener( "overlayBegan" )

--

function scene:overlayEnded( event )
    print( "The following overlay scene was removed: " .. event.sceneName )
end
scene:addEventListener( "overlayEnded" )


위 리스너들에서 유심히 보셔야 될 것들이 두가지 있습니다. 첫번째는 일반적인 화면 전환에서와 같이 파라미터(custom data)들을  overlays scene에 params option을 사용해서  pass 할 수 있습니다. 그 custom data는 위에서 보신 예대로 리스너 함수에서 event.params 로 접근할 수 있구요.

두번째로 보셔야 될 부분은 event.sceneName 변수 입니다. 이것은 overlay scene의 이름을 나타냅니다. 이 변수는 overlayBegan과 overlayEnded 이벤트에서만 접근 가능합니다.

좀 더 자세한 사용법과 신택스는 storyboard.showOverlay() 문서를 봐 주세요.

storyboard.hideOverlay()

View Documentation

이 함수는 이름만 봐서도 어떤 일을 하는지 알 수 있겠죠? 그런데 한가지 알아두셔야 할 중요한 사항이 있습니다. 이것은 현재 보여지는 overlay를 hide 해줍니다. 하지만 그 이상의 무엇인가가 또 있습니다.

디폴트로 overlay scene은 완전히 remove 될 겁니다. (purge되고 메모리에서 그 모듈이 unload 될 겁니다. 현재 load된 scene이 일반적인 scene이고 overlay로 사용되고 있지 않다면요) 옵션으로 이 함수로 overlay scene을 간단하게 purge 시킬 수도 있습니다. 이것은 조만간 이 화면을 다시 사용하려고 할 때 유용하게 이용될 겁니다.

storyboard.showOverlay() 함수가 있는데요. 이 함수에서 storyboard.gotoScene()에서 사용할 수 있는 화면전환 효과도 사용할 수 있습니다.

좀 더 자세한 사용법과 신택스는 storyboard.hideOverlay() 문서를 참조하세요.

Important Notes

overlay scene과 관련해서 몇가지 알아 두셔야 할 점들이 있습니다.

첫번쨰로 한번에 단 한개의 overlay 화면만이 보여질 수 있습니다. 여러분이 storyboard.gotoScene(), storyboard.removeAll(), storyboard.purgeAll() 을 call 하거나 다른 overlay scene을 보여주려고 시도한다면 현재의 overlay scene은 remove 될 겁니다. 이 overlay scene은 그 이전에 있던 오리지널 scene에 종속돼 있는 것입니다.

또 다른 중요한 사항은 overlay scene들을 어떻게 call 하느냐에 대해 주의하셔야 합니다. 예를 들어 시간을 좀 delay 시킨 후 overlay를 보여준다면 화면전환 효과는 이 time delay가 끝날 때까지 일어나지 않을거라는 겁니다. 그리고 오리지널 scene에서 display.gotoScene()을 하기전에 이 overlay를 remove 해 주셔야 합니다.



반응형


반응형

Working with Time: Delays and Counting 

Posted by Jonathan Beebe

time 을 사용하는 앱이나 게임은 무수히 많습니다. 몇 초 후에 어떤 일이 일어나게 하던지 유저가 얼마 안에 특정 일을 끝내게 해야 한다던지 같은 시간을 컨트롤 해야 할 일들은 많습니다.

Corona SDK에서는 이러한 time을 빠르고 쉽게 콘트롤 함으로서 게임이나 앱의 개발에 도움을 줄 수 있는 가이드를 제공하고 있습니다.

이 튜토리얼에서는 코로나의 아주 유용한 timer.performWithDelay() 함수에 대해 소개하려고 합니다. 그리고 이 함수를 가지고 여러분의 앱에서 간단하게 활용할 수 있는 방법도 알려 드리겠습니다.

Time Delays


timer.performWithDelay() 는 특정 시간 이후에 특정 동작을 행할 수 있도록 해 줍니다. 이 함수 이름만 봐도 이 함수가 뭘 하는지 쉽게 짐작하실 수 있을 겁니다.

아래 신택스가 있습니다.

timer.performWithDelay( delay, listener [, iterations] )


여러분이 이 함수를 call 했을 때 여러분은 얼마동안 delay 하는지에 대해 정해 주시면 됩니다. (단위는 밀리세컨드입니다.) 그리고 그 지정된 시간이 다 됐을 때 불리워질 함수를 넣으시면 됩니다. 옵션으로 이 작업을 몇번이나 반복해서 수행하는지도 iterarions 에 숫자를 넣어서 정해 주시면 됩니다. 디폴트는 1 입니다.

What are iterations?

timer iteration은 이 timer.performWithDelay 를 몇번 수행할지 정해 주시는 부분입니다. 이 숫자를 0으로 지정하시면 이 timer를 remove 하거나 앱을 종료할 때까지 무한으로 반복합니다.


다음에는 timer.performWithDelay() 함수와 함께 anonymous 함수를 어떻게 사용할 수 있는지에 대해 알려드리겠습니다.





Using a function

아래 예제에서는 1초 후에 hello_world() 함수를 call 하는 것을 단 1회 시작하도록 코딩 했습니다.

local function hello_world()
  print( "Hello world!" )
end

timer.performWithDelay( 1000, hello_world, 1 )


hello_world vs. hello_world()

계속 진행하기 이전에 많은 개발자 분들이 혼동하시는 부분에 대해 명확히 밝히고 넘어가겠습니다. 위 예제에서 timer.performWidhDelay() 함수의 두번째 인수로 hello_world() 를 사용하지 않고 hello_world 를 사용한 점입니다.

그 이유는 이것은 존재하는 함수를 단지 참조하라고 알려주는 것이라서 입니다. 그래서 우리는 그 함수의 변수명(variable name)을 사용하면 되는 겁니다. 만약에 여기에 hello_world()를 사용한다면 이 함수를 실제로 call 하게 되는 겁니다. 그러면 hello_world() 함수에서 return 되는 값에 따라 그 다음 동작이 일어날 수도 있고 안 일어 날 수도 있습니다. 기본적으로 함수의 디폴트 return 은 nol 이기 때문에 그렇게 하면 문제가 발생할 수가 있습니다. 그래서 함수명이 아니라 변수명을 사용하시는 겁니다.


Using anonymous functions

timer.performWithDelay() 함수의 두번째 인수가 함수가 들어가는데요. 여기에 anonymous 함수를 사용할 수도 있습니다. 그냥 이 부분에 함수를 구현하실 수 있다는 애기입니다. 아래 예제에서 보시는 대로 두번째 인수에 이 함수를 구현하시면 됩니다.

timer.performWithDelay( 1000, function()
  print( "Hello world!" )
end, 1 )


물론 이것을 1라인으로 만들 수도 있지만 이것이 함수인것을 좀 더 이해하기 쉽도록 하기 위해 저렇게 줄을 나눴습니다.

이 anonymous 함수를 사용하실 때 알아두셔야 할 점은요. 쉼표 (,) 사이에 전체 함수 (function() 에서 end 까지)가 들어가야 한다는 것입니다. 그래야지 timer.performWithDelay()는 이 인수가 valid 하다고 판단합니다.

좀 더 자세한 정보는 1년전에 Eric Wing이 작성한 using closures as function callbacks 튜토리얼을 보시면 아실 수 있을 겁니다.

Passing Arguments to the Listener

timer.performWithDelay()를 사용하면서 많이 나오는 질문이 호출하는 함수에 어떤 인자를 전달할 수 있느냐 입니다.

이것을 구현하는 방법은 아래와 같이 하시면 됩니다.

local function hello_world( arg1, arg2 )
  print( "Hello world!", arg1, arg2 )
end

timer.performWithDelay( 1000, function()
    hello_world( "first", "second" )
end, 1 )


어떻게 하는지 아시겠죠? timer.performWithDelay() 안에서 anonymous 함수를 사용해서 그 함수에서 외부 함수를 인수와 함께 호출했습니다.
좀 헛갈리시나요? 몇번 해 보시면 금방 익숙해 지실 겁니다.

Other functions

timer 함수는 timerId를 return 합니다. 그래서 다른 함수가 이 timerId를 가지고 어떤 동작을 하도록 컨트롤 할 수 있습니다. timer 함수에는 timer.pause, timer.cancel(), timer.resume() 등의 메소드가 있습니다. 이 메소드들은 이름만 봐도 어떤 일을 하는지 알 수 있겠죠? 자세한 내용은 timer API reference page 를 참조하세요.

Counting Time


앞서 얘기했듯이 앱에서 이 time을 컨트롤 해야 할 상황이 아주 많습니다. 예를 들어 게임을 시작하는 시간과 끝나는 시간을 한번 catch 해 봅시다.

이 게임을 시작하는 부분에 아래 코드를 넣습니다.

local markTime = os.time()

os.time()
이 함수는 현재의 시간을 return 합니다. (위와 같이 아무런 인자 없이 call 했을 경우) 이외에도 더 많은 기능이 있는데요. 그 기능은 여기를 참조하세요.



사용자가 game over 상태에 이르렀을 때 아래 코드로 게임 시간이 얼마나 길었는지를 얻어낼 수 있습니다.

local timePassed = os.time() - markTime


처음 시작했을 때의 시간이 markTime 이니까 끝날 때의 현재시간 (os.time()) 에서 markTime을 빼면 게임 시간이 나오겠죠? 여기서 timePassed 는 초단위로 값을 갖고 있습니다. 분단위로 표시하고 싶으면 이 값을 60으로 나누면 되겠죠. 밀리세컨드로 하려면 1000을 곱하면 되겠구요. 밀리세컨드로 곧바로 값을 받을 수도 있습니다. system.getTimer()를 이용하시면 됩니다. 이용하시는 방법은 위와 똑 같구요.

Time’s up!

이제 여러분은 timer.performWithDelay() 함수를 사용하시는데 프로가 되셨습니다. 그리고 여러분의 앱에서 어떻게 time을 관리해야 하는지에 대해서도 이해하셨을 겁니다.

time 과 관련된 다른 함수들들을 더 이해하고 싶으시면 os.clock(), os.date(), os.difftime(), system.getTimer() 함수들을 보시면 더욱 더 유용하게 여러분의 앱에서 time을 컨트롤 하실 수 있을 겁니다.

반응형


반응형

이번주에도 Corona SDK 에서 금주의 SDK FAQ 5개를 올렸습니다.

이 내용 번역해서 같이 공유 합니다.


FAQ Wednesday

Posted by Tom Newman 

수요일 입니다. 오늘도 자주 들어오는 5개의 질문을 골라서 답변해 드리겠습니다.

Question 1

코로나에서는 PNG 나 JPG 어떤 이미지를 써야 하나요?

Answer

이미지의 화질이나 앱 패키지의 사이즈 등에 따라 다를 수 있습니다. 코로나는 32비트 PNG 와 32비트 JPGs를 지원합니다. PNG는 손실없이 압축하면서도 투명 효과를 지원하고 JPG는 압축되지만 약간 손실이 있고 장점은 광범위한 Color range를 지원합니다. 같은 해상도에서 PNG는 일반적으로 JPGs 보다 사이즈가 큽니다. 이건 여러분의 앱 용량 제한 조건에 영향을 줄 수 있습니다.

texture 메모리 사용량에 대해  PNG와 JPG는 모두 같은 용량의 openGL 메모리를 차지합니다. 왜냐하면 이미지는 메모리에 로드됐을 때는 압축되지 않기 때문이죠. 또 한가지 알아두셔야 할 것은 이미지는 openGL 메모리에 로드됐을 때는 2의 제곱으로 (2, 4, 8, 16, 32, 64, 128, 256, 512, etc.) 로드 됩니다. 만약 여러분이 320*480, 280*400 두개의 이미지가 있을 때 이 이미지는 모두 512*512 만큼의 texture memory를 소비한다는 겁니다. 769*1024 이미지는 1024*1024 byte를 소비할 겁니다.





Question 2

가끔 began touch 이벤트는 있는데 ended 이벤트는 없는 경우가 있는데 왜 그런가요?

Answer

그런 현상은 버그가 아닙니다. 이런 일이 어떻게해서 일어나는지 그리고 어떻게 처리해야 하는지 개발자로서 잘 알아 두실 필요가 있습니다. touch 에는 began과 ended 이벤트가 있습니다. display object에 touch 리스너를 생성하셨다면 그 object를 touch 하면 일반적으로 began, moved, ended 이벤트를 받게 됩니다. 그리고 그 리스너를 어떻게 구현했는지 그리고 유저가 그 object에 대해 touch를 어떻게 발생했는지에 따라 touch 시에 특정 이벤트가 missing 될 수 있습니다.

아래 코드는 circle object에 대해 간단한 방법으로 touch 리스너를 단 예제입니다.

local circle = display.newCircle( 100, 100, 50 )

-- Touch listener
local function myTouch( event )
    print( "Touch event = " .. event.phase )
end

circle:addEventListener( "touch", myTouch )


만약 유저가 원을 터치하고 손을 떼면 리스너는 began과 ended 이벤트를 call 할 겁니다. 또 만약 손가락을 떼지 않고 화면에서 움직이면 moved 이벤트가 나올 겁니다.

유저가 그 원을 터치하고 움직이다가 원을 벗어났다고 생각해 봅시다. 그럴 경우에는 began 과 moved 이벤트만 생성되고 ended 이벤트는 생성되지 않을 겁니다. 왜냐하면 손가락을 뗀 행위는 그 원안에서 일어나지 않았기 때문입니다.

그러면 ended 이벤트는 어디로 갔을 까요? 답은 다른 object 리스너로 갔다 입니다. Runtime touch 리스너나 원이 아닌 다른 object 의 리스너로 간거죠.

그러면 그 다른 object의 이벤트는 어떨까요? 그 object에는 moved와 ended는 있지만 began이 없겠죠? 왜냐하면 touch 이벤트가 한 object에서 시작해서 그 object 를 떠나서 다른 object에서 마감을 했기 때문입니다.

만약 한 object에서 이벤트가 시작됐을 경우 그 이벤트의 끝이 그 object에서 작동하게 하려면 setFocus 를 쓰시면 됩니다.

local circle = display.newCircle( 100, 100, 50 )

-- Touch listener
local function myTouch( event )
    print( "Touch event = " .. event.phase )
  
    if "began" == event.phase then
        display.getCurrentStage():setFocus( circle )  -- set touch focus on circle
        event.target.focus = true
    end
  
    if "ended" == event.phase or "cancelled" == event.phase then
        if event.target.focus ~= true then
            return false
        end
        print( "Ended found" )
        display.getCurrentStage():setFocus( nil ) -- clear touch focus
        event.target.focus = false
    end

    return true
end

circle:addEventListener( "touch", myTouch )


이 예제에서 setFocus는 began 일 경우에 설정을 했습니다. 그리고 ended에서 이 setFocus를 해제를 했죠. 이러한 방법으로 해당 객체에서 이벤트가 시작됐으면 그 이벤트가 그 객체 밖에서 종료하더라도 해당 객체에 ended 가 적용되도록 만들 수 있습니다.

아래 문구에 대해서 주의 깊게 살펴 보실 필요가 있습니다.

event.target.focus = true

이 코드가 began 에서 사용됐죠 그리고 ended 에서도 false로 할당 하느라고 사용했습니다. 바로 이 코드가 해당 object에서 리스너가 일어나고 끝날 수 있게 컨트롤 해 주는 겁니다.

좀 touch에 대해 좀 더 자세히 알고 싶으시면 Detecting Touches in Corona 튜토리얼을 보시기 바랍니다.

Question 3

코로나에서 하수를 정의하는 두가지 방법에 대해서 봤습니다. 어떤게 올바른 건가요? 그리고 그 둘의 차이점은 뭔가요?

Answer

함수는 두가지 방법으로 생성하실 수 있습니다.

local function myfunc1()
    print( "function = ", myfunc1 )
end

and
local myfunc2 = function()
    print( "function = ", myfunc2 )
end


두개 모두 대부분의 경우 잘 동작합니다. 그런데 두번째의 경우에는 이 함수 내부에서  function name을 참조하는것이 필요한 경우에는 작동하지 않습니다. 왜냐하면 이 함수 변수인 myfunc2는 이 함수가 정의 되기 전까지는 아직 생성된게 아니니까요. 첫번째의 경우에는 함수 변수 myfunc1은 이 함수가 정의되기 이전에 생성된 겁니다. 그러니까 이 함수 내부에서 참조될 수가 있습니다. 위 두개의 코드를 시뮬레이터에서 실행하시면 첫번째는 myfunc1 값을 보실수 있지만 두번째는 nil을 보시게 될 겁니다.

myfunc1 함수는 아래와 똑 같습니다.

local myfunc1
function myfunc1()
...
end


저는 myfunc1 방식으로 함수를 사용하는 편입니다. 왜냐하면 저한테는 이게 더 전통적이라고 느껴지거든요. 그리고 함수 안에서 그 함수를 참조할 때 nil 값을 받을 염려도 없구요. 하지만 글로벌 함수로 이용한다면 두 함수 모두 똑 같습니다.

Question 4

config.lua 에서 스크린 사이즈를 640*960 (iPhone 4) 로 설정했습니다. 그랬더니 iPhone 3 에서는 이미지가 작게 나와요. 왜 그럴까요?

Answer

만약 여러분이 디바이스의 표준 해상도보다 큰 이미지를 로드하기 위해 display.newImage를 사용하신다면 이 이미지들은 config.lua 파일에 세팅된 width/height 에 근거해서 dynamic 하게 scale이 조절되기 전에 screen에 맞게 먼저 조절 됩니다. 예를 들어 600*100 픽셀짜리 이미지를 iPhone3 (320*480) 에 표시한다고 합시다. 이 이미지는 dynamic하게 scale 되기 전에 화면에 맞게 먼저 이미지가 작아질 겁니다. 이래서 iPhone4에 맞추면 iPhone3에서 이미지가 작게 보이는 이유입니다. 이것을 해결하려면 display.newImageRect (위의 경우에는 이미지 사이즈를 600*100으로 하시면 되겠죠)나 display.newImage와 isFullResolution flag를 true로 세팅하시면 됩니다. 이렇게 하면 native screen size에 근거해서 이미지가 scaling 되는 것을 건너 뛰게 해 줍니다.

Note : iPhone4에서 scale down 하기 위해 320*480 보다 큰 이미지를 사용하면 display.newImage에서 에러가 발생하는 버그가 있었습니다. 이런 현상은 dynamic scaling이 적용 되던 안되던 발생했습니다. 이 버그는 Daily Build 2012.788 에서 해결 됐습니다.

좀 더 자세한 정보는 Dyamic Image Resolution 을 참조하세요.

Question 5

iOS5 환경에서 코로나는 audio 관련 버그가 좀 있었습니다. 왜 애플과 관련해서계속 버그가 나오죠?

Answer


가끔 코로나의 버그들은 operating system 에서 발견된 버그에 기인하는 경우가 있습니다. 그 문제와 관련해서 해결책을 찾기위해 노력중입니다. 일단 최선의 방법은 그 OS에서 버그를 해결하는게 되겠죠. iOS5에서는 해결하기 어려운 openAL audio 버그들이 좀 있습니다. 저희들은 포럼들에 버그 메세지가 올라오는 것을 보고 그 버그를 지속적으로 수정하고 있습니다. 그리고 그 버그 해결과 관련한 글을 그 포럼들에 댓글로 답해주고 있습니다. 그리고 그 버그들을 정리하고 있습니다. 또 애플에 report를 하고 있구요.  더 많은 유저들이 이 버그에 대해 레포트를 한다면 애플에서 이 버그를 근본적으로 해결할 가능성이 커 지겠죠. Ansca 말고는 아무도 이 버그 레포트를 하지 않는다면 이 문제는 근본적인 해결이 어렵겠죠.

좀 더 자세한 정보와 애플 버그와 관련된 정보는 Apple Bug Reporter 에서 보실 수 있습니다.


 
 

반응형


반응형

Working with classes in Sencha Touch 2.0

1. Declaration (선언)

1.1. The Old Way (옛날 방법)


만약 여러분이 Sencha Touch 1.x 버전을 사용하신다면 분명 클래스를 생성하기 위한 Ext.extend 를 잘 알고 계실겁니다.

var MyPanel = Ext.extend(Object, { ... });

이것은 다른 클래스를 상속받는 새로운 클래스를 생성할 때 손쉽게 이용할 수 있는 방법입니다. 상속하는 것 말고는 다른 클래스 생성 관점에서 보면은 그렇게 크게 유용하지는 않습니다. configuration이라던지 statics, mixins 같은 것들 말이죠. 간단하게 이런 아이템들과 관련한 사항들을 살펴보죠.

아래 샘플을 한번 보세요.

My.cool.Panel = Ext.extend(Ext.Panel, { ... });

여기서는 새로운 클래스의 네임스페이스를 사용했고 Ext.Panel을 extend 했습니다. 이 예제에서는 두가지 알아두어야 할 것들이 있습니다.

1. My.cool은 프로퍼티로서 Panel을 할당하기 전에 객체로서 존재해 있어야 합니다.
2. Ext.Panel은 이것이 참조되기 전에 존재하고 또 로드 되어 있어야 합니다.

첫번째 아이템은 대개 Ext.namespace (Ext.ns)를 사용해서 해결 합니다. 이 메소드는 object/property를 통해 재귀적으로 참조 되고 그것이 존재하지 않으면 생성합니다. 좀 성가신 일은 여러분이 Ext.extend를 사용할 때는 항상 이것을 사용해야 한다는 것이죠. 아래 예제가 있습니다.

Ext.ns('My.cool');
My.cool.Panel = Ext.extend(Ext.Panel, { ... });


두번째 이슈는 이것을 address 하기가 쉽지 않다는 것입니다. 왜냐하면 Ext.Panel 은 다른 많은 클래스들을 depend on  할 것이기 때문이죠. 다른 클래스들을 직접적이든 간접적이든 상속하니까요. 그러면 그 상속할 대상이 되는 클래스는 반드시 존재해 있어야 하겠죠. 이러한 이유 때문에 Sencha Touch 2 이전에는 ext-all.js의 모든 라이브러리의 일부분만 사용해도 이것을 통재로 include 했었습니다.

1.2. The New Way (새로운 방법)

센차 터치 2 는 클래스를 생성할 때 오직 한가지 메소드만 생각하면 되도록 부가적인 것들은 전부 제거했습니다. 그것은 Ext.define 입니다. 아주 간단한 신택스죠.

Ext.define(className, members, onClassCreated);

이 신택스의 각 부분별로 한번 살펴 보겠습니다.

- className 은 클래스의 이름입니다.
- members는 key-value 조합의 클래스 멤버 collection을 나타내는 객체입니다.
- onClassCreated는 옵션입니다. 모든 관계된 클래스가 ready 되면 invoke 하기 위한 callback 함수이죠. 또한 이 클래스 자체가 완전히 생성되면 invoke 되기도 합니다. 클래서 생성의 새로운 비동기적인 성격으로 인해  이 callback은 다양한 경우에 아주 유용하게 사용될 수 있습니다. 이 내용은 Sencha Touch 2 튜토리얼 4장에서 다시 자세하게 다뤄질 겁니다.


Example

Ext.define('My.sample.Person', {
    name: 'Unknown',

    constructor: function(name) {
        if (name) {
            this.name = name;
        }
    },

    eat: function(foodType) {
        alert(this.name + " is eating: " + foodType);
    }
});

var aaron = Ext.create('My.sample.Person', 'Aaron');
    aaron.eat("Salad"); // alert("Aaron is eating: Salad");

   
Ext.create() 메소드를 사용해서 My.sample.Person의 새로운 인스턴스를 생성했습니다. 그러려면 아마 (new My.sample.Person())을 사용해야 했겠죠. 하지만 다이나믹 로딩의 장점을 이용하기 위해서 위의 방법대로 하실것을 권장합니다. 다이나믹 로딩의 좀 더 자세한 사항은 Getting Started guide를 살펴 보세요.

2. Configuration

센차터치 2에서는 클래스가 생성되기 전에 강력한 Ext.Class 전처리 장치에 의해 진행되는 config property를 제공하고 있습니다.
이것은 아래와 같은 내용들을 제공합니다.

- configurations는 다른 클래스 멤버로부터 완전하게 캡슐화 되어있습니다.
- 각 config property의 getter와 setter 메소드들은 클래스가 생성되는 동안 이 메소드들이 따로 정의되어 있지 않으면 class prototype에 자동적으로 생성합니다.
- 각 config property에 대해 apply 메소드도 또한 생성됩니다. 자동으로 생성된 setter 메소드는 value를 setting 하기 전에 내부적으로 apply 메소드를 call 합니다.
그 value 를 세팅하기 전에 custom logic 을 run 할 필요가 있으면 config property에 apply 메소드를 override 합니다. 만약 apply가 어떤 값도 return 하지 않으면 setter는 value를 set 하지 않습니다.

아래에 예제가 있습니다.

Ext.define('My.own.WindowBottomBar', {});

Ext.define('My.own.Window', {

    /** @readonly */
    isWindow: true,

    config: {
        title: 'Title Here',

        bottomBar: {
            enabled: true,
            height: 50,
            resizable: false
        }
    },

    constructor: function(config) {
        this.initConfig(config);
    },

    applyTitle: function(title) {
        if (!Ext.isString(title) || title.length === 0) {
            console.log('Error: Title must be a valid non-empty string');
        }
        else {
            return title;
        }
    },

    applyBottomBar: function(bottomBar) {
        if (bottomBar && bottomBar.enabled) {
            if (!this.bottomBar) {
                return Ext.create('My.own.WindowBottomBar', bottomBar);
            }
            else {
                this.bottomBar.setConfig(bottomBar);
            }
        }
    }
});


아래 예제는 이것을 어떻게 사용하는지를 보여줍니다.

var myWindow = Ext.create('My.own.Window', {
    title: 'Hello World',
    bottomBar: {
        height: 60
    }
});

console.log(myWindow.getTitle()); // logs "Hello World"

myWindow.setTitle('Something New');
console.log(myWindow.getTitle()); // logs "Something New"

myWindow.setTitle(null); // logs "Error: Title must be a valid non-empty string"

myWindow.setBottomBar({ height: 100 }); // Bottom bar's height is changed to 100



3. Statics

static 멤버들은 static config를 사용해서 정의될 수 있습니다.

Ext.define('Computer', {
    statics: {
        instanceCount: 0,
        factory: function(brand) {
            // 'this' in static methods refer to the class itself
            return new this({brand: brand});
        }
    },

    config: {
        brand: null
    },

    constructor: function(config) {
        this.initConfig(config);

        // the 'self' property of an instance refers to its class
        this.self.instanceCount ++;
    }
});

var dellComputer = Computer.factory('Dell');
var appleComputer = Computer.factory('Mac');

alert(appleComputer.getBrand()); // using the auto-generated getter to get the value of a config property. Alerts "Mac"

alert(Computer.instanceCount); // Alerts "2"



Error Handling and debugging (에러 처리와 디버깅)


센차터치 2에는 디버깅과 에러 처리를 도와주는 유용한 기능이 있습니다.

메소드의 display name을 얻으려면 Ext.getDisplayName()을 사용하실 수 있습니다. 이것은 description 안에 클래스 이름과 메소드 이름을 가진 에러를 throw 할 때 유용하게 사용하실 수 있습니다.

throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');

에러가 Ext.define()을 사용해 정의된 클래스의 메소드내에서 던져졌을 때 여러분의 브라우저가 크롬(Chrome)이나 사파리(Safari) 같이 WebKit 을 사용하는 브라우저라면 call stack에 그 메소드와 클래스 이름이 표시될 겁니다.

아래에 크롬에서 보실 수 있는 에러 메세지들이 있습니다.


반응형

PhoneGap 설치하고 예제 실행하기

2012. 4. 26. 02:59 | Posted by 솔웅


반응형

오늘은 PhoneGap 을 한번 설치 해 보기로 했습니다.

저는 Hybrid App 을 Corona SDK, Sencha Touch, JQuery Mobile 을 위주로 한번 연구해 볼 생각이거든요.


거기다가 Kurogo 가 도움이 된다면 같이 한번 사용해 보고 싶고...

웹 서버쪽은 PHP 와 데이터베이스를 사용할 거고.


이런 구조로 Hybrid App 을 개발 툴 조합을 연구해 보고 있습니다.


그런데 디바이스의 Native 기능 등을 사용하기 위해 Corona SDK를 사용하느냐. PhoneGap을 사용하느냐 를 결정하려면 장단점을 알고 있어야 할 것 같아서요.


Corona SDK에 대해서는 잘 알지만 일반적으로 Hybrid App에 많이 사용되는 PhoneGap에 대해서는 전혀 몰라서 오늘 한번 설치해보고 감을 잡고자 합니다.


우선 eclipse 와 Android SDK, ADT Plugin, JAVA 등은 다 설치 되서 Native Android 앱 개발 환경은 다 완료 된 것으로 하고 PhoneGap 설치를 진행해 보겠습니다.


1. http://phonegap.com/start 로 접속을 합니다.


2. 아래 화면에서 해당 platform을 선택합니다. (저는 Android를 선택했습니다.)



3. 비디오 튜토리얼이 있네요. 이것부터 한번 볼까요?




보니까 PhoneGap 에 대해 많이 이해가 되네요.

이클립스 개발환경에서 폰갭을 설치하고 샘플 앱을 만드는 방법까지 자세히 설명을 했습니다.


4. 다음 단계는 Eclipse, Android SDK, ADT Plugin을 설치하는 단계입니다.



저는 ADT Plugin 까지 모두 설치 된 상태이기 때문에 PhoneGap 다운로드부터 하겠습니다.




이 글을 올리는 시점에는 PhoneGap 1.6.1 이 최신 버전이네요.


5. 다운받은 압축 파일을 푸니까 아래와 같은 구조네요.



lib 폴더에 android, bada, blackberry, ios, symbian, windows 같은 각 모바일 플랫폼 별 jar 파일과 js 파일이 들어있고 예제 파일도 들어있습니다.


6. 그 다음은 Android Native Language로 App을 만들 때 처럼 이클립스에서 New Android Projet를 만듭니다.


- 이클립스에서 File-New-Android Project를 선택합니다. 그리고 Project Name을 정합니다.



- 일단 버전은 2.2 를 선택하겠습니다.


- Package Name 이 빠졌으면 이 부분 넣고 Finish 버튼을 누릅니다.




7. 그 다음에는 project 폴더에 2개의 폴더를 더 추가해 넣습니다. (libs, assets/www)


8. 다음에 아까 받았던 PhoneGap 의 jar 파일을 libs에 js 파일을 www 에 복사해 넣습니다.

그리고 xml 폴더를 res 폴더 밑에 복사해 넛습니다.




9. 다음은 java 파일을 조금 수정하는데요.




위에 빨간 줄 친 부분을 바꾸시면 됩니다. (위에것 에서 아래 것으로요)


10. 다음에는 AndroidManifest.xml 파일을 수정합니다.

AndroidManifest.xml 안에서 <uses-sdk android:minSdkVersion="8" /> 코드를 찾으세요.

그리고 그 위에 아래 코드를 붙여 넣으세요.


<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />


그리고 <activity ..... > 태그에 아래 코드를 추가하세요.

android:configChanges="orientation|keyboardHidden"


그러면 대개 아래와 같은 형식이 될 겁니다.



10. 그 다음은 PhoneGap 프로그래밍을 하시면 됩니다.

www 폴더 밑에 index.html 파일을 생성하신후 아래와 같이 해 보세요.


<!DOCTYPE HTML>
<html>
<head>
<title>PhoneGap</title>
<script type="text/javascript" charset="utf-8" src="cordova-1.x.x.js"></script>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>


11. 이제 실행하시면 됩니다. Ctrl + F11 을 누르시던지 프로젝트에서 오른쪽 마우스 버튼을 클릭한 후 Run As - Android Application을 실행 해 보세요.


아래 화면이 완성된 화면입니다.




처음엔 좀 복잡하네요..


하여간 이렇게 설치하고 예제를 하나 실행했더니 폰갭이 대강 이해가 갑니다.


자체적으로 jar 파일하고 js 파일을 제공해서 모바일 앱을 만들도록 하는 거네요.

각 플랫폼 마다 따로따로 개발해야 되는 번거로움이 좀 있구요.

(코로나 SDK 는 그냥 빌드만 따로 하면 되는데 말이죠.)

대신 기존 Android Native Programming 구도를 그대로 사용하는 거라서 Native 기능을 모두 사용할 수는 있겠네요.


폰갭 + JQuery, Sencha Touch를 하면 정말 많이 편리할 것 같습니다.


폰갭 공부도 좀 더 해서 폰갭 조합 하고 코로나 SDK 조합 Hybrid App 개발 둘 다 해야 겠습니다.


재밌네요...



반응형

Kurogo Platform Demo 체험기

2012. 4. 25. 00:55 | Posted by 솔웅


반응형

지난번에 Kurogo Mobile Middleware 문서를 하나 번역해서 소개해 드렸습니다.

Multi-Platform 모바일 환경에서 유용하게 사용될 기술 같아서 관심을 가졌는데요.


대충 감만 잡았지 잘 모르겠더라구요.


그래서 오늘은 해당 웹사이트에서 소개하는 5분만에 Kurogo Mobile Middleware 체험하기 가 있길래 한번 따라해 봤습니다.


우선 http://modolabs.com/ 로 가시던지 아니면 http://kurogo.org/home/ 로 가세요.


1. Kurogo Demo 체험해보기 시작

 위 첫번째 주소로 가시면 아래 화면이 나올겁니다.


두번째 주소로 가시면 아래 화면을 보세요.



첫번째 화면에서는 Try Our Demo Today를 누르시고 두번째 화면에서는 5-Minute Test Drive를 누르세요.


2. 다음은 sign up 화면 입니다. 필요한 정보 채우시고 Sign up 버튼을 누르세요.



3. 아래 화면이 나오면 Go to Quickstart Admin 을 누르세요.


4. 이제 아까 등록했던 Email 하고 패스워드를 누르고 sign in 하시면 됩니다.




5. 첫 화면에는 아래와 같이 Site 이름 등이 나오고 Optional Menu 로는 Contents가 들어있는 싸이트나 유튜브 아이디 등을 넣으라고 나옵니다. (저는 그냥 디폴트로 했어요.)



6. 다 입력하고 밑에 finish 버튼을 누르면 아래와 같은 화면을 보실 수 있습니다.

왼쪽 메뉴를 보시면 여러 configuration 메뉴를 보실 수 있습니다.

살펴 보시고 난 후 View Site를 누르세요.



7. 그러면 Site 가 나옵니다.

저는 회사 logo image에 제 사진을 넣었어요.

그리고 밑에 파란 아이콘들을 누르면 여러가지 contents들을 볼 수 있어요.

아마 이렇게 Kurogo Platform을 설치하면 저 아이콘을 누르면 들어가서 볼 수 있는 비디오나 맵, 도표, 뉴스, 주소록 등을 쉽게 이용할 수 있도록 하나봅니다.


저도 Kurogo 관련 문서 하나 보고 잘 이해가 안 가서 Demo를 한번 더 실행해 봤는데요.

조금 더 알것 같긴 하지만 좀 더 공부해야 할 것 같아요.


저는 지금 Corona SDK와 Sencha Touch, JQuery Mobile 쪽을 더 중심에 놓고 공부를 하고 있거든요.


이 Kurogo 관련 기술은 짬짬이 더 공부를 해야겠습니다.


좋은 기술인 것 같은데 많이 공부해야 할 것 같습니다.


반응형


반응형

큰 규모의 프로젝트를 진행하려면 OOP (객체지향) 개념을 사용하는 것이 좋습니다.

이 OOP를 사용하려면 클래스를 잘 이용해야 합니다.

이번글과 다음글은 Sencha Touch 2 에서 클래스를 어떻게 사용하는지에 대해 공부해 보겠습니다.

Sencha Touch2 에서는 나름의 class system을 제공하고 있네요.

클래스를 사용하는데 여러 간편한 방법을 제공하는 것 같습니다.


오늘은 여러 규칙과 개념 위주로 정리를 하고 다음 글에서 실제로 코딩하는 방법에 대해 주로 알아 보겠습니다.


먼저 이 글을 보시기 전에 아래 Sencha Touch 2 의 class system에 대해 설명하는 동영상을 보시면 도움이 되실 겁니다.




SenchaCon 2011: The Sencha Class System from Sencha on Vimeo.



How to use classes in Sencha Touch 2  - 1 -

센차터치 2는 Ext JS 4에서 개발된 art class system을 사용합니다. 이 시스템은 providing inheritance, dependency loading, mixins, 강력한 configuration 옵션들 그리고 더 다양한 것들을 위해 자바스크립트에서 새로운 클래스를 쉽게 생성하도록 해 줍니다.

이 시스템에서 클래스는 단지 어떤 함수의 객체일 뿐이고 거기에 프로퍼티들이 첨가 됩니다. 예를 들어 여기 animal 이란 클래스가 있습니다. 이 클래스의 이름과 함수는 아래와 같이 구성할 수 있습니다.

Ext.define('Animal', {
    config: {
        name: null
    },

    constructor: function(config) {
        this.initConfig(config);
    },

    speak: function() {
        alert('grunt');
    }
});


이제 Animal이라는 클래스가 생겼습니다. 이제 각각의 animal 객체를 만들 수 있고 그 객체들은 이름을 가질 수 있고 짖을 수 있습니다. animal의 새 instance를 만들기 위해 우리는 Ext.create 를 사용하면 됩니다.

var bob = Ext.create('Animal', {
    name: 'Bob'
});

bob.speak(); //alerts 'grunt'


여기 Bob이라는 Animal을 만들었습니다. 그리고 bob에게 말하라라고 시켰습니다. 우리가 클래스를 생성하고 그것을 초기화 했고 또 그것을 더 진화시킬 수도 있습니다. 여기까지는 우리는 아직 Bob이 어떤 종류인지를 모릅니다. 이제 우리가 Human 이라는 서브클래스가 있다고 해 봅시다.

Ext.define('Human', {
    extend: 'Animal',

    speak: function() {
        alert(this.getName());
    }
});


여기 Animal을 상속받은 새 클래스가 있습니다. 이 클래스는 Animal 클래스의 모든 함수와 configuration들을 사용할 수 있습니다. 이 Human 에서는 speak 함수를 overrode 했습니다. 왜냐하면 human은 똑똑하기 때문에 grunt 하는 대신에 자신의 이름을 말 할 수 있으니까요. Human은 grunt 하지 않고 자기 이름을 말하도록 하겠습니다.

var bob = Ext.create('Human', {
    name: 'Bob'
});

bob.speak(); //alerts 'Bob'


우리는 Human 서브클래스를 추가할 때 마법같은  함수를 사용했습니다. 느끼셨겠지만 Animal 클래스에서는 getName 함수를 정의하지 않았었습니다. 어디서 이게 왔을까요? 이 class system에서는 다음과 같은 것들을 자동으로 제공하고 있습니다.

- 현재 값을 return 하는 getter 함수, 위 경우에는 getName()
- 새 값을 세팅하는 setter 함수, 위 경우에는 setName()
- setter 에 의해 call 되는 applier 함수. 이 함수는 configuration 에 변경이 있을 때 함수를 실행할 수 있도록 해 줍니다. 위 역우에는 applyName()


getter와 setter 함수들은 자동으로 생성되고 클래스 안에서 데이터를 저장할 때 사용하시기에 좋을 겁니다. 센차터치의 모든 컴포넌트는 이 class system을 사용합니다. 그리고 이렇게 자동으로 함수들을 생성해 주니까 여러분이 config를 알면 자동으로 그 값의 get과 set을 어떻게 해야 하는지도 알게 되시는 겁니다.

이 기능은 여러분들의 코드를 더 간결하게 해 줄 겁니다. 예를 들어 만약에 유저가 Bob의 이름을 바꾸고 싶어한다면 여러분은 applyName 함수를 정의하시기만 하면 됩니다. 이 함수는 자동으로 call 되는 함수이니까요.

Ext.define('Human', {
    extend: 'Animal',

    applyName: function(newName, oldName) {
        return confirm('Are you sure you want to change name to ' + newName + '?')? newName : oldName;
    }
});


위 예제에서는 브라우저의 built in confirm 함수를 사용했습니다. 이 함수는 대화창을 보여주면서 Yes 와 No 를 선택하도록 할 겁니다. applier 함수에서 만약에 false를 return 하게 된다면 이름을 바꾸는 것을 cancel 하도록 할 수도 있습니다. 위 예제에서는 유저가 Yes나 No를 선택하게 되면 거기에 맞는 새 name 이나 기존 name 이 return 될 겁니다.

만약 No를 클릭하면 Bob의 이름은 바뀌지 않겠죠.

var bob = Ext.create('Person', {
    name: 'Bob'
});

bob.setName('Fred'); //opens a confirm box, but we click No

bob.speak(); //still alerts 'Bob'


여기까지 하면 아래와 같은 클래스에 대한 아주 중요한 부분을 이미 다 알게 되신겁니다.

- 여러분들이 만드는 클래스를 포함해 모든 클래스는 Ext.define 에서 정의합니다.
- 대부분의 클래스들은 extend 신택스를 이용해 다른 클래스를 extend 합니다.
- 클래스들은 Ext.create를 사용해서 생성됩니다. 예를 들어 Ext.create('클래스이름',{어떤:'configuration'}) 이런식입니다.
- 자동적으로 생성되는 getter와 setter를 사용하기 위해 config 신택스를 사용합니다. 그러면 코드도 한결 간결해 집니다.


이 정도 되면 여러분들은 여러분의 앱에 이미 클래스들을 생성할 수 있습니다. 그런데 class system에는 몇가지 더 주의해야 할 것들이 있습니다. class system의 유용한 다른 기능들을 사용할 수 있도록 도와주는 방법들이 몇개 더 있습니다.







Dependencies and Dynamic Loading

대부분 클래스들은 다른 클래스들에 depend on 합니다. Human 클래스는 위에서 Animal 클래스를 depend on 했죠. 왜냐하면 Human 클래스에서 Animal 클래스를 extend 했으니까요. Animal 이 Human을 정의할 수 있도록 도와 준 겁니다. 가끔 여러분들은 클래스 안에 클래스를 생성해야 될 때가 있을 겁니다. 이렇게 하려면 아래 신택스대로 하시면 됩니다.

Ext.define('Human', {
    extend: 'Animal',

    requires: 'Ext.MessageBox',

    speak: function() {
        Ext.Msg.alert(this.getName(), "Speaks...");
    }
});


이런 방법으로 클래스를 생성하면 센차 터치는 Ext.MessageBox가 이미 로드 됐는지 아닌지를 체크합니다. 그래서 로드되지 않았다면 즉시 그 파일을 AJAX를 이용해서 로드 합니다.

Ext.MessageBox는 그 안에 자신이 depend on 하는 클래스들을 가지고 있을 겁니다. 그것들은 background에서 자동적으로 로드될 겁니다. 일단 모든 required 클래스들이 로드 되면 Human 클래스는 정의된거고 여러분은 people를 instantiate 하기 위해 Ext.create를 사용하기 시작할 수 있습니다. 이것은 개발자 여러분이 개발 할 대 필요한 그런 클래스들을 직접 로드할 필요없이 다 자동적으로 문제없이 로드 된다는것을 의미합니다. 그런데 production 에서는 그렇지 않습니다. 왜냐하면 인터넷을 통해서 하나하나 로드되는것은 시간이 아주 길어질 수가 있으니까요.

production 에서는 단 1개의 JavaScript 파일만을 로드할 것을 원합니다. 단지 우리의 어플리케이션이 사용할 그 클래스만 포함되면 되죠. 이것은 JSBuilder 툴을 이용해 Sencha Touch2를 사용하면 아주 쉽게 할 수가 있습니다. 이 툴은 여러분의 앱을 분석해서 여러분이 만든 모든  클래스들과 오직 여러분의 앱이 실제로 사용하는 framework class 들만 모아서 single file build를 생성하거든요. JSBuilder를 어떻게 사용하는지 좀 더 자세하게 아시고 싶으면 Building guide를 보세요.

각각의 approach는 pros와 cons를 가집니다. 이 중에 나쁜것은 말고 그 둘의 좋은 부분만 가질 수 있을까요? 정답은 yes 입니다. Sencha Touch 2 에서는 그 solution을 implement 했습니다.

Naming Conventions

클래스와 네임스페이스 그리고 파일이름과 관련해 일관된 naming convention을 사용한다는 것은 여러분의 코드를 organize 하고 structure 하고 가독성있게 유지하는데 아주 유용합니다.

1) Classes


클래스 이름들은 오직 알파벳 글자만이 포함됩니다. 숫자도 가능하지만 그것이 어떤 전문 용어가 아닌 이상 대부분의 경우 권장되지는 않습니다. 밑줄이나 하이픈 또는 다른 알파벳이 아닌 특수문자들은 사용하지 마세요.

- MyCompany.useful_util.Debug_Toolbar 같은 형식은 추천하지 않습니다.
- MyCompany.util.Base64 같은 형식은 가능합니다.


클래스 이름들은 . (dot) 을 사용해서 관련된 것끼리 패키지를 만들어서 그룹화 해야 합니다. 최소한 거기에는 한개의 유니크한 top-level 네임스페이스가 있어야 하죠.

- MyCompany.data.CoolProxy
- MyCompany.Application


top-level 네임스페이스와 실제 클래스 이름은 CamelCase를 사용해야 합니다. 다른 것들은 소문자로 하시면 됩니다.

- MyCompany.form.action.AutoLoad

Sencha Touch에서 기본적으로 지원하는 클래스가 아니면 Ext 라는 top-level 네임스페이스를 절대 사용할 수 없습니다.

Acronyms(첫글자 이니셜)은 CamelCase convention 규칙을 따릅니다.

- Ext.data.JSONProxy 대신 Ext.data.JsonProxy 를 사용합니다.
- MyCompary.parser.HTMLParser 대신 MyCompany.util.HtmlParser 를 사용합니다.
- MyCompany.server.HTTP 대신 MyCompany.server.Http 를 사용합니다.


2) Source Files


클래스 맵의 이름은 그것이 저장돼 있는 곳의 file path를 가리킵니다. 그렇기 때문에 한 파일에 한개의 클래스만 있어야 합니다.

- Ext.mixin.Observable 는 path/to/src/Ext/mixin/Observable.js 에 저장돼 있습니다.
- Ext.form.action.Submit 는 path/to/src/Ext/form/action/Submit.js 에 저장돼 있습니다.
- MyCompany.chart.axis.Numeric 는 path/to/src/MyCompany/chart/axis/Numeric.js 에 저장돼 있습니다.


path/to/src는 여러분 애플리케이션의 클래스의 경로 입니다. 모든 클래스들은 이 경로 밑에 위치합니다. 그리고 개발과 운영,보수 등을 용이하게 하기 위해 이렇게 확실하게 네임스페이스를 따라 명명합니다.

3) 메소드(Methods)와 변수(Variables)


클래스 이름과 마찬가지로 메소드와 변수 이름들도 알파벳만을 사용합니다. 숫자를 사용할 수는 있지만 특정 용어가 아닌 이상은 권장하지 않습니다. 밑줄이나 하이픈 같은 다른 특수문자들은 사용하지 마세요.

메소드와 변수 이름들은 CamelCase를 사용합니다. acronyms 에도 마찬가지로 적용 됩니다.

아래 예제가 있습니다.

사용 가능한 메소드 이름들 :

- encodeUsingMd5()
- getHTML() 대신 getHtml() 를 사용합니다.
- getJSONResponse() 대신 getJsonResponse() 를 사용합니다.
- parseXMLContent() 대신 parseXmlContent() 를 사용합니다.


사용 가능한 변수 이름들 :

- var isGoodName
- var base64Encoder
- var xmlReader
- var httpServer


4) Properties

클래스 프로퍼티 이름은 그것이 static constant일 경우를 제외하고는 메소드나 변수이름과 같은 규칙을 따릅니다. static 클래스 프로퍼티는 모두 대분자로 표시되어야 합니다.

- Ext.MessageBox.YES = "Yes"
- Ext.MessageBox.NO = "No"
- MyCompany.alien.Math.PI = "4.13"

반응형