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

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

카테고리


반응형
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  섹션을 보세요.


반응형

Sunshower and America's Cup in Newport RI

2012. 7. 3. 23:23 | Posted by 솔웅


반응형

요즘 회사일에만 집중하다보니 블로그에 글을 포스팅할 시간이 없네요.

지난 주말에 올린 이명박 대통령 친인척 측근 비리 글도 너무 오래 됐고...

제 블로그가 너무 정치적으로 보이고 싶지 않아서 다른 글을 올리려고 하는데..

틈틈이 번역하고 공부하고 올릴려니까 시간이 걸리는군요.

지금은 jQuery Mobile 쪽을 집중적으로 하고 있습니다.

Mobile 관련 글은 조만간에 올릴께요.

내일이 휴일(독립기념일) 이니까 글 한두개는 정리해서 올릴 수 있을 것 같습니다.

그 사이 MB의 친인척 측근 비리 관련 글을 내려놓기 위해 최근에 찍은 사진 몇장 올릴께요.


어제 퇴근하려고 창문을 봤더니 해가 쨍쨍 내리 쬐더라구요.

퇴근길에 이 맑은 날씨를 즐기면서 가겠구나 하는 기대감으로 회사 문을 열고 막 나갔는데...

굵은 비가 막 내리는거예요.

해는 내리쬐고 비는 꽤 많이 내리고 그 내린비가 금새 수증기가 되서 다시 올라가고...

이 모든 일이 동시에 이뤄지더라구요.. 신기하게... ^^

신기한 sunshower.

운전할 때도 달리는 자동차 바퀴가 일으키는 물보라마다 무지개를 만들어 내서 보기가 참 좋았어요.


지난 일요일에는 요트경기가 열리는 Newport에 다녀왔어요.

이번 America's Cup 경기대회에 한국팀이 출전한다고 그래서...


총 8개팀이 출전했는데...

한국팀이 4위를 했어요.

처음엔 하위권으로 달리다 그나마 두 세대 제치고 4위를 해서 기분이 좋더라구요.

처음에 요트들 소개할 때는 그 요트에 맞는 배경음악이 따로 나오던데...

한국 소개할 때는 윤도현 노래가 나왔어요. 제목은 잘 모르지만.......

가사는 아리랑 가사던데....

내년도에는 샌프란시스코에서 열린다고 하던데... 그때는 한국이 꼭 1등 하기를 바랍니다.

반응형


반응형

이명박 대통령 친인척 측근 비리 개요가 업데이트 됐네요.


경향신문 인포그래픽 기사에서요.


예전에도 같은 내용 올렸었는데 업데이트가 됐으니 업데이트된 내용으로 다시 올립니다.


원래 기사는 여기로 가시면 보실 수 있습니다.

여기 티스토리 블로그에는 폭이 좁아서 다 안나오네요.

오른쪽에 짤린 부분도 더 많이 있으니까 원래 기사로 보시면 전부 다 보실 수 있을 거예요.


국가를 자신들의 수익모델로 삼아서 망쳐버린 현 집권세력에 응당한 처벌이 반드시 가해졌으면 좋겠습니다.


어쨌든 저는 오늘도 열심히 프로그래밍 합니다.



반응형


반응형

jQuery Mobile and Dynamic Page Generation


jQuery Mobile은 default click hijacking behavior나 매뉴얼로 $.mobile.changePage()를 call 하는 것을 통해 다이나믹하게 DOM으로 page이 당겨져 올 수 있도록 해 줍니다. 이것은 서버사이드에서 HTML pages/fragments 를 generate 하는데 아주 좋습니다. 하지만 가끔 JSON이나 다른 포맷으로부터 클라이언트 사이드에서 page content를 다이나믹하게 generate 할 필요가 있습니다. 아마도 네트워크 광역폭이나 퍼포먼스적인 이유로 그런 일이 필요할 겁니다. 혹은 서버와 서로 소통하기 위해 서버가 선택할 데이터 포맷일 수도 있겠죠.


클라이언트 사이드에서 page markup을 generate 할 필요가 있는 어플리케이션을 위해 $.mobile.changePage() call 하는 동안 트리거되는 notification에 대해 이해하고 있는것이 중요합니다. 왜냐하면 해당 시간에 여러분의 content를 generate 할 수 있도록  navigation system 에 hook 하는것을 가능하게 해 주기 때문입니다. changePage()를 call 하게 되면 대개 아래와 같은 event notification이 trigger 됩니다.


  • pagebeforechange
    • Fired off before any page loading or transition.
    • NOTE: This event was formerly known as "beforechangepage".
  • pagechange
    • Fired off after all page loading and transitions.
    • NOTE: this event was formerly known as "changepage".
  • pagechangefailed
    • Fired off if an error has occurred while attempting to dynamically load a new page.


이런 notification들은 페이지의 parent container element(

$.mobile.pageContainer)에서 trigger 됩니다. 그리고 document element와 window에까지 계속 떠 다니게 될 겁니다. JSON이나 in-memory JS object 같은 non HTML data를 이용해서 어플리케이션에 page를 inject 하기를 원한다던가 아니면 빠르게 현재 존재하는 페이지의 내용을 modify 하기를 원한다면 pagebeforechange event 가 아주 유용할 겁니다. pagebeforechange event는 URL이나 page element들을 analyzing 하기위해 hook 할 수 있도록 해 줍니다.  어플리케이션은 load 하거나 switch 할거냐고 질문을 받게 되고 pagebeforechange event에서 preventDefault()를 call 함으로서 default changePage() behavior가 short-circuit 할지에 대해서도 질문을 받게 됩니다.




이 기술을 이용하기 위해 working sample을 한번 살펴 보시기 바랍니다. 이 샘플에서는 유저가 navigate 할 수 있는 카테고리 리스트로 메인페이지가 시작합니다. 각 카테고리의 실제 아이템들은 메모리의 javaScript object에 저장되어 있습니다. 이 데이터들은 어떤 곳에서든지 올 수가 있습니다.


var categoryData = {
	animals: {
	  name: "Animals",
	  description: "All your favorites from aardvarks to zebras.",
		items: [
			{
				name: "Pets"
			},
			{
				name: "Farm Animals"
			},
			{
				name: "Wild Animals"
			}
		]
	},
	colors: {
		name: "Colors",
		description: "Fresh colors from the magic rainbow.",
		items: [
			{
				name: "Blue"
			},
			{
				name: "Green"
			},
			{
				name: "Orange"
			},
			{
				name: "Purple"
			},
			{
				name: "Red"
			},
			{
				name: "Yellow"
			},
			{
				name: "Violet"
			}
		]
	},
	vehicles: {
		name: "Vehicles",
		description: "Everything from cars to planes.",
		items: [
			{
				name: "Cars"
			},
			{
				name: "Planes"
			},
			{
				name: "Construction"
			}
		]
	}
};


