diff --git a/articles/2011/1294884600.html b/articles/2011/1294884600.html index 856296f..ae66ea7 100644 --- a/articles/2011/1294884600.html +++ b/articles/2011/1294884600.html @@ -64,7 +64,7 @@

disableAutomaticKeyboardDismissal 메소드는 기본적으로 input view가 사라지도록 하는 Behavior를 Override 할 수 있게 한다.

Feedback

+

UIViewController 클래스에 추가된 disableAutomaticKeyboardDismissal 메소드는 기본적으로 input view가 사라지도록 하는 Behavior를 Override 할 수 있게 한다.

Feedback

Maven에서 스크립트 사용하기

기본적으로 Maven에는 로직을 넣을 수 없다. 로직이 있으면 있는 대로 없으면 없는 대로 장단점이 있어서 일률적으로 '좋다', '나쁘다.'라고 말할 수 없다. 하지만, 나는 로직을 넣을 수 있는 것이 더 좋다. Ant도 그렇지만 Maven으로 프로젝트를 관리하다 보면 답답할 때가 잦다. 특히 자주 저지르는 실수를 검증하는 코드는 넣고 싶을 때가 잦다(항상 틀린 걸 또 틀리니까!).

+ +

Maven에 Plugin으로 스크립트를 Embed할 방법이 있는데 maven-antrun-plugin, gmaven-plugin, maven-scala-plugin이 쓸만하다:

+ +
    +
  • maven-antrun-plugin: run 골을 이용해서 ant 스크립트를 실행할 수 있다.
  • +
  • gmaven-plugin: execute 골을 이용해서 groovy 스크립트를 실행할 수 있다.
  • +
  • maven-scala-plugin: script 골을 이용해서 scala 스크립트를 실행할 수 있다.
  • +
+ +

