[iPhone Dev] Date Formatter

No Comments

맨날 뒤지기 싫어 괜찮은 링크 겁니다.

하단 링크를 가면 더 많은 관련 포스트들이 있죠.
Date Formatter Examples – Take 2: Format Strings

[iPhone Dev] 분석 종결자 Google Analytics로 아이폰 앱 통계 분석하기~

No Comments

여러 광고 플랫폼들을 이용하면 어느 정도 앱 다운로드나 사용 빈드를 분석을 할 수 있습니다만.. 좀 부족한 부분이 많죠?

블로그나 사이트의 통계를 분석해주는 종결자 Google Analytics를 아이폰 앱 분석에 사용하면 아래와 같은분석 데이터를 아이폰 앱에서도 얻을 수 있습니다~

(물론, 예전부터 이 방법이 소개되었었죠. 저도 몇 번 말했지만… 아무튼 테스트를 한 번 해보고 포스팅해봅니다~)

 

방문자 수가 앱 사용자 수가 되겠죠?

여기에 국가별 통계, 사용 시간 등등 아주 유용한 정보를 얻을 수 있을 것입니다.

( -_-; 아래 정보는 이 블로그의 정보이고요)

방법은
1. 웹 페이지를 하나 만듭니다.
Google Analytics가 폴더 단위로 분석하기 때문에, 도메인을 하나 만들긴 좀 그렇고, 폴더를 하나 만들면 되겠죠?
그 폴더에 index.html을 하나 만듭니다.
2. Google Analytics에 분석할 사이트 (위에서 만든 폴더까지의 경로로)를 등록하면 추적 스크립트 코드를 줍니다.
3. 이 추적 코드를 ’1′ 에서 만든 index.html에 넣어 줍니다.
4. 아이폰 앱에서 webview를 하나 (window 위에다 살짝 올려서 숨겨두면 되겠죠? ) 띄워 줍니다.
앱이 처음 시작하거나, 포 그라운드로 오거나 할 때 webview로 ’1′에서 만든 페이지를 열어 주면 되겠죠?
좀 더 세심한 분석을 원하면 원하는 view로 진입할 때 마다 불러줘도 되겠죠?
테스트 앱을 만들어서 해보니 잘 되더군요 ^^

[iPhone Dev] RAY WENDERLICH 이 아이폰을 떠나서 안드로이드로 간다고 합니다 ㅜㅜ

2 Comments

Mobile Orchard 가 포트팅을 중단했을 때 만큼의 충격이군요.

Ray Wenderlich 이름은 생소할 수 있어도 그의 블로그 를 가보시면 “아 여기, 날 살려준 글들이 있던 그곳?” 이라는 말이 나올 것입니다.

(자신도 이야기하지만) 글도 잘 쓰고, 꾸준히 튜토리얼 형식으로 깊이있게 또 친절하게 설명해주던 그가 아이폰을 떠나 안드로이드 개발을 하겠다고 합니다.

You can now call me Ray-droid!

Why I’m Ditching iOS and Becoming an Android Developer

 

(최소한 저로써는) 앱 스토어가 하나라서 편하고, 화면 해상도가 (아직은) 두 개라서 좋고, 디바이스도 다양하지 않고, 명확한 C/C++ 스타일의 Objective C가 좋다는 장점들을 완전하게 단점으로 이야기하는 그를 보면, 진정한 Indie 개발자인가라는 생각이 됩니다.

ㅜㅜ 하지만, 한국이면 부산이라도 찾아가 소주 한 잔 기울이면서 “아직은 떠나지 말아줘” 라고 이야기 하고 싶군요.

그는 “라면을 거론하면서 떠났습니다”

We all know that if you’re a true indie developer, all you need is some ramen, a cup of hot water, and a heart bursting with a passion for making apps.

 

개인적인 해석은,

아이폰으로 성공도 했고 (돈과 명예), 애플 앱 스토어의 제약 등도 좀 질려서, 좀 더 자유로운 (그 것이 꼭 안드로이드는 아니더라도) 곳으로 가려는 것같습니다.

“아이폰, 안드로이드, HTML5 모든 것은 “도구” 라고 생각합니다. 자신의 아이디어나 지식을 표현하기 위한 도구요. 그 것이 현재의 상황에서 아이폰이 적합한 것이고, 다른 것이 더 좋거나 필요하면 도구를 바꿀 수 있는 것이겠죠”

[iPhone Dev] XCode에서 실행할 때마다 올라오는 Debug Area 및 좌측 Navigator 조절하기

No Comments

실행을 하면, 항상 아래 쪽의 Debug Area (콘솔창같은)가 올라오고, 좌측의 Navigator가 바뀝니다.

( -_-; 항상 Shift + Cmd + Y로 콘솔 내리기가 짜증나죠)

설정을 찾아보니 아래와 같이 “Behaviors”에서 Run 시의 행동을 설정할 수 있었습니다.

즉, 아래 “Run generates output”에서 “Show navigator”와 “Show Debug Area”의 체크를 풀어 주면 됩니다.

[iPhone Dev] NSDictionary, NSArray 등의 저장에 대해

No Comments