이 어플리케이션은 어플리케이션에게 어떤 카테고리 아이템이 display 되어야 하는지를 말해주는 hash를 포함한 url이 있는 링크를 사용합니다.



 <h2>Select a Category Below:</h2>
 <ul data-role="listview" data-inset="true">
    <li><a href="#category-items?category=animals">Animals</a></li>
    <li><a href="#category-items?category=colors">Colors</a></li>
    <li><a href="#category-items?category=vehicles">Vehicles</a></li>
 </ul>


내부적으로 이 링크 중 하나를 클릭하면 어플리케이션은 internal $.mobile.changePage() call을 intercept 합니다. 이 $.mobile.changePage() 는 프레임워크의 default link hijacking behavior에 의해 invoke 된 것이죠. 그러면 이제 로드되기 위해 페이지에 대한 URL을 analyze 하게 됩니다. 그리고 나서 이것이 로딩 자체만을 위한 것인지 아니면 일반적인 changePage() 코드로 처리해야 될 것인지에 대해 판단하게 되죠.

어플리케이션은 도큐먼트 레벨에서 pagebeforechange event로 binding 됨으로서 changePage() 로 그 자체를 insert 할 수 있게 됩니다.



// Listen for any attempts to call changePage().
$(document).bind( "pagebeforechange", function( e, data ) {

// We only want to handle changePage() calls where the caller is
// asking us to load a page by URL.
	if ( typeof data.toPage === "string" ) {

// We are being asked to load a page by URL, but we only
// want to handle URLs that request the data for a specific
// category.
		var u = $.mobile.path.parseUrl( data.toPage ),
			re = /^#category-item/;

		if ( u.hash.search(re) !== -1 ) {

// We're being asked to display the items for a specific category.
// Call our internal method that builds the content for the category
// on the fly based on our in-memory category data structure.
			showCategory( u, data.options );

// Make sure to tell changePage() we've handled this call so it doesn't
// have to do anything.
			e.preventDefault();
		}
	}
});



왜 도큐먼트 레벨에서 listen할까요? 간단히 말하면 deep-linking 때문입니다. 우리는 jQuery Mobile 프레임워크가 initialize 하기전에 active 되기위해 binding이 필요합니다. 그리고 어플리케이션을 invoke 한 initial URL을 어떻게 process 할지 결정하게 됩니다. pagebeforechange binding에 대한 callback이 invoke 됐을 때 callback에 대한 두번째 argument는 initial $.mobile.changePage() call에 pass 될 argument들을 포함한 data object가 될 겁니다. 이 object의 프로퍼티들은 아래와 같습니다.
  • toPage
    • transition 될 페이지를 포함한  jQuery collection object가 될 수도 있고 로드되거나 transition 될 페이지에 대한 URL reference가 될 수 있습니다.
  • options
    • $.mobile.changePage() function 함수의 caller에 의해 pass 된 옵션들을 포함한 Object
    • 옵션의 리스트는 여기에서 찾아 보실 수 있습니다.
우리의 샘플 어플리케이션에서는 URL들이 initial 하게 pass 된 changePage() calls 에 대해서만 관심이 있습니다. 그래서 우리의 callback이 하는 첫번째 일은 toPage의 type을 체크하는 겁니다 그 다음으로는 어떤 URL parsing 유틸리티의 도움을 받아서 우리가 스스로 handling 하기위해 관심을 가지고 있는 hash를 포함한 URL인가에 대해 체크를 합니다. 만약 그렇다면 showCategory()라는 어플리케이션 함수를 call 합니다. 이 함수는 URL hash에 의해 명시된 카테고리에 대한 content를 다이나믹하게 create 할 겁니다. 그리고 이벤트에서 preventDefault()를 call 할 겁니다. pagebeforechange event에서 preventDefault()를 call 하는 것은 다른 작업 없이 exit 하기 위해 $.mobile.changePage() call 을 유발하게 됩니다. 이 이벤트에서 preventDefault() method를 call 하는 것은 changePage() request를 여러분 스스로 핸들링하게되는 jQuery Mobile과 같다고 말할 수 있습니다.


preventDefault()가 call 되지 않는다면 changePage()는 평상시에 하던대로의 작업을 계속 이어나갈 겁니다. 우리의 callback에 pass 된 data object에 대해 짚고 넘어갈 부분은 여러분이 toPage 프로퍼티나 options 프로퍼티에 어떤 change를 했던지 간에 preventDefault()가 call 되지 않으면 changePage() processing에 영향을 줄 것이라는 겁니다. 예를 들어 다른 internal/external 페이지에 특정 URL을 redirect하거나 map 하고 싶다면 우리의 callback은 그 URL이나 redirect 될 페이지의 DOM 엘리먼트로 callback에 data.toPage 프로퍼티를 set 해야 합니다. 마찬가지로 우리는 우리 callback 안의 어떤 옵션에 대한 set이나 un-set을 할 수 있습니다. 그러면 changePage()는 새로운 세팅을 사용하게 될 겁니다.


이제 우리는 어떻게 changePage() call을 intercept 하는지 알게 됐습니다 이제 이 샘플 소스가 그 페이지에 대한 markup을 실제로 어떻게 generate 하는지 자세히 살펴 보겠습니다. 우리의 샘플 소스는 각 카테고리를 display 하기 위해 같은 페이지를 사용하거나 재 사용합니다. 우리의 special link 가 클릭 될 때마다 showCategory()가 invoke 됩니다.