maple
(from http://www.talismancoins.com/servlet/detail?no=920)

+ +

maven-antrun-plugin

+ +

ant도 원래 로직을 넣을 수 없다. Ant-Contrib Task를 추가하면 로직을 사용할 수 있지만 Maven->Ant Plugin->Ant-Contrib 형태로 의존성이 생기는 거라 볼썽사납다.

+ +

기본적으로 <target> 타스크의 unless 속성을 이용하면 아주 간단한 로직은 구현할 수 있다. 특정 변수가 있을 때 실행할 배치작업을 쉽게 구현할 수 있다(from http://stackoverflow.com/questions/6342071/ant-target-to-run-only-based-on-condition):

+ +
<target name="check-abc">
+    <available file="abc.txt" property="abc.present"/>
+</target>
+
+<target name="do-unless-abc" depends="check-abc" unless="abc.present">
+    ...
+</target> 
+
+ +

abc.present가 있을 때만 "do-unless-abc" 타스크가 수행된다. 특정 변수가 있을 때 실행하는 것을 조절하는 것뿐이지 로직을 구현할 수 있을 만큼은 아니다.

+ +

maven-antrun-plugin은 maven 자체로는 하기 어려운 배치작업을 구현할 때 좋다. 파일을 복사하거나 삭제하고, ssh로 원격에서 작업한다거나 하는 일을 할 때 좋다. 로직을 넣어서 검증하는 코드를 작성하기에는 좋지 않다.

+ +

javascript

+ +

최근에는 Rhino엔진이 들어가 있어서 jar파일을 추가하지 않고서도 바로 <script> 타스크에서 Javascript를 사용할 수 있지만 실제로 써보지 않았다.

+ +

더군다나 maven-antrun-plugin에서 <script> 타스크를 쓰는 것은 바람직하지 않다.

+ +

gmaven-plugin

+ +

groovy 스크립트를 실행할 수 있기 때문에 Maven 모델에 접근해서 정보를 가져와서 검사할 수 있다. 사용해본지 너무 오래됐고 이제는 maven-scala-plugin만 사용하기 때문에 정확하게 정리할 수는 없지만, 다음과 같이 할 수 있다(from http://grumpyapache.blogspot.kr/2012/08/maven-is-groovy.html):

+ +
<plugin>
+    <groupId>org.codehaus.gmaven</groupId>
+    <artifactId>gmaven-plugin</artifactId>
+    <version>1.4</version>
+    <executions>
+        <execution>
+        <phase>prepare-package</phase>
+        <goals>
+            <goal>execute</goal>
+        </goals>
+        <configuration>
+            <source><![CDATA[
+            def concat(s1, s2, t) {
+                def java.io.File f1 = new java.io.File(s1)
+                def java.io.File f2 = new java.io.File(s2)
+                def java.io.File ft = new java.io.File(t)
+                def long l1 = f1.lastModified()
+                def long l2 = f2.lastModified()
+                def long lt = ft.lastModified()
+
+                if (l1 == 0) {
+                    throw new IllegalStateException("Source file must exist:" + f1);
+                } else if (l2 == 0) {
+                    throw new IllegalStateException("Source file must exist:" + f2); 
+                } else if (lt == 0 || l1 > lt || l2 > lt) {
+                    java.io.File pd = ft.getParentFile()
+
+                    if (pd != null && !pd.isDirectory() && !pd.mkdirs()) {
+                        throw new IOException("Unable to create parent directory: " + pd)
+                    }
+
+                    println("Creating target file: " + ft)
+                    println("Source1 = " + f1)
+                    println("Source2 = " + f2)
+
+                    java.io.FileInputStream fi1 = new java.io.FileInputStream(f1)
+                    java.io.FileInputStream fi2 = new java.io.FileInputStream(f2)
+                    ft.append(fi1)
+                    ft.append(fi2)
+                    fi1.close()
+                    fi2.close()
+                } else {
+                    println("Target file is uptodate: " + ft)
+                    println("Source1 = " + f1)
+                    println("Source2 = " + f2)
+                }
+            }
+            concat("target/classes/com/softwareag/de/s/framework/demo/db/derby/initZero.sql",
+                "src/main/db/init0.sql",
+                "target/classes/com/softwareag/de/s/framework/demo/db/hsqldb/init0.sql")
+
+            concat("target/classes/com/softwareag/de/s/framework/demo/db/derby/initZero.sql",
+                "src/main/db/init0.sql",
+                "target/classes/com/softwareag/de/s/framework/demo/db/hsqldb/init0.sql")
+            ]]></source>
+        </configuration>
+        </execution>
+    </executions>
+</plugin>
+
+ +

이 예제를 왜 만들었는지는 JOCHEN WIEDMANN의 을 참고하라.

+ +

groovy는 Java랑 비슷하니까 대충 짜서 사용할 수 있다.

+ +

maven-scala-plugin

+ +

최근에 Maven에 로직을 넣을 일이 있으면 이 플러그인을 사용한다. 간단한 스크립트를 짜는 게 전부니까 maven에서 scala가 groovy보다 나을 이유는 없다. 익숙한 걸 사용하면 되는데, 최근 scala를 공부하고 있기도 하고 gmaven-plugin보다 사이트가 더 잘 정리돼 있어서 보기 편하다.

+ +

scala를 java처럼 사용해도 충분하다. scala의 현란한 문법은 몰라도 된다.

+ +
<plugin>
+    <groupId>org.scala-tools</groupId>
+    <artifactId>maven-scala-plugin</artifactId>
+    <version>2.15.2</version>
+    <executions>
+        <execution>
+            <phase>validate</phase>
+            <goals>
+                <goal>script</goal>
+            </goals>
+        </execution>
+    </executions>
+    <configuration>
+        <script> <![CDATA[
+            import java.io.File
+
+            //필요한 환경 변수가 있는지 검사.
+            if( System.getenv("MY_HOME") == null ) {
+                throw new RuntimeException( "MY_HOME variable not found ")
+            }
+
+            //NEED_DIR = "need1, need2, need3"
+            val needDirs="${NEED_DIR}".split(',')
+
+            //프로젝트 이름도 얻어올 수 있다.
+            //project 변수를 통해서 Maven 내부에 접근할 수 있고 Maven의 정보를 이용할 수 있다.
+            println(project.getName+" is the current project")
+
+            //필요한 디렉토리가 만들어져 있는지 검사.
+            needDirs.foreach(dir=>{
+                val file = new File( dir )
+                if( !file.exists() ){
+                    throw new RuntimeException( "[" + dir + "] dir not found ")
+                }
+            })
+        ]]> </script>
+    </configuration>
+</plugin>
+
+ +

validate Phase에서 내가 빠트린 것을 점검할 수 있다. 그리고 project 변수를 이용하면 더 많은 것들을 할 수 있다.

+ +

이 project의 타입은 org.scala.tools.maven.model.MavenProjectAdapter 이고 이 클래스가 제공하는 인터페이스로 Maven 정보를 이용할 수 있다. 자세한 내용은 apidoc을 봐라.

+ +

결론

+ +

maven-scala-plugin가 킹왕짱. 사견이지만, Maven에서 배치스크립트를 실행할 때는 maven-antrun-plugin이 검증코드 등 로직을 넣을 때는 maven-scala-plugin이 좋다.

Feedback

+ +
+
+
+

Copyright © 2008-2012 Dogfeet from coding to pixels, powered by Docpad

\ No newline at end of file diff --git a/articles/2012/maven/maple.jpeg b/articles/2012/maven/maple.jpeg new file mode 100644 index 0000000..b3272ba Binary files /dev/null and b/articles/2012/maven/maple.jpeg differ diff --git a/articles/2012/persist-cookie-of-uiwebview.html b/articles/2012/persist-cookie-of-uiwebview.html new file mode 100644 index 0000000..16b0656 --- /dev/null +++ b/articles/2012/persist-cookie-of-uiwebview.html @@ -0,0 +1,108 @@ +#dogfeet - UIWebView 쿠기 유지하기

UIWebView 쿠기 유지하기

애플리케이션에서 UIWebView를 사용할 때 쿠키를 저장하는 방법을 살펴본다. 쿠키를 저장하면 애플리케이션이 종료되더라도 로그인 상태 등을 유지할 수 있다. 서버가 특별히 쿠키의 지속 시간을 지정하지 않은 경우 쿠키는 애플리케이션이 종료되면(백그라운드에 남아있는 것과는 다르다) 쿠키 정보는 사라진다.

+ +

UIWebView can save and restore cookies. Although application has terminated, the cookies and the session can be restored.

+ +

cookies do not always wish to remain stacked.
cookies do not always wish to remain stacked. by klara

+ +

애플리케이션 종료시 쿠키 저장

+ +

우선 애플리케이션이 종료되는 이벤트를 잡아야 한다. 현재 멀티태스킹이 지원되는 SDK를 사용하여 애플리케이션을 만든 경우 Application Delegate의 아래 메소드가 호출된다.

+ +
- (void)applicationDidEnterBackground:(UIApplication *)application
+
+ +

멀티태스킹이 지원되기 이전 버전의 SDK나 멀티태스킹을 사용하지 않도록 설정한 애플리케이션은 다음고 같은 메소드에서 종료 이벤트를 잡을 수 있다.

+ +
- (void)applicationWillTerminate:(UIApplication *)application
+
+ +

쿠키 정보를 저장할 때 UIWebView 인스턴스는 필요 없다 [NSHTTPCookieStorage sharedHTTPCookieStorage] 메소드를 호출하면
애플리케이션에게 할당된 쿠키 저장소를 반환받는다. 즉 시스템 브라우저인 Safari나 다른 애플리케이션과 공유하지 않는 애플리케이션만의 쿠키 저장소이다. (iOS는 쿠키를 공유하지 않지만 Mac OS는 쿠키를 공유한다)

+ +
{
+    NSLog(@"%@", @"PersisteWebCookie");
+    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
+    NSData *cookieData = [NSKeyedArchiver archivedDataWithRootObject:cookies];
+    [[NSUserDefaults standardUserDefaults] setObject:cookieData forKey:@"MySavedCookies"];
+    NSLog(@"%@", @"PersisteWebCookie Saved");
+}
+
+ +

저장소에 현재 저장된 쿠키를 배열로(NSArray) 받아와서 NSUserDefaults에 저장할 수 있도록 NSKeyedArchiver를 통해 NSData 인스턴스로 변환한다. 키 값은 MySavedCookies를 사용하여 NSUserDefaults에 저장해둔다.

+ +

일반적으로 쿠키는 브라우저나 애플리케이션이 종료되면(iOS의 경우 홈버튼을 더블탭 하여 마이너스 아이콘으로 종료시키면) 쿠키 정보가 삭제된다. 하지만 위와 같이 저장한 쿠키 정보는 애플리케이션을 다시 실행시켰을 때 복구할 수 있다.

+ +

애플리케이션으로 돌아왔을 때

+ +

애플리케이션이 백그라운드에서 돌아오거나 다시 실행되는 이벤트는 보통 다음 Application Delegate의 메소드에서 처리한다.

+ +
- (BOOL)application:(UIApplication *)application 
+    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+
+ +

쿠키를 다시 되살리는 방법은 저장하는 순서의 반대로 한다. 키 값을 MySavedCookies로 하여 NSUserDefaults로부터 데이터를 꺼내오고 배열로 만든 후 하나씩 다시 쿠키 저장소에 저장한다.

+ +
{
+    NSLog(@"%@", @"PersisteWebCookie");
+    NSData *cookiesdata = [[NSUserDefaults standardUserDefaults] objectForKey:@"MySavedCookies"];
+    if([cookiesdata length]) {
+        NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesdata];
+        NSHTTPCookie *cookie;
+
+        for (cookie in cookies) {
+            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
+        }
+    }
+    NSLog(@"%@", @"PersisteWebCookie Restored");
+}
+

Feedback

+ +
+
+
+

Copyright © 2008-2012 Dogfeet from coding to pixels, powered by Docpad

\ No newline at end of file diff --git a/atom.xml b/atom.xml index 0ef214b..82ecc78 100644 --- a/atom.xml +++ b/atom.xml @@ -1,10 +1,226 @@ -<![CDATA[ 개발새발 ]]>2012-08-25T06:59:24.613Zhttp://dogfeet.github.comchangwoo-park.html.mdpismute@gmail.comsean-lee.html.mdsean@weaveus.comyongjae-choi.html.mdmage@weaveus.com<![CDATA[ Git: 델타와 스냅샷 ]]>2012-08-24T15:00:00.000Zhttp://dogfeet.github.com/articles/2012/git-delta.html우리가 커밋을 하면 그 시점의 스냅샷을 저장하는 것이고 두 시점의 스냅샷을 비교하면 델타를 얻을 수 있다. VCS는 스냅샷이나 델타를 저장하고 누가, 언제, 왜 저장했는지 등을 추적하고 관리하는 시스템이다. 실제로 저장할 때도 스냅샷을 저장하는 시스템도 있고(SVN, git) 델타를 저장하는 시스템도 있다(git, hg).

+<![CDATA[ 개발새발 ]]>2012-09-02T00:10:56.238Zhttp://dogfeet.github.comchangwoo-park.html.mdpismute@gmail.comsean-lee.html.mdsean@weaveus.comyongjae-choi.html.mdmage@weaveus.com<![CDATA[ Maven에서 스크립트 사용하기 ]]>2012-09-01T15:00:00.000Zhttp://dogfeet.github.com/articles/2012/maven-scala-plugin.html기본적으로 Maven에는 로직을 넣을 수 없다. 로직이 있으면 있는 대로 없으면 없는 대로 장단점이 있어서 일률적으로 '좋다', '나쁘다.'라고 말할 수 없다. 하지만, 나는 로직을 넣을 수 있는 것이 더 좋다. Ant도 그렇지만 Maven으로 프로젝트를 관리하다 보면 답답할 때가 잦다. 특히 자주 저지르는 실수를 검증하는 코드는 넣고 싶을 때가 잦다(항상 틀린 걸 또 틀리니까!).

-

+

Maven에 Plugin으로 스크립트를 Embed할 방법이 있는데 maven-antrun-plugin, gmaven-plugin, maven-scala-plugin이 쓸만하다:

+ +
    +
  • maven-antrun-plugin: run 골을 이용해서 ant 스크립트를 실행할 수 있다.
  • +
  • gmaven-plugin: execute 골을 이용해서 groovy 스크립트를 실행할 수 있다.
  • +
  • maven-scala-plugin: script 골을 이용해서 scala 스크립트를 실행할 수 있다.
  • +
+ +

maple
(from http://www.talismancoins.com/servlet/detail?no=920)

+ +

maven-antrun-plugin

+ +

ant도 원래 로직을 넣을 수 없다. Ant-Contrib Task를 추가하면 로직을 사용할 수 있지만 Maven->Ant Plugin->Ant-Contrib 형태로 의존성이 생기는 거라 볼썽사납다.

+ +

기본적으로 <target> 타스크의 unless 속성을 이용하면 아주 간단한 로직은 구현할 수 있다. 특정 변수가 있을 때 실행할 배치작업을 쉽게 구현할 수 있다(from http://stackoverflow.com/questions/6342071/ant-target-to-run-only-based-on-condition):

+ +
<target name="check-abc">
+    <available file="abc.txt" property="abc.present"/>
+</target>
+
+<target name="do-unless-abc" depends="check-abc" unless="abc.present">
+    ...
+</target> 
+
+ +

abc.present가 있을 때만 "do-unless-abc" 타스크가 수행된다. 특정 변수가 있을 때 실행하는 것을 조절하는 것뿐이지 로직을 구현할 수 있을 만큼은 아니다.

+ +

maven-antrun-plugin은 maven 자체로는 하기 어려운 배치작업을 구현할 때 좋다. 파일을 복사하거나 삭제하고, ssh로 원격에서 작업한다거나 하는 일을 할 때 좋다. 로직을 넣어서 검증하는 코드를 작성하기에는 좋지 않다.

+ +

javascript

+ +

최근에는 Rhino엔진이 들어가 있어서 jar파일을 추가하지 않고서도 바로 <script> 타스크에서 Javascript를 사용할 수 있지만 실제로 써보지 않았다.

+ +

더군다나 maven-antrun-plugin에서 <script> 타스크를 쓰는 것은 바람직하지 않다.

+ +

gmaven-plugin

+ +

groovy 스크립트를 실행할 수 있기 때문에 Maven 모델에 접근해서 정보를 가져와서 검사할 수 있다. 사용해본지 너무 오래됐고 이제는 maven-scala-plugin만 사용하기 때문에 정확하게 정리할 수는 없지만, 다음과 같이 할 수 있다(from http://grumpyapache.blogspot.kr/2012/08/maven-is-groovy.html):

+ +
<plugin>
+    <groupId>org.codehaus.gmaven</groupId>
+    <artifactId>gmaven-plugin</artifactId>
+    <version>1.4</version>
+    <executions>
+        <execution>
+        <phase>prepare-package</phase>
+        <goals>
+            <goal>execute</goal>
+        </goals>
+        <configuration>
+            <source><![CDATA[
+            def concat(s1, s2, t) {
+                def java.io.File f1 = new java.io.File(s1)
+                def java.io.File f2 = new java.io.File(s2)
+                def java.io.File ft = new java.io.File(t)
+                def long l1 = f1.lastModified()
+                def long l2 = f2.lastModified()
+                def long lt = ft.lastModified()
+
+                if (l1 == 0) {
+                    throw new IllegalStateException("Source file must exist:" + f1);
+                } else if (l2 == 0) {
+                    throw new IllegalStateException("Source file must exist:" + f2); 
+                } else if (lt == 0 || l1 > lt || l2 > lt) {
+                    java.io.File pd = ft.getParentFile()
+
+                    if (pd != null && !pd.isDirectory() && !pd.mkdirs()) {
+                        throw new IOException("Unable to create parent directory: " + pd)
+                    }
+
+                    println("Creating target file: " + ft)
+                    println("Source1 = " + f1)
+                    println("Source2 = " + f2)
+
+                    java.io.FileInputStream fi1 = new java.io.FileInputStream(f1)
+                    java.io.FileInputStream fi2 = new java.io.FileInputStream(f2)
+                    ft.append(fi1)
+                    ft.append(fi2)
+                    fi1.close()
+                    fi2.close()
+                } else {
+                    println("Target file is uptodate: " + ft)
+                    println("Source1 = " + f1)
+                    println("Source2 = " + f2)
+                }
+            }
+            concat("target/classes/com/softwareag/de/s/framework/demo/db/derby/initZero.sql",
+                "src/main/db/init0.sql",
+                "target/classes/com/softwareag/de/s/framework/demo/db/hsqldb/init0.sql")
+
+            concat("target/classes/com/softwareag/de/s/framework/demo/db/derby/initZero.sql",
+                "src/main/db/init0.sql",
+                "target/classes/com/softwareag/de/s/framework/demo/db/hsqldb/init0.sql")
+            ]]></source>
+        </configuration>
+        </execution>
+    </executions>
+</plugin>
+
+ +

이 예제를 왜 만들었는지는 JOCHEN WIEDMANN의 을 참고하라.

+ +

groovy는 Java랑 비슷하니까 대충 짜서 사용할 수 있다.

+ +

maven-scala-plugin

+ +

최근에 Maven에 로직을 넣을 일이 있으면 이 플러그인을 사용한다. 간단한 스크립트를 짜는 게 전부니까 maven에서 scala가 groovy보다 나을 이유는 없다. 익숙한 걸 사용하면 되는데, 최근 scala를 공부하고 있기도 하고 gmaven-plugin보다 사이트가 더 잘 정리돼 있어서 보기 편하다.

+ +

scala를 java처럼 사용해도 충분하다. scala의 현란한 문법은 몰라도 된다.

+ +
<plugin>
+    <groupId>org.scala-tools</groupId>
+    <artifactId>maven-scala-plugin</artifactId>
+    <version>2.15.2</version>
+    <executions>
+        <execution>
+            <phase>validate</phase>
+            <goals>
+                <goal>script</goal>
+            </goals>
+        </execution>
+    </executions>
+    <configuration>
+        <script> <![CDATA[
+            import java.io.File
+
+            //필요한 환경 변수가 있는지 검사.
+            if( System.getenv("MY_HOME") == null ) {
+                throw new RuntimeException( "MY_HOME variable not found ")
+            }
+
+            //NEED_DIR = "need1, need2, need3"
+            val needDirs="${NEED_DIR}".split(',')
+
+            //프로젝트 이름도 얻어올 수 있다.
+            //project 변수를 통해서 Maven 내부에 접근할 수 있고 Maven의 정보를 이용할 수 있다.
+            println(project.getName+" is the current project")
+
+            //필요한 디렉토리가 만들어져 있는지 검사.
+            needDirs.foreach(dir=>{
+                val file = new File( dir )
+                if( !file.exists() ){
+                    throw new RuntimeException( "[" + dir + "] dir not found ")
+                }
+            })
+        ]]> </script>
+    </configuration>
+</plugin>
+
+ +

validate Phase에서 내가 빠트린 것을 점검할 수 있다. 그리고 project 변수를 이용하면 더 많은 것들을 할 수 있다.

+ +

이 project의 타입은 org.scala.tools.maven.model.MavenProjectAdapter 이고 이 클래스가 제공하는 인터페이스로 Maven 정보를 이용할 수 있다. 자세한 내용은 apidoc을 봐라.

+ +

결론

+ +

maven-scala-plugin가 킹왕짱. 사견이지만, Maven에서 배치스크립트를 실행할 때는 maven-antrun-plugin이 검증코드 등 로직을 넣을 때는 maven-scala-plugin이 좋다.

]]> +
<![CDATA[ UIWebView 쿠기 유지하기 ]]>2012-08-27T00:00:00.000Zhttp://dogfeet.github.com/articles/2012/persist-cookie-of-uiwebview.html애플리케이션에서 UIWebView를 사용할 때 쿠키를 저장하는 방법을 살펴본다. 쿠키를 저장하면 애플리케이션이 종료되더라도 로그인 상태 등을 유지할 수 있다. 서버가 특별히 쿠키의 지속 시간을 지정하지 않은 경우 쿠키는 애플리케이션이 종료되면(백그라운드에 남아있는 것과는 다르다) 쿠키 정보는 사라진다.

+ +

UIWebView can save and restore cookies. Although application has terminated, the cookies and the session can be restored.

+ +

cookies do not always wish to remain stacked.
cookies do not always wish to remain stacked. by klara

+ +

애플리케이션 종료시 쿠키 저장

+ +

우선 애플리케이션이 종료되는 이벤트를 잡아야 한다. 현재 멀티태스킹이 지원되는 SDK를 사용하여 애플리케이션을 만든 경우 Application Delegate의 아래 메소드가 호출된다.

+ +
- (void)applicationDidEnterBackground:(UIApplication *)application
+
+ +

멀티태스킹이 지원되기 이전 버전의 SDK나 멀티태스킹을 사용하지 않도록 설정한 애플리케이션은 다음고 같은 메소드에서 종료 이벤트를 잡을 수 있다.

+ +
- (void)applicationWillTerminate:(UIApplication *)application
+
+ +

쿠키 정보를 저장할 때 UIWebView 인스턴스는 필요 없다 [NSHTTPCookieStorage sharedHTTPCookieStorage] 메소드를 호출하면
애플리케이션에게 할당된 쿠키 저장소를 반환받는다. 즉 시스템 브라우저인 Safari나 다른 애플리케이션과 공유하지 않는 애플리케이션만의 쿠키 저장소이다. (iOS는 쿠키를 공유하지 않지만 Mac OS는 쿠키를 공유한다)

+ +
{
+    NSLog(@"%@", @"PersisteWebCookie");
+    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
+    NSData *cookieData = [NSKeyedArchiver archivedDataWithRootObject:cookies];
+    [[NSUserDefaults standardUserDefaults] setObject:cookieData forKey:@"MySavedCookies"];
+    NSLog(@"%@", @"PersisteWebCookie Saved");
+}
+
+ +

저장소에 현재 저장된 쿠키를 배열로(NSArray) 받아와서 NSUserDefaults에 저장할 수 있도록 NSKeyedArchiver를 통해 NSData 인스턴스로 변환한다. 키 값은 MySavedCookies를 사용하여 NSUserDefaults에 저장해둔다.

-

이 글은 델타 관점으로 git을 설명하고자 작성했다. 특정 시점을 의미하는 델타와 스냅샷을 두고 git이 어떻게 저장하는지 Merge/Rebase 명령어가 실제로는 델타를 구해서 적용하는 것을 설명하고자 한다.

+

일반적으로 쿠키는 브라우저나 애플리케이션이 종료되면(iOS의 경우 홈버튼을 더블탭 하여 마이너스 아이콘으로 종료시키면) 쿠키 정보가 삭제된다. 하지만 위와 같이 저장한 쿠키 정보는 애플리케이션을 다시 실행시켰을 때 복구할 수 있다.

+ +

애플리케이션으로 돌아왔을 때

+ +

애플리케이션이 백그라운드에서 돌아오거나 다시 실행되는 이벤트는 보통 다음 Application Delegate의 메소드에서 처리한다.

+ +
- (BOOL)application:(UIApplication *)application 
+    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+
+ +

쿠키를 다시 되살리는 방법은 저장하는 순서의 반대로 한다. 키 값을 MySavedCookies로 하여 NSUserDefaults로부터 데이터를 꺼내오고 배열로 만든 후 하나씩 다시 쿠키 저장소에 저장한다.

+ +
{
+    NSLog(@"%@", @"PersisteWebCookie");
+    NSData *cookiesdata = [[NSUserDefaults standardUserDefaults] objectForKey:@"MySavedCookies"];
+    if([cookiesdata length]) {
+        NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesdata];
+        NSHTTPCookie *cookie;
+
+        for (cookie in cookies) {
+            [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
+        }
+    }
+    NSLog(@"%@", @"PersisteWebCookie Restored");
+}
+
]]> +
<![CDATA[ Git: 델타와 스냅샷 ]]>2012-08-24T15:00:00.000Zhttp://dogfeet.github.com/articles/2012/git-delta.html우리가 커밋을 하면 그 시점의 스냅샷을 저장하는 것이고 두 시점의 스냅샷을 비교하면 델타를 얻을 수 있다. VCS는 스냅샷이나 델타를 저장하고 누가, 언제, 왜 저장했는지 등을 추적하고 관리하는 시스템이다. 실제로 저장할 때도 스냅샷을 저장하는 시스템도 있고(SVN, git) 델타를 저장하는 시스템도 있다(git, hg). 이 글은 델타 관점으로 git을 설명하고자 작성했다. 특정 시점을 의미하는 델타와 스냅샷을 두고 git이 어떻게 저장하는지 살펴보고, 델타를 구해서 적용하는 것으로 Merge/Rebase 명령어를 설명해보고자 한다.

+ +

델타

@@ -68,7 +284,7 @@

Cherry-pick:

-

Cherry-pick은 특정 커밋과 그 커밋의 부모와의 델타를 구해서(그러니까 해당 커밋의 델타만) 현 브랜치에 적용하는 것이다. 고른 커밋 하나에 대해서면 Rebase하는 것이다:

+

Cherry-pick은 특정 커밋과 그 커밋의 부모와의 델타를 구해서(그러니까 해당 커밋의 델타만) 현 브랜치에 적용하는 것이다. 고른 커밋 하나에 대해서만 Rebase하는 것이다:

git-cherry-pick1

]]>
<![CDATA[ Meteor: Learn Meteor Fundamentals and Best Practices ]]>2012-08-18T15:00:00.000Zhttp://dogfeet.github.com/articles/2012/meteor-fundametals-and-best-practices.html