NSUserDefaults를 이용해서 NSString 기반으로 앱의 데이터를 저장하는 것은 손쉽지만, NSDictionary나 NSArry 등의 데이터를 저장하기는 불편할 것입니다.

NSPropertyListSerialization을 이용하는 방법을 주로 사용했었는데요, NSDictionary의 writeToFile:automatically과 dictionaryWithContentsOfFile: 을 이용해서 좀 더 직관적으로 하는 것도 좋을 것 같아서 포스팅 해봅니다.

 

[1] NSDictionary의 writeToFile:automatically과 dictionaryWithContentsOfFile: 이용

저장할 때는 writeToFile:automatically을 불러올 때는 dictionaryWithContentsOfFile: 을 이용하면 될 것입니다.

그리고 NSString의 stringByExpandingTildeInPath을 이용해서 Documents의 path도 쫌 더직관적으로 얻어 오면 다음과 같은 코드가 만들어질 것입니다.
[저장하기]

-(void)saveDic:(NSMutableDictionary*)aDic ForKey:(NSString*)aKey {
if( aDic == nil || aKey == nil ) {
return;
}

NSString* dataPath = [[NSString stringWithFormat:@"~/Documents/%@", aKey] stringByExpandingTildeInPath];

[aDic writeToFile:dataPath atomically:YES];

}

 

[불러오기]

-(NSMutableDictionary*)loadDicForKey:(NSString*)aKey {
if( aKey == nil ) {
return nil;
}

NSString* dataPath = [[NSString stringWithFormat:@"~/Documents/%@", aKey] stringByExpandingTildeInPath];

return [NSMutableDictionary dictionaryWithContentsOfFile:dataPath];
}

 

[사용 예]

NSPropertyListSerialization 의 사용에도 마찬가지지만, (실수에 의한) memory leak을 막기 위해서 데이터를 가지고 있는 object는 property로 처리하는 것이 좋은 것 같습니다.

// dictionaryWithContentsOfFile 이용
NSString* testKey = @"testKey";

self.dataDic = [self loadDicForKey:testKey];

if( self.dataDic ) {
NSLog(@"testKey (first): %@", self.dataDic);
}

[self.dataDic setObject:[NSArray arrayWithObjects:@"a", @"b", @"c", nil] forKey:@"abc"];

[self saveDic:self.dataDic ForKey:testKey];
self.dataDic = nil;

self.dataDic = [self loadDicForKey:testKey];

if( self.dataDic ) {
NSLog(@"testKey (second): %@", self.dataDic);
}

[2] NSPropertyListSerialization 이용

아래 코드에 주석으로 표기 했지만, propertyListFromData:mutabilityOption:format:error: 이나 dataFromPropertyList:format:error: 등은 곧 decprecate될 것이라고 하니 대체되는 method를 사용해야할 것입니다.

그리고 , [1]에서도 이야기 했지만, 데이터를 받는 객체는 property로 처리해줘야 memory leak을 깔끔하게 없앨 수 있겠죠.

 

[저장 및 불러오기]

 

-(NSMutableDictionary*)restoreDataForKey:(NSString*)aKey {

if( aKey == nil ) {
return nil;
}

NSString *finalPath = nil;

NSData *plistData;
NSError *error;
NSPropertyListFormat format;

// normal
finalPath = [self getFilePathForkey:aKey];
plistData = [NSData dataWithContentsOfFile:finalPath];

NSMutableDictionary* tempDic = nil;
if( plistData ) {
/*
// propertyListFromData will be deprecated soon.
dataDic = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListMutableContainers
format:&format
errorDescription:&error];
*/
tempDic = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListMutableContainers format:&format error:&error];

}

if(tempDic == nil) {
tempDic = [[[NSMutableDictionary alloc] init] autorelease];
}

return tempDic;
}

-(void)storeData:(NSMutableDictionary*)aDic ForKey:(NSString*)aKey {

if( aDic == nil || aKey == nil ) {
return;
}

NSString *finalPath = nil;
NSData *xmlData;
NSError *error;

// normal
if(aDic != nil ) {

finalPath = [self getFilePathForkey:aKey];

/*
dataFromPropertyList will be deprecated soon.
xmlData = [NSPropertyListSerialization dataFromPropertyList:aDic
format:NSPropertyListXMLFormat_v1_0
errorDescription:&error];
*/

xmlData = [NSPropertyListSerialization dataWithPropertyList:aDic format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];

if(xmlData) {
//NSLog(@"No error creating XML data.");
[xmlData writeToFile:finalPath atomically:YES];
}
else {
NSLog(@"%@", error);
[error release];
}
}
}

 

[사용 예]

// NSPropertyListSerialization 이용
testKey = @"testKey2";
self.dataDic2 = [self restoreDataForKey:testKey];
if( self.dataDic2 ) {
NSLog(@"testKey2 (first): %@", self.dataDic2);
}

[self.dataDic2 setObject:[NSArray arrayWithObjects:@"aa", @"bb", @"cc", nil] forKey:@"aabbcc"];

[self storeData:self.dataDic2 ForKey:testKey];

self.dataDic2 = nil;

self.dataDic2 = [self restoreDataForKey:testKey];

if( self.dataDic2 ) {
NSLog(@"testKey2 (scond): %@", self.dataDic2);
}

Older Entries