// Load the data for a specific category, based on
// the URL passed in. Generate markup for the items in the
// category, inject it into an embedded page, and then make
// that page the current active page.
function showCategory( urlObj, options )
{
	var categoryName = urlObj.hash.replace( /.*category=/, "" ),

// Get the object that represents the category we
// are interested in. Note, that at this point we could
// instead fire off an ajax request to fetch the data, but
// for the purposes of this sample, it's already in memory.
		category = categoryData[ categoryName ],

// The pages we use to display our content are already in
// the DOM. The id of the page we are going to write our
// content into is specified in the hash before the '?'.
		pageSelector = urlObj.hash.replace( /\?.*$/, "" );

	if ( category ) {
// Get the page we are going to dump our content into.
		var $page = $( pageSelector ),

// Get the header for the page.
		$header = $page.children( ":jqmData(role=header)" ),

// Get the content area element for the page.
		$content = $page.children( ":jqmData(role=content)" ),

// The markup we are going to inject into the content
// area of the page.
		markup = "<p>" + category.description + 
"</p><ul data-role='listview' data-inset='true'>", // The array of items for this category. cItems = category.items, // The number of items in the category. numItems = cItems.length; // Generate a list item for each item in the category // and add it to our markup. for ( var i = 0; i < numItems; i++ ) { markup += "<li>" + cItems[i].name + "</li>"; } markup += "</ul>"; // Find the h1 element in our header and inject the name of // the category into it. $header.find( "h1" ).html( category.name ); // Inject the category items markup into the content element. $content.html( markup ); // Pages are lazily enhanced. We call page() on the page // element to make sure it is always enhanced before we // attempt to enhance the listview markup we just injected. // Subsequent calls to page() are ignored since a page/widget // can only be enhanced once. $page.page(); // Enhance the listview we just injected. $content.find( ":jqmData(role=listview)" ).listview(); // We don't want the data-url of the page we just modified // to be the url that shows up in the browser's location field, // so set the dataUrl option to the URL for the category // we just loaded. options.dataUrl = urlObj.href; // Now call changePage() and tell it to switch to // the page we just modified. $.mobile.changePage( $page, options ); } }


위 샘플에는 우리가 handle 하는 URL의 해쉬는 아래 두가지 부분을 포함하고 있습니다.


#category-items?category=vehicles

? 전에 있는 첫번째 부분은 content를 write할 page의 id입니다.  ? 다음 부분은 어떤 데이터가 사용되고 언제  페이지에 대한 markup을 generate 할지에 대해 알 수 있는 정보 입니다. showCategory()가 하는 첫번째 일은 이 content 를 write 할 페이지의 id를 추출하기 위해 hash를 deconstruct(해채) 하는 겁니다. 그리고 카테고리 이름은 우리의  in-memory JavaScript category object로부터 올바른 data 세트를 찾아올 때 사용됩니다. 어떤 카테고리 데이터를 사용할 지에 대한 작업이 끝난 이후 그 카테고리에 대한 markup을 generate 합니다. 그리고 그것을 그 페이지의 header와 content 부분에 inject 합니다. 그 element에 이전에 있었던 markup들은 모두 씻겨 나갑니다.


이 markup을 inject 한 이후에 막 inject 된 markup list를 잘 사용하기 위해 적당한 jQuery Mobile widget을 call 하게 됩니다. 이 과정은 styled listview에 list markup이 적용되는 일반적인 과정입니다.


이 작업이 일단 끝나면 $.mobile.changePage()를 call 합니다. 그리고 우리가 방금 modify 한 페이지의 DOM 엘리먼트를 pass 합니다. 이 페이지가 보여지기를 원한다고 프레임워크에게 말하기 위해서죠. 이제 이 부분에서 흥미로운 부분은 jQuery Mobile은 보여지는 페이지와 연관된 URL과 함께 브라우저의 location hash를 update 한다는 겁니다. 이러한 일이 일어 날 수 있는 이유는 우리가 각 카테고리에 대해 같은 페이지를 재사용했기 때문입니다. 이것은 이상적인 상황만은 아닙니다. 왜냐하면 그 페이지에 대한 URL은 그것과 관련된 특정 category 정보를 가지고 있지 않기 때문입니다. 이 문제를 해결하기 위해서는 showCategory()가 changePage()에 pass 한 options object에 대한 dataUrl 프로퍼티를 세팅해 주는 일입니다. 우리의 오리지날 URL 대신에 이것을 display 해 달라고 얘기하기 위해서죠.


여기까지가 샘플입니다. 이 샘플이 아주 좋은 예제는 아닙니다. 특히 grade가 낮아서 JavaScript가 turn off 됐을 때에는요. 이 의미는 C-Grade 브라우저에서는 제대로 작동하지 않을 거라는 겁니다. 이렇게 낮은 grade의 브라우저에서 어떻게 제대로 동작할 수 있도록 하는지에 대해서는 나중에 글을 올릴겁니다. 업데이트 된 내용을 보시려면 여기를 참조하세요.



반응형

How to Use Custom Events in Corona

2012. 6. 28. 02:46 | Posted by 솔웅


반응형

How to Use Custom Events in Corona

Posted on . Written by



1년 쯤 전에 (2011년 6월), Corona Event Model 에 대해서 다뤘었습니다. 거기서 코로나에서의 이벤트가 정확히 무엇인지 설명을 했었죠. 이벤트가 발생했을 때 어떻게 여러분이 hook 해서 코로나의 여러 기능들을 적용할수 있는지에 대해서도 다뤘었습니다.

하여간 지난번에는 코로나에서 제공하는 built-in 이벤트들에 대해서 그 API를 주로 다뤘었습니다. 그 때 제가 다루지 않았던 부분은 개발자가 스스로 custom 이벤트를 정의할 수 있다는 것입니다. 그리고 그 이벤트가 발생했을 때 listen 할 수 있다는 것하구요.(개발자 스스로 완벽하게 컨트롤 할 수가 있죠)


이 튜토리얼은 여러분만의 custom 이벤트를 어떻게 정의하고 dispatch 하는지에 대해 알려드릴겁니다.  여러분은 여러분의 게임이나 앱에 이 기능들을 적용할 수 있겠죠. 만약 여러분이 코로나 이벤트 모델에 대해서 그렇게 친숙하지 않다면 우선  The Corona Event Model Explained부분을 읽고 난 후 아래 부분을 읽기를 권장합니다.






The Scenario


이 튜토리얼의 시나리오를 한번 짜 보면 한개의 object와 하나의 player 가 있습니다. 여기에 그 건강상태와 관련된 많은 이벤트를 적용해 볼 겁니다. 우리는 이것을 health 이벤트라고 부르겠습니다. (이름은 여러분이 원하는대로 붙이시면 됩니다. 단지 다른 Corona event와 이름이 중복되거나 이미 있는 다른 custom event와 이름이 겹치지만 않으면 되요.)


Dispatching an Event


게임이 시작되면 어떻게 되는지 한번 얘기해 봐요. player의 건강은 75%일 겁니다. 그는 med pack을 집을거고 그러면 그의 건강의 100%가 될겁니다. 이 부분에서 우리는 health 이벤트를 dispatch 할 겁니다. event.type을 full로 할거구요. 여기서 여러분이 첫 번째로 할 일은 event table을 만드는 겁니다. 이 테이블은 listener 함수에 보낼 모든 데이터를 가지고 있게 될 겁니다. 일단 event table 셋업이 완료 되면 여러분은 object:dispatchEvent() 메소드를 call 할 수 있습니다.


local event = {
    name = "health",
    type = "full",
    healthPercent = 100
}
player:dispatchEvent( event )


event table에 있는 name 키는 object:dispatchEvent() 메소드에 전달될 건데요. 이게 유일하게 반드시 있어야 될 항목입니다. 나머지는 완벽하게 여러분 마음에 달려있습니다. 옵션이죠.

아래에 보면 health level이 low나 empty일 때 어떻게 health를 dispatch 하는지 보여 드립니다.


local event = {
    name = "health",
    type = "low",
    healthAmount = 10
}
player:dispatchEvent( event )
local event = {
    name = "health",
    type = "empty",
    healthAmount = 0
}
player:dispatchEvent( event )


Listening to Events


custom event에 object listen을 갖게 하는 방법은 코로나의 predefine된 이벤트에 listen을 다는 것과 똑 같이 하시면 됩니다. 간단하게 event name을 명시하고 (dispatch 했을 때 명시된 이벤트 이름이요) 그런 type의 event가 receive 됐을 때 그 함수가 call 되게 됩니다.

아래 예제는 player object가 dispatch 된 health 이벤트들에 어떻게 object listen 하게 되는지를 보여드리고 있습니다.


local function health_listener( event )
    if event.type == "full" then

        print( event.healthAmount )  -- 100
        turn_health_bar_green()    

    elseif event.type == "low" then

        print( event.healthAmount )  -- 10
        warn_player()
        turn_health_bar_red()

    elseif event.type == "empty" then

        print( event.healthAmount )  -- 0
        initiate_game_over()
    end
end
player:addEventListener( "health", health_listener )


table listener를 사용함으로서 self object로 그 object를 reference 할 수 있게 됩니다.


local function health_listener( self, event )
    if event.type == "full" then

        print( event.healthAmount )  -- 100
        turn_health_bar_green()    

    elseif event.type == "low" then

        print( event.healthAmount )  -- 10
        warn_player()
        turn_health_bar_red()

    elseif event.type == "empty" then

        print( event.healthAmount )  -- 0
        initiate_game_over()
    end
end
player.health = health_listener
player:addEventListener( "health", player )


어떻게 리스너 함수에서  healthAmount 변수가 접근 될 수 있는지 주목해 주세요. 이것이 Corona의 이벤트 모델이 진정 가치있는 부분입니다. 언제든지 이벤트의 특정 타입으로 object를 respond 하기를 원한다면 여러분은 object:addEventListener() method를 사용해서 그렇게 하실 수 있습니다. 역으로 object:removeEventListener() method를 사용해서 그 object의 listening을 stop 시킬수도 있습니다.


Things to Keep in Mind

믿으실지 모르겠지만 custom event의 dispatch와 listening 을 모두 끝냈습니다. 이제 여러분이 custom event를 사용하실 일 만 남았는데요. 몇가지 염두에 두셔야 할 것을들 정리했습니다.
  • 코로나에 이미 내장된 코로나 이벤트와 비교해서 살펴보면 custom event에서는 이벤트가 dispatch 될 때 반드시 여러분이 컨트롤 해야 합니다.
  • 코로나에 이미 내장된 코로나 이벤트와 마찬가지로 이벤트를 dispatch 되게 하기 위한 object listening을 하지 않으면 아무 일도 일어나지 않습니다.
  • object:dispatchEvent() method에 pass 된 이벤트 테이블은 name 키가 필요합니다. 그 나머지는 옵션입니다.


물론 여러분은 이벤트를 dispatching 하는 대신 direct로 함수를 call 하실 수 있습니다. 이벤트를 사용하는 가장 큰 이유는 여러분이 원하면 언제든지 그 이벤트에 대한 listening을 stop 시킬수 있다는 겁니다. (만들고 관리하고 함수를 call 할 때마다   Boolean 변수를 사용해서 항상 체크하고 하는것보다 훨씬 간편합니다.).

이벤트를 사용하는것은 또한 간단한 코딩을 지원합니다. 그러므로 유지보수를 더 수월하게 하죠. 어떤 종류의 custom 방식으로 코로나의 이벤트 모델을 사용하실건가요?




반응형


반응형

Data-url storage


navigation model은 모든 data-role="page" elements에서 data-url attribute를 maintain합니다. 이 data-url attribute는 page element의 근원을 track 하는데 사용됩니다. main application document에 embeded 된 페이지들은 모두 그들의 data-url 파라미터를 가지고 있습니다. 이것은 data-role="page"와 함께 그들의 ID로 세트 됩니다. 유일한 예외상황은 document의 첫번째 페이지에만 해당 됩니다 첫번째 페이지는 특별합니다. 왜냐하면 이 첫번째 페이지는 아이디를 가지고 있다면그 id로 addressed 되거나 document나 base URL (hash fragment가 없이)로 addressed 됩니다.

외부로 가는 페이지들은 ajax를 통해서 다이나믹하게 pull 됩니다. 그리고 그 data-url은 외부페이지와 연관된 경로로 세팅됩니다. 다른 도메인의 외부 페이지 로딩이 가능한 환경이라면 data-url은 absolute URL로 세팅 됩니다.



Auto-generated pages and sub-hash urls


어떤 플러그인들은 페이지 콘텐츠의 일부분을 deep link로 접근할 수 있는 별도의 navigable 페이지로 다이나믹하게 choose 하기도 합니다. 예를 들어 Listview 플러그인을 들 수 있습니다. 그것은 내부에 있는 UL (혹은 OL) 을 별도의 페이지로 분화합니다. 이것은 각각 data-url attribute 가 주어지게 되죠. 그래서 그것은 jQuery Mobile에서 다른 일반적인 페이지들처럼 링크가 걸릴 수 있습니다. 어쨌든 이 페이지들에 링크를 걸기 위해서는 첫번째로 서버로부터 request 되어야 합니다. 이렇게 하기 위해서 플러그인에 의해 자동 generate 되는 페이지들은 다음과 같은 특별한 data-url structure를 사용합니다.


<div data-url="page.html&subpageidentifier">


예를 들어 listview에 의해 generate 된 페이지는 다음과 같은 data-url을 가지게 될 겁니다.


 data-url="artists.html&ui-page=listview-1"


페이지가 request 되면은 jQuery Mobile은 ui-page에서 URL을 split 해야 된다는 것을 압니다. 그리고 그 key 전에 URL의 부분을 HTTP request 합니다. 위에 언급한 listview 예제의 경우 URL은 다음과 같을 겁니다. http://example.com/artists.html&ui-page=listview-1 ...

그리고 jQuery Mobile은 artists.html을 request 할 겁니다. 그 artists.html은 sub page들을 generate 하겠죠. data-url="artists.html&ui-page=listview-1" 와 함께 div도 생성할 겁니다. 그리고 나서 active page로 display 할 겁니다.

전체 URL path를  포함한 element의  data-url attribute 는 단지 &ui-page= 이후에 붙는 부분이라는 의미만이 아닙니다. 이로서 jQuery Mobile은  page data-url attributes와 매치되는 URL의 single consistent mechanism을 유지하게 되는 겁니다.


Cases when Ajax navigation will not be used


특정 상황에서 일반적인 http requests가 Ajax request 대신 사용될 겁니다. 이 경우는 external 웹사이트로 링크를 거는 경우에 해당 됩니다. 여러분은 다음과 같은 link attribute들을 통해 일반적인  http request를 사용하실 수 있습니다.

  • rel=external

  • target (with any value, such as "_blank")



Form submissions


Form submission도 navigation model을 통해서 자동적으로 처리 됩니다. 좀 더 자세한 정보는 forms section 를 참조하세요.


Using the Application Cache


jQuery Mobile에서 application cache를 사용할 때 고려해야할 사항이 있습니다. 어떤 브라우저에서는 cache에 request를 만들 때 성공하면 http status가 0를 report 할 겁니다. 이것은 에러 핸들러를 trigger하기 위해 jQuery Core의 $.ajax를 유발합니다. 이것을 해결하는 방법은 jQuery ajax pre-filter를 사용하는 겁니다. 아래와 같은 방식이 될 겁니다.(credit to jammus for the snippet):


$.ajaxPrefilter( function(options, originalOptions, jqXHR) {
  if ( applicationCache &&
       applicationCache.status != applicationCache.UNCACHED &&
       applicationCache.status != applicationCache.OBSOLETE ) {
       // the important bit
       options.isLocal = true;
  }
});



isLocal을 true로 해서 ajax request가 return 값이 0인 경우 다르게 처리하도록 jQuery Core에 alert 하게 합니다. Local request들은 비슷한 현상이 일어날 겁니다. (예: 0 status) 그리고 Core는 xhr responseText attribute의 content 에 근거해서 성공여부를 결정하기 위해 fall back 할 겁니다.


위와 관련해 한가지 알아두셔야할 점은  manifest 던지 아니던지 가리지 않고 ajax를 통해 만들어진 모든 request들에 대해 isLocal을 true로 세팅할 거라는 겁니다. 그렇게해서 cache가 valid 되는 겁니다. Core가 uncached result에 영향을 주지 않도록 status가 0 일 때 isLocal 값을 컨트롤하기 때문에 지금은 이렇게 작동을 합니다. 하지만 앞으로도 isLocal 이 0 status 값을 처리하기 위한 목적으로만 사용될 지는 보장할 수 없습니다. 만약 그 부분이 바뀌면 여러분의 어플리케이션은 문제를 일으킬 수 있습니다.



Known limitations


jQuery Mobile's page navigation model에 의해 생성된 non-standard environment는 페이지를 만들 때 주의해야 할 아래와 같은 상황들이 있습니다.


  • filename url 없이 디렉토리에 링크를 걸 때 (예를 들어 href="typesofcats/index.html 라고 하지 않고  href="typesofcats/라고 했을 때 ) 여러분은 반드시 trailing slash를 제공하셔야 합니다. 왜냐하면 jQuery Mobile은 url의 / 이후의 글자를 파일이름으로 생각하기 때문입니다. 그렇게 되면 / 이후의 부분은 나중에 참조할 때 사라지게 됩니다.

  • Ajax에 의해 로드된 document는 JQM 페이지 엘리먼트로서 로드 된 document의 DOM에 있는  첫번째 페이지가 select 될겁니다. 그래서 개발자는 로드된 페이지의 ID attribute와 child element를 잘 관리 해야 합니다.  그래야 DOM을 다룰 때 혼란스럽지 않습니다.

  • multipage document에 링크를 걸려면 그 링크에 반드시 data-ajax="false"를 하셔야 합니다. 이렇게 함으로서 Ajax request 에서 로드된 첫번째 페이지만 사용하는 제한을 벗어나서 full page를 사용하게 됩니다. 이 multi-page document를 로드할 수 있도록 하는 툴인 subpage plugin 이 있습니다.

  • jQuery Mobile-driven site에서 페이지에 의해 참조되는 unique assets는 page element 내부에 위치해 있어야 합니다. (page의 data-role attribute의 element). 예를 들어 별도의 페이지로 존재하는 styles와 scripts로의 링크 같은 경우 div 안에서 reference 될 수 있습니다. 어쨌든 바람직한 접근법은 특정 페이지가 로드될 때 특정 script를 실행하기 위해서 jQuery Mobile's page events를 사용하는 겁니다. NOTE : 이미 markup에서 특정된 data-url로 서버로부터 페이지를 return 받을 수 있습니다. 그리고 jQuery Mobile은 hash update를 할 겁니다. 이것은 여러분이 trailing slash로 directory path를 resolve 할 수 있도록 해 줍니다. 그래서 나중에 base url path가 사용될 수 있도록 합니다.

  • 역으로, non-unique assets (site 범위에서 사용되는)의 경우엔 HTML 도큐먼트의 <head> 섹션에서 reference 되어야 합니다. 적어도 page element의 밖에서 reference 되어야 합니다. 그래야지 그 script가 한번 이상 실행되는 것을 방지할 수 있습니다.

  • sub-hash url references에서 사용되는 "ui-page" key name은 여러분이 원하는대로 그 값을 세팅할 수 있습니다. 이 값은 jQuery.mobile.subPageUrlKey에 저장 됩니다.

  • push state plugin 이 enable 된 상태에서 내부나 외부 도큐먼트로부터 jQuery Mobile document로 back 될 때 어떤 브라우저는 잘못된 도큐먼트나 어떤 잘못된 원인이라고 해서 popstate 이벤트를 load하고 trigger 합니다. 여러분이 외부 document를 계속 링크를 걸어야 한다면 이 pushstate support를 disable 시키실 필요가 있습니다.

  • jQuery Mobile은 query parameter를 internal/embedded 페이지로 passing 하는 것을 지원하지 않습니다. 하지만 이 기능을 지원하도록 하는 두개의 플러그인이 있습니다. 가벼운 플러그인으로는 page params plugin이 있고 여러 기능을 제공하는 것으로는 jQuery Mobile router plugin이 있습니다. (이것은 backbone.js나 spine.js를 사용할 수 있도록 합니다.)

  • Back button behavior를 방지하기 위해 URL hash를 사용할 때 traditional anchor link(#foo)를 사용하는 것이 지원되지 않는 페이지를 jump down 하기 위해 page anchor를 사용합니다. scroll eventlistener trigger 하지 않고 특정 Y position을 scroll 하는 방법으로 silentScroll를 사용하는 방법이 있습니다.  yPos argument를 pass해서 그 Y location으로 scroll 할 수 있습니다.


반응형


반응형

jQuery Mobile's navigation model


jQuery Mobile 에서 page는 data-role 어트리뷰트를 page로 세팅한 엘리먼트(대개 div)로 구성됩니다. header,content,footer라는 role과 함께 div 엘리먼트를 주로 사용하게 되는데 일반적인 마크업이나 form 그리고 jQuery Mobile 위젯들을 포함하고 있습니다.


page 로딩의 기본적인 흐름은 아래와 같습니다.
첫째로 페이지는 일반적인 HTTP request 로 request 됩니다. 그리고 나서 그 다음 page들이 request 되고 page의 DOM으로 inject 됩니다. 그래서 DOM은 한번에 그 안에 여러개의 page들을 가지고 있게 됩니다. 그 페이지들은 data-url 어트리뷰트의 링크를 통해 re-visited 될 수 있습니다.


url이 initially request 됐을 때 그 response로 한개 이상의 page들이 있을 겁니다. 그 중에서 가장 첫번째 page가 보여집니다. 한개 이상의 페이지를 저장하는 것의 장점은 다시 방문할 가능성이 있는 page들에 대해 pre-fetch 할 수 있다는 것입니다.





Hash and Ajax driven page navigation


디폴트로 jQuery Mobile의 모든 navigation은 location.hash를 바꾸고 업데이트 하는 방법을 사용합니다. page change는 현재의 page와 다음 page 간의 부드러운 화면 전환을 할 수 있도록 해 줍니다. 그것이 DOM에 있는 페이지 이든 아니든 Ajax를 통해서 자동적으로 로드 됩니다.


jQuery Mobile에 의해 생성된 해쉬값들은 로드된 첫번째 실제 페이지의 URL과 연관된 full path를 사용합니다. 해쉬는 언제나 valid URL로서 유지가 됩니다. 그래서 jQuery Mobile의 어떤 페이지라도 즐겨찾기를 하거나 link로 연결할 수 있습니다. non-hash-based URL을 retrieve 하려면 간단하게 그 주세에서 #를 없애고 page를 refresh 하면 됩니다.


일반적으로 hash changes는 jQuery mobile에서 링크가 클릭 됐을 때마다 생성됩니다. 링크가 클릭되면 jQuery mobile은 그 링크가 local URL을 참조하고 있다는 것을 확인하고 만약 그렇다면 링크의 디폴트 click behavior를 Ajax를 통해서 url이 참조되도록하는 request나 상황이 일어나지 않도록 방지하게 도비니다 . 페이지가 성공적으로 return 되면 새 페이지의 relative url로 location.hash가 새로 세팅될겁니다.


click이외에 독립적으로 hash changes가 일어나는 경우, 예를 들어 유저가 back 버튼을 클릭했을 때라던지 할 때는 hashchange event에 의해 처리 됩니다. 이것은 Ben Alman의 hashchange special event plugin (jQuery Mobile에 include 돼 있음)를 사용해서 window object를 bound 합니다. hash change 가 일어나면 (혹은 첫번째 페이지가 로드될 때) hashchange event handler는 location.hase를 $.mobile.changePage() function으로 전달할 겁니다. $.mobile.changePage() function는 참조페이지를 로드하던가 reveal 하게 됩니다.


한번 그 참조 페이지가 DOM에 탑재되게 되면 $.mobile.changePage() function은 현재 active page와 새로운 페이지 사이에서 화면전환을 적용시키게 됩니다. Page transition은 CSS 애니메이션을 추가하거나 remove 함으로서 작동시키게 됩니다. 예를 들어 slide-left transition은 현재 페이지에는 "slideleft" 클래스를 적용하게 되고 그 다음에 "out" 하게 됩니다. 그리고 새로오는 페이지에는 slideleft 와 in 클래스가 적용 됩니다. 그리고 ui-page-active 도 새로 적용되서 새로운 페이지가 보여지도록 mark를 합니다. 이 애니메이션이 완료되면 in 과 out 클래스들은 remove 됩니다. 그리고 원래 있던 페이지는 ui-page-active 를 잃게 됩니다.


pushState plugin


이것은 옵션 기능인데요, 조금 전에 언급했던 hash-based URL 보다 긴 full document path를 다루고 URL structure에 Ajax tracking transparent를 만듭니다. 이것은 Ajax 링크에 대한 hash-based URL system 의 top에서 좀 더 enhance 된 기능을 제공하려고 만들어 졌습니다. 이름은 이렇지만 이 기능은 현재 버전에서는 기술적으로 history.replaceState (not history.pushState)을 사용해서 hash-based urls을 convert 한다는 것을 유념해 두세요. history.replaceState 를 지원하지 않는 브라우저나 이 기능이 가능하지 않은 경우에는 hash-based URL이 대신 사용될 겁니다.


DOM이 full 로드 됐을 때 플러그인이 initialize 되면 글로벌 configuration option$.mobile.pushStateEnabled 를 document가 준비되기 전에 언제든지 false로 세팅함으로서 이것을 enable 시키거나 disable 시킬 수 있습니다.



Important: rel="external" and $.mobile.ajaxEnabled=false


다양한 브라우저에서 replaceState API의 약간 다른 implementation은 특정 상황에서 이상하게 동작할 수도 있습니다. 예를 들어 어떤 브라우저(데스크탑 브라우저도 포함해서)의 implementation은 외부 링크일 경우나 링크가 이미 pushed/replaced 상태인 페이지로 move back 할 경우  popstate event 가 다르게 implement 됩니다. ajax navigation이 명시적으로 disable 된 jQuery Mobile 어플리케이션이 빌드 될 때 pushState feature 를 disable 시키라고 권고 합니다. 이는 hash based navigation의 좀 더 나은 consistent를 유지할 수 있도록 하기 위해서 입니다. - ajax navigation은 링크에 rel="external" 을 사용해서 disable 시킬수도 있고 $.mobile.ajaxEnabled=false 를 통해서 Ajax navigation을 완전히 disable 시킬 수도 있습니다. -



changePage


프레임워크에서 page changes는 - 페이지가 DOM에 이미 있던지 Ajax를 통해서 로드될 필요가 있던지 - $.mobile.changePage() 함수를 사용합니다. $.mobile.changePage() 에는 페이지를 transition 하는데 필요한 모든 로직이 있습니다. 그리고 page not found 같은 다양한 response 상태에 대해 어떻게 handle 할지에 대해서도 포함하고 있습니다.


$.mobile.changePage()는 externally call 될 수 있고 다음과 같은 argument들을 받을 수 있습니다. (to, transition, back, changeHash). to argument는 스트링(file url, local emdment의 ID 등), 배열(배열의 첫번째 아이템은 화면 전환할 from 페이지이고 두번째 아이템은 to 페이지 임) 혹은 객체(with expected properties: url, type ("get" or "post"), and data (for serialized parameters))를 받을 수 있습니다. 후자의 것은 form data이 경우에 유용하게 페이지를 로딩할 수 있습니다. transition argument는 slide 같이 transition 이름을 스트링으로 받습니다. 그리고 back argument는 transition이 순방향으로 진행할지 역방향으로 진행할지를 boolean을 통해서 지정할 수 있습니다. 마지막으로 changHash argument는 url이 성공적으로 페이지가 변환 된것에 따라 update 할지 여부에 대해 boolean을 사용해서 정합니다.


$.mobile.changePage() function은 jQuery Mobile에서 아주 많이 사용됩니다. 예를 들어 링크가 클릭 됐을 때 그것의 href attribute가 normalize 되고 나서 $.mobile.changePage() 이 나머지를 처리합니다. form 이 submit 됐을 때는 jQury Mobile은 아누 간단하게 몇개의 form의 attribute를 수집합니다. 그리고 그것을 serialize 하고 다시한번 $.mobile.changePage()이 submission과 response를 처리합니다. 또한 dialog를 생성하는 링크도 $.mobile.changePage() 를 사용해서 해당 페이지를 hash에 대한 update 없이 open 합니다. 이것은 history tracking 할 때 dialog를 제외시키는데 유용하게 사용됩니다.


Base element

jQuery Mobile's page navigation model의 또 다른 key point는 base element 입니다. 이것은 head에 삽입되고 모든 page change할 때 modify 됩니다. 이것의 역할은 모든 assets(이미지, CSS, JS 등) 이 정확한 경로를 통해 request 될 것인지에 대한 page 참조를 담당합니다. base emement에 대한 다이나믹 업데이트를 지원하지 않는 브라우저에서는 (파이어폭스 3.6 등) jQury Mobile은 base path를 기반으로 페이지와 prefix된 그들의 href 그리고 src sttribute 등의 assets를 참조해서 루프를 돕니다.


Developer explanation of base url management:

 jQuery Mobile은 generate된 절대 URL 경로와 generate된 <base> element의 href attribute 의 조합을 사용해서 http request를 관리합니다. 이 두 개의 조합은 로드되는 페이지의 full path를 포함하는 URL을 생성할 수 있도록 해 줍니다. base element는 이 로드된 페이지들에 의해 정확한 direct asset request를 만듭니다.


TODO: internal base와 urlHistory object의 decriptiond을 update 하세요.



반응형

iOS 웹클립에 관한 팁

2012. 6. 25. 21:51 | Posted by 솔웅


반응형

매니저인 Patrick이 휴가 가면서 웹사이트 링크를 메일로 보내주고 같습니다.
거기에는 iOS에서 사용되는 WebClip 에 대한 소개글이 있더라구요.

imore.com이라는 사이트인데 여러가지 개발 관련 팁 정보가 많이 있는 곳 같아요.


WebClip에 대한 내용은 이미 알고 있었지만 이렇게 따로 정리 해 두면 나중에 좀 더 도움이 될 수 있을 것 같아서 정리해 두기로 했어요.


그리고 외국 동료들이 알려주는 웹 싸이트는 네이버등 한국 검색엔진을 통해서 얻어지는 정보 이외에 추가적으로 정보를 얻을 수 있는 source가 될 수 있더라구요.


좀 더 풍부한 정보 소스를 확보 할 수 있는 잇점이 있어요.

(이 글을 읽는 분들에게도 도움이 되시길 바래요)


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


Ninja tip: How to create a custom iPhone/iPad home screen icon for your website

By , Friday, Nov 26, 2010 at 2:54 pm





Add to Homescreen 을 눌렀을 때 iPhone, iPod touch, iPad 에 웹사이트의 아이콘이 만들어서 보여지는데 관심 있으세요? 방문자들이 당신의 웹 사이트의 WebClip을 그들의 홈 스크린에 추가해서 볼 수가 있습니다. 그들은 그것을 친구들한테 보여 주겠죠? 그 친구들도 홈스크린에 웹 클릭을 추가할거고 여러분의 웹사이트는 구글 Page ranks에서 보여질 겁니다.

올해에 애플이 아이패드와 새로운 Retina Display 해상도를 선보였죠? 그러면 여러분은 더 큰 사이즈의 아이콘을 준비하셔야 할 겁니다.

• 120X120 사이즈의 아이콘이 iPad와 아이폰 4에 알맞는 아이콘 이미지 크기 입니다. 이 크기의 아이콘을 만드세요.
• 테두리에 둥근 처리 하는 것은 걱정하지 마세요. 애플이 자동적으로 해 줄겁니다. 그리고 손톱 모양의 shiny 효과도 자동적으로 해 줄거구요.


아이콘은 아래처럼 될 겁니다.



•  근사한 아이콘을 만들고 난 후 이것의 이름을 apple-touch-icon.png 로 명명하세요.
•  이제 이것을 여러분 웹사이트의 root 디렉토리에 업로드 하세요. 아마 아래와 같이 경로가 되겠죠.
http://www.yoursite.com/apple-touch-icon.png


이제 됐습니다. 아주 쉽죠?

이제 방문자가 아이폰이나 아이팟 터치 혹은 아이패드로 여러분의 사이트를 보다가 action 버튼(iOS 4.2 이하의 버전에서는  the "+" button 임)을 누르고 Add to Home Screen을 선택하게 될 겁니다. 그러면 방문자의 앱 목록에 여러분 사이트의 웹클립이 생성되겠죠. 이제 그 웹클립 아이콘만 누르면 한번에 여러분 사이트를 방문할 수 있습니다. 그러면 여러분 사이트는 더 많은 방문자를 기록하겠죠. 이 간단하고 소박한 기능을 절대 평가 절하하지 마세요. 





Bonus tip : 여러분 사이트에 custom icon을 생성하지 않으면 애플은 그 사이트의 페이지에 대한 screenshot으로 아이콘을 만들겁니다. 그 페이지는 Add to Home Screen을 할 때 오픈했던 페이지가 될겁니다.

UPDATE: Update : Marc EdwardsCampaign Monitor 에서 Jesse Dodd's article의 아티클에대해 다음단계로 웹 아이콘을 어떻게 생성하는지에 대해 알려 주었습니다.



나는 각 iOS 기계들의 해상도에 맞게 3개의 아이콘 이미지를 만들었습니다. iPhone 3G/3GS 에 대해서는 163dip를 iPad에 대해서는 132dpi를 그리고 iPhone4에 대해서는 326dpi 이미지를 만들었습니다.

<link rel="apple-touch-icon-precomposed" media="screen and (resolution: 163dpi)" href="/link/to/iOS-57px.png" />
<link rel="apple-touch-icon-precomposed" media="screen and (resolution: 132dpi)" href="/link/to/iOS-72px.png" />
<link rel="apple-touch-icon-precomposed" media="screen and (resolution: 326dpi)" href="/link/to/iOS-114px.png" />


위의 코드를 보시면 제가 apple-touch-icon-precomposed를 사용하신 것을 보실 수 있으실 거예요. -precomposed를 붙이면 iOS에서 자동적으로 만들어 지는 손톱모양의 shiny 효과와 코너 round 효과를 보여주지 않도록 할 겁니다. 만약 이 효과를 적용하고 싶으시면 이 부분을 빼면 됩니다. 그러면 여러분은 그냥 평면 이미지만 제공해도 iOS에서 자동적으로 처리를 해 주겠죠. 여러분이 직접 효과를 넣어서 더 예쁘게 하고 싶으시면 -precomposed 부분을 넣으시면 되구요.


더 자세한 것을 알고 싶으시면 전체 아티클을 읽어 보세요.

이제 방법을 아셨나요? 질문이 있으시면 댓글로 남겨 주세요. 만약 여러분 사이트에 훌륭한 새 아이콘이 생겼다면 저희에게 알려 주세요. 저희도 체크해 보게요.

Tips of the day 코너는 초보자부터 숙련자까지의 개발자들에게 도움이 되는 내용을 전해 드립니다. 이 팁을 이미 알고 계셨더면 다른 친구들에게 도움이 될 수 있도록 링크를 알려 주세요. 만약에 여러분만의 팁이 있으시다면 댓글로 알려주시거나 dailytips@tipb.com 으로 내용을 보내 주세요. (아주 훌륭하고 이전에 알려지지 않은 팁이라면 상품을 드립니다.)



반응형


반응형


Data Architect









Data Modeling Architect











반응형


반응형

phonegap-android-terminal-quickstart


이 글은 PhoneGap 0.9.2 와 0.9.3 시절의 튜토리얼 입니다. 지금은 폰갭 버전이 1.8.1이네요. 이점 감안하시고 보세요.

 

Requirements

 

이 글은 이미 안드로이드 SDK를 인스톨 했고 제대로 작동 되는 상황에서 직접 해 보실 수가 있습니다. 아직 안됐으면 먼저 Android SDK를 설치 하시고 진행하세요. 여기에서 다운로드 받으시면 됩니다. 그리고 최소한 한개 이상의 Android virtual device(AVD)를 생성해 놓으셔야 합니다. 안드로에드 에뮬레이터에서 여러분이 만든 프로젝트를 돌릴려면 AVD가 필요합니다. 그리고 여러분 system path에 Android tools와 android platform-tools 폴더 가 있어야 합니다. 이 두개의 폴더들은 여러분의 Android installation directory안에 있을 겁니다.


 

또한 폰갭도 필요하겠죠.

  • Download the latest copy of PhoneGap and extract its contents. 이글은 Android에 대한 튜토리얼이기 때문에 Android 디렉토리에 있는 내용이 중요합니다.
  • ant가 인스톨 돼 있어야 합니다. 필요하면 system path에 ant installation의 bin 폴더를 추가하셔야 합니다. 환경변수 ANT_HOME을 ant가 인스톨 된 폴더로 지정해 주세요.

 

 

Building The Sample Project

 

터미널에서 새로 다운로드 받은 폰갭을 찾아보세요. 그리고 android/sample 폴더로 가세요.

 

커맨드라인에서 android list targets를 타입해서 target 리스트를 보세요.

 

그리고 android update project -p . -t # 를 타입하세요. 그러면 필요한 파일들이 추가되거나 업데이터 될 겁니다. 위 명령어 중에서 # 는 ID로 바꿔주세요.




이제 에뮬레이터를 실행시키거나 device를 plug in  해 주세요. device를 plug in 하시는 편이 더 낫습니다. 그러면 아래 2 screen에 대한 과정은 넘어 가셔도 됩니다.

 

에뮬레이터는 Android AVD manager 와 함께 실행되고 커맨드라인에서 android라고 치면 됩니다.




원하는 virtual device를 선택하세요.



에뮬레이터가 다 로딩 될 때까지 기다리시고.

 그리고 build 하고 run  하시려면 터미널에 ant debug install을 타입하시면 됩니다.

  이제 여러분은 로드된 샘플 앱을 에뮬레이터를 통해 보실 수 있습니다.



Notes

 

가끔 and debug install이 실패할 수도 있습니다. 이럴 때는 터미널에 adb kill-server 를 하시고 adb start-server를 하세요. 그리고나서 adb-devices를 치시면 연결된 devices를 보실 수 있습니다.


샘플 프로젝트를 보실 수 있으시면 index.html을 마음대로 수정하시고 다시 실행 해 보세요.

 

안드로이드에서 디버그하기에 좋은 툴은 logcat 입니다. 이 logcat 을 사용하려면 터미널에서 adb logcat 을 치세요.


반응형