이름이 /로 끝났다. / 끝나는 이름은 디렉토리만 매치하겠다는 의미다. 그리고 /로 시작하지 않았기 때문에 base 디렉토리에 있는 target/ 뿐만 아니라 project/target처럼 하위 디렉토리 안에 있는 디렉토리도 매치된다.

]]> -
<![CDATA[ sbt: Getting Started Guide: Hello, World ]]>2012-07-07T15:00:00.000Zhttp://dogfeet.github.com/articles/2012/sbt-getting-started-hello.html이 글은 Getting Started sbt을 번역한 것이다.

- -

sbt

- -

소스 코드에 프로젝트 디렉토리 만들기

- -

어떤 디렉토리에 소스 파일이 하나라도 있으면 그 디렉토리는 sbt 프로젝트라고 할 수 있다. hello 디렉토리를 만들고 그 안에 다음과 같은 hw.scala 파일을 만들어 넣는다:

- -
object Hi {
-    def main(args: Array[String]) = println("Hi!")
-}
-
- -

hello 디렉토리에서 sbt를 실행하고 sbt 콘솔에서 run을 실행한다. Linux와 OS X에서는 다음과 같이 실행한다:

- -
$ mkdir hello
-$ cd hello
-$ echo 'object Hi { def main(args: Array[String]) = println("Hi!") }' > hw.scala
-$ sbt
-...
-> run
-...
-Hi!
-
- -

sbt는 관례에 따라 동작하는 것인데 다음과 같은 것을 찾는다.

- -
    -
  • Base 디렉토리에 있는 소스
  • -
  • src/main/scala 또는 src/main/java에 있는 소스
  • -
  • src/test/scala 또는 src/test/java에 있는 테스트
  • -
  • src/main/resources 또는 src/test/resources`에 있는 데이터 파일
  • -
  • lib에 있는 jar 파일
  • -
- -

sbt는 sbt를 실행하는 데 사용한 Scala 버전으로 프로젝트를 빌드한다.

- -

sbt run으로 프로젝트를 실행하거나 sbt console 명령으로 Scala REPL을 연다. sbt console은 프로젝트의 클래스패스에서 실행하는 것이라서 프로젝트 소스를 이용한 Scala 코드를 라이브로 실행 수 있다.

- -

빌드 정의하기

- -

프로젝트들은 보통 손으로 설정해줘야 한다. 프로젝트 Base 디렉토리에 build.sbt 파일을 만들고 기본 설정을 한다.

- -

예를 들어, 프로젝트 Base 디렉토리가 hello라면 hello/build.sbt 파일에 다음과 같이 만든다:

- -
name := "hello"
-
-version := "1.0"
-
-scalaVersion := "2.9.1"
-
- -

각 아이템 사이에 빈 줄이 있는데 그냥 보기 좋으라고 넣은 것이 아니다. 아이템 사이에는 꼭 빈 줄을 넣어줘야 한다. .sbt build definition에서 build.sbt 파일을 작성하는 방법을 자세히 배운다.

- -

프로젝트를 jar 파일로 패키지할 거라면 build.sbt 파일에 버전과 이름 정도는 설정할 것이다.

- -

sbt 버전 설정하기

- -

hello/project/build.properteis 파일에 어떤 버전의 sbt를 사용할지 명시할 수 있다. 다음과 같이 만든다:

- -
sbt.version=0.11.3
-
- -

0.10 버전부터는 버전이 올라가도 99% 이상 잘 호환된다. 하지만 project/build.properties에 sbt 버전을 명시하면 혹시 모를 문제를 예방할 수 있다.

]]> -
<![CDATA[ sbt: Getting Started Guide: Setup ]]>2012-07-02T15:00:00.000Zhttp://dogfeet.github.com/articles/2012/sbt-getting-started-setup.html이 글은 Getting Started sbt을 번역한 것이다.

- -

sbt

- -

Overview

- -

다음과 같은 과정을 거쳐서 sbt 프로젝트를 만든다:

- -
    -
  • sbt를 설치하고 실행할 스크립트를 만든다.
  • -
  • hello-world 프로젝트를 만든다. -
    • 프로젝트 디렉토리를 만들고 소스를 넣는다.
    • -
    • 어떻게 빌드할지 정의한다.
  • -
  • running을 통해 sbt를 실행하는 법을 배운다.
  • -
  • .sbt-build-definition에서 어떻게 빌드할지 정의하는 법을 배운다.
  • -
- -

sbt 설치

- -

sbt-launch.jar 파일과 실행할 스크립트만 있으면 된다.

- -

Note: 다운로드는 다운로드 페이지에서 할 수 있다.

- -

Yum

- -

Typesafe Yum 레파지토리에 yum 패키지가 있다. 레파지토리 rpm 패키지를 설치하면 typesafe yum 레파지토리가 승인된 소스 목록에 추가된다. 그리고 다음과 같이 실행한다:

- -
yum install sbt
-
- -

sbt의 최신 버전이 설치된다.

- -

Note: 이슈를 발견하면 여기에 신고할 수 있다.

- -

Apt

- -

Typesafe Debian 레파지토리에 sbt Debian 패키지가 있다. 레파지토리 deb 패키지를 설치하면 typesafe debian 레파지토리가 승인된 소스 목록에 추가된다. 그리고 다음과 같이 실행한다:

- -
apt-get install sbt
-
- -

sbt의 최신 버전이 설치된다.

- -

sbt 없으면 레파지토리에서 정보를 업데이트한다:

- -
apt-get update
-
- -

Note: 이슈를 발견하면 여기에 신고할 수 있다.

- -

Gentoo

- -

공식 소스 안에는 sbt용 ebuild 스크립트가 없다. 하지만 https://github.com/whiter4bbit/overlays/tree/master/dev-java/sbt-bin 에 sbt를 머지하는 ebuild 스크립트가 있다. 다음과 같이 ebuild 스크립트로 sbt를 머지한다:

- -
mkdir -p /usr/local/portage && cd /usr/local/portage
-git clone git://github.com/whiter4bbit/overlays.git
-echo "PORTDIR_OVERLAY=$PORTDIR_OVERLAY /usr/local/portage/overlay" >> /etc/make.conf
-emerge sbt-bin
-
- -

Mac

- -

MacPorts로 설치한다:

- -
$ sudo port install sbt
-
- -

HomeBrew로 설치할 수 있다:

- -
$ brew install sbt
-
- -

sbt-launch.jar를 직접 다운로드할 필요 없다:

- -

Windows

- -

msi를 다운로드한다:

- -

아니면

- -

sbt.bat 배치 파일을 만든다:

- -
set SCRIPT_DIR=%~dp0
-java -Xmx512M -jar "%SCRIPT_DIR%sbt-launch.jar" %*
-
- -

그리고 그 디렉토리에 [sbt-launch.jar][] 파일을 넣는다. 커맨드 라인에서 'sbt'라고 실행하려면 PATH 환경 변수에 sbt.bat를 등록해준다.

- -

Unix

- -

sbt-launch.jar를 다운로드해서 ~/bin 디렉토리에 넣는다.

- -

이 jar 파일을 실행하는 스크립트를 'sbt'라는 이름으로 만들고 ~/bin 디렉토리에 넣는다:

- -
java -Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=384M -jar `dirname $0`/sbt-launch.jar "$@"
-
- -

그리고 스크립트를 실행할 수 있게 만든다:

- -
$ chmod u+x ~/bin/sbt
-
- -

팁, 노트

- -

문제가 생겨서 sbt가 실행이 안되면 설치 노트를 확인하라. 터미널 엔코딩, HTTP 프록시, JVM 옵션 등에 대해 나와 있다.

- -

꼼꼼하게 만들어진 쉘 스크립트가 있어서 이 스크립트로 sbt를 설치할 수 있다: https://github.com/paulp/sbt-extras (루트 디렉토리에 있는 sbt 파일). 이 스크립트로 설치하면 패키지로 설치하는 것처럼 원하는 버전의 sbt를 설치할 수 있다. 설치할 sbt의 버전을 선택한다든지 하는 유용한 옵션이 있다.

]]>
\ No newline at end of file diff --git a/index.html b/index.html index 05940c5..1128b6f 100644 --- a/index.html +++ b/index.html @@ -1,14 +1,36 @@ #dogfeet - 개발새발

Git: 델타와 스냅샷

by Changwoo Park +

Maven에서 스크립트 사용하기

기본적으로 Maven에는 로직을 넣을 수 없다. 로직이 있으면 있는 대로 없으면 없는 대로 장단점이 있어서 일률적으로 '좋다', '나쁘다.'라고 말할 수 없다. 하지만, 나는 로직을 넣을 수 있는 것이 더 좋다. Ant도 그렇지만 Maven으로 프로젝트를 관리하다 보면 답답할 때가 잦다. 특히 자주 저지르는 실수를 검증하는 코드는 넣고 싶을 때가 잦다(항상 틀린 걸 또 틀리니까!).

+ +

Maven에 Plugin으로 스크립트를 Embed할 방법이 있는데 maven-antrun-plugin, gmaven-plugin, maven-scala-plugin이 쓸만하다:

+ +
    +
  • maven-antrun-plugin: run 골을 이용해서 ant 스크립트를 실행할 수 있다.
  • +
  • gmaven-plugin: execute 골을 이용해서 groovy 스크립트를 실행할 수 있다.
  • +
  • maven-scala-plugin: script 골을 이용해서 scala 스크립트를 실행할 수 있다.
  • +
+ +

maple
(from http://www.talismancoins.com/servlet/detail?no=920)

+ +

Read more »

UIWebView 쿠기 유지하기

애플리케이션에서 UIWebView를 사용할 때 쿠키를 저장하는 방법을 살펴본다. 쿠키를 저장하면 애플리케이션이 종료되더라도 로그인 상태 등을 유지할 수 있다. 서버가 특별히 쿠키의 지속 시간을 지정하지 않은 경우 쿠키는 애플리케이션이 종료되면(백그라운드에 남아있는 것과는 다르다) 쿠키 정보는 사라진다.

+ +

UIWebView can save and restore cookies. Although application has terminated, the cookies and the session can be restored.

+ +

cookies do not always wish to remain stacked.
cookies do not always wish to remain stacked. by klara

+ +

Read more »

Git: 델타와 스냅샷

우리가 커밋을 하면 그 시점의 스냅샷을 저장하는 것이고 두 시점의 스냅샷을 비교하면 델타를 얻을 수 있다. VCS는 스냅샷이나 델타를 저장하고 누가, 언제, 왜 저장했는지 등을 추적하고 관리하는 시스템이다. 실제로 저장할 때도 스냅샷을 저장하는 시스템도 있고(SVN, git) 델타를 저장하는 시스템도 있다(git, hg).

+

우리가 커밋을 하면 그 시점의 스냅샷을 저장하는 것이고 두 시점의 스냅샷을 비교하면 델타를 얻을 수 있다. VCS는 스냅샷이나 델타를 저장하고 누가, 언제, 왜 저장했는지 등을 추적하고 관리하는 시스템이다. 실제로 저장할 때도 스냅샷을 저장하는 시스템도 있고(SVN, git) 델타를 저장하는 시스템도 있다(git, hg). 이 글은 델타 관점으로 git을 설명하고자 작성했다. 특정 시점을 의미하는 델타와 스냅샷을 두고 git이 어떻게 저장하는지 살펴보고, 델타를 구해서 적용하는 것으로 Merge/Rebase 명령어를 설명해보고자 한다.

-

이 글은 델타 관점으로 git을 설명하고자 작성했다. 특정 시점을 의미하는 델타와 스냅샷을 두고 git이 어떻게 저장하는지 Merge/Rebase 명령어가 실제로는 델타를 구해서 적용하는 것을 설명하고자 한다.

-

Read more »

go to Archive »

Copyright © 2008-2012 Dogfeet from coding to pixels, powered by Docpad

Archive

2012 May 27
2012 Apr 29
2012 Apr 28
2012 Mar 30
2012 Jan 21
2012 Jan 08
2012 Jan 01
2011 Dec 24
2011 Dec 10
2011 Dec 02
2011 Dec 01
2011 Dec 01
2011 Nov 30
2011 Nov 22
2011 Sep 09
2010 Jan 14
2009 Nov 10
2009 Mar 16

Copyright © 2008-2012 Dogfeet from coding to pixels, powered by Docpad