영삼이의 IT정보2012. 6. 4. 13:47

KT앱 대회 준비하면서 모은 자료들을 정리해서 올립니다.
거의 맥부기 카페 자료들이 대부분인데 한곳에 모아서 찾아보기 쉬우라고 올려봅니다.


-푸쉬  서버  개발  관련 자료-
이지 APNS 오픈 소스 라이브러리
http://www.easyapns.com/
구글 코드 APNS 오픈 소스
http://code.google.com/p/apns-php/
서버 튜토리얼
http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/


-label이나 textView에 현재 시간을 표시하고 싶습니다-
NSDate *t = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
NSString *timeStr = [formatter setDateFormat:@"HH:mm:ss"];
myLabel.text = timeStr;
...
[textView scrollRangeToVisible:NSMakeRange([textView.text length]-1, 1)];


-시뮬레이터 포토 라이브러리 자신의 이미지 추가 방법-
UIImage * sShot = [UIImage imageNamed:@"imageName.jpg"];
UIImageWriteToSavedPhotosAlbum(sShot, nil, nil, nil);


-네이게이션바 스타일 바꾸기-
http://cafe.naver.com/mcbugi/1241


-이미지 자르기 함수를 소개합니다. (UIImage)-

- (UIImage*)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
{
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropped;
}
http://www.hive05.com/2008/11/crop-an-image-using-the-iphone-sdk/


-HTTP 라이브러리-
http://allseeing-i.com/ASIHTTPRequest/How-to-use


-json 관련-
라이브러리 http://code.google.com/p/json-framework/
json 투토리얼 http://iphonedevelopertips.com/networking/iphone-json-flickr-tutorial-part-1.html


-알럿 템플렛-
self.myAlertView = [ [UIAlertViewalloc]
initWithTitle:@"알림"
message:@"이메일을입력해주세요"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"확인", nil];
self.myAlertView.delegate = self;
[self.myAlertViewshow];


-푸쉬서버 구현을 위한 서버 인증서 pem 만들기-
애플 개발자 센터 apps ID 추가 (이때 와일드카드(*)는 사용하면 안됨)

키체인에서 개인 인증서 하나 만들어 애플 개발 센터에 등록

애플 개발센터에서 cert파일을 다운받아서 키체인으로 추가

키체인에서 내보내기로 p12파일로 저장

커맨드에서  p12파일을 pem파일로 변환
openssl pkcs12 -in quizers_dev_cert.p12 -out quizers_dev_cert.pem -nodes -clcerts


-전역변수를 사용해 보자...-
http://cafe.naver.com/mcbugi/55643


-JSON 2중 뎁스 이상 키 접근하기-
NSDictionary*feed =[self downloadPublicJaikuFeed];
// get the array of "stream" from the feed and cast to NSArrayNSArray*streams =(NSArray*)[feed valueForKey:@"stream"];
// loop over all the stream objects and print their titlesint ndx;
NSDictionary*stream;
for(ndx =0; ndx < stream.count; ndx++){
        NSDictionary*stream =(NSDictionary*)[streams objectAtIndex:ndx];
        NSLog(@"This is the title of a stream: %@", [stream valueForKey:@"title"]); 
}


-배열 NSArray-
초기 데이터로 생성
NSArray *array = [[NSArray alloc] initWithobjects:추가할 객체들.. , nil];
 스트링으로 생성
NSArray *joins =(NSArray*)[result objectForKey:@"joins"];
길이 구하기
NSLog(@"Array size : %d " , sizeof(BUILDING_DATA) / sizeof(BUILDING_DATA[0]));


-NSString 클래스를 이용하여 문자을 넣자니 유니코드를 받아 초기화-
-(NSUInteger) UnicharLength:(const unichar*)str
{
unichar* pStr = (unichar*)str;
for( ; pStr[0] != nil ; pStr++ );
return (NSUInteger)(pStr - str);
}
[[NSString alloc] initWithCharacters:(원본문자열) length:[self UnicharLength:(원본문자열)]];


-랜덤 출력-
srandom(time(NULL));
value = random() % 100;
위처럼 하시면 0~99사이의 한수를 리턴합니다.
srandom(time(NULL)); 는 첨에 한번만 해주시면 됩니다.


-Code Sign error: Provisioning profile이 맞지 않을 때 변경 방법-
여러 장비에서 작업을 하거나 여러 프로젝트를 진행 중에 변경된 Provisioning profile이 적용되지 않아 Debug를 할 때 ”Code Sign error: Provisioning profile ‘3E6AA725-6534-46F8-B9CE-D19AC9FD854B’ can’t be found” 이런 오류가 발생하는 경우가 있는데요. 이럴 때 현재 사용중인 Provisioning Profiles로 프로젝트 세팅을 변경해주는 방법을 소개한 글(원문)이 있어서 공유합니다.

1. 실행중인 Xcode Project를 닫습니다.
2. Finder에서 프로젝트 폴더로 이동합니다.
3. 프로젝트 .xcodeproj 파일 선택하고 마우스 오르쪽 키를 눌러 '패키지 내용 보기'를 선택합니다.
4. 패키지 내용 보기를 통해 패키지 안에 있는 project.pbxproj 파일을 Xcode로 불러옵니다.
5. 검색을 통해 PROVISIONING_PROFILE 부분을 찾아 변경된 Provisioning profile 로 변경해줍니다.
6. 현재 Provisioning profile을 확인하려면 Organizer 창을 열어보면 알 수 있습니다.
7. Window > Organizer로 Organizer 창을 열고 왼쪽에 IPHONE DEVELOPMENT > Provisioning Profiles로 이동합니다.
8. 오른쪽에 있는 Profile Identifier를 복사해서 변경해주면됩니다.
9. 변경이 끝나면 project.pbxproj 저장하고 프로젝트를 열어 테스트합니다.


-아이폰 웹개발에서 디바이스 아이디 가져올수있나요?-
[[UIDevice currentDevice] uniqueIdentifier];



-Accessing Objects in a NSArray-
To access an object in an NSArray, you use the -objectAtIndex: method, as in the following example:NSArray *numbers;
NSString *string;

numbers = [NSArray arrayWithObjects: @"One", @"Two", @"Three", 
                                     nil];
string = [numbers objectAtIndex: 2];   // @"Three"

Of course, you have to be careful not to ask for an object at an index which is negative or bigger than the size of the array; if you do, an NSRangeException is raised (we'll learn more about exceptions in another tutorial).
To get the length of an array, you use the method -count, as in:
NSArray *numbers;
int i;

numbers = [NSArray arrayWithObjects: @"One", @"Two", @"Three", 
                                     nil];
i = [numbers count];   // 3


-상태바 제어-
안 보이게
[UIApplication sharedApplication].statusBarHidden = NO;

스타일
UIApplication *myApp = [UIApplication sharedApplication];
[myApp setStatusBarStyle:UIStatusBarStyleBlackOpaque];


-메모리 오버되어서 어플이 죽는 경우에 호출되는 이벤트??-

뷰컨트롤러 베이스로 작업을 한다면

- (void)didReceiveMemoryWarning

함수로 메모리가 위험할시에 위 함수를 핸들링하니 내부에 관련 대응할 처리를 구현해주면 됩니다.



-D-Day 구하기-
NSDate* date  = [NSDatedateWithNaturalLanguageString:@"2010-06-30"];
NSDate* d_day = [NSDatedateWithNaturalLanguageString:@"2010-12-31"];

NSDateComponents *dcom = [[NSCalendar currentCalendar]components: NSDayCalendarUnit
fromDate:date  
  toDate:d_day  
  options:0];

NSLog(@"day=%d",   [dcom day]);   // 184


-라디오 버튼이나 체크박스등을 찾지를 못하고  있는데-
Interface Builder 에서 library를 보시면 segmented control, switch가 보일겁니다.
말씀하시는 라디오버튼이나 체크박스는 없지만  
라디오버튼은 segmented control로 대체, 체크박스는 switch 로 대체하셔서 사용하시면 될듯합니다.


-책장 넘기기 효과-
UIView 를 하나 만들고 그 안에 UIImageView 를 만들었습니다.
이제 이미지뷰어의 내용을 채울때 책장을 넘기듯이 넘기는 방법입니다.

[UIView baginAnimations:@"stalker" context:nil]; <- stalker 는 UIView 의 이름입니다
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:stalker cache:YES];
[UIView setAnimationDuration:1.0];
imageView.image = [UIImage imageNAmed:이미지파일명];
[UIView commitAnimations];

이 걸 터치 이벤트나 이런곳에 삽입하면
책장을 넘기듯이 이미지의 전환이 일어납니다. 


-image를 fade out 효과-
[UIView beginAnimations:nil context:NULL];
[imageView setAlpha:0.0];
[UIView commitAnimations]; 


-UIView Animation 중복방지-
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveLinear]; 
....
[UIView setAnimationDelegate:self]; 
[UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
        [UIView commitAnimations];

이런 식으로 에니메이션을 만들었는데 간단하게 UIImageView를 한점에서 다른 한점으로 이동시킵니다.
근데 그래서 에니매이션이 끝나면 다시 또다른 다른 두 좌표로 해서 위의 코드가 실행되서 계속해서 UIImageView를 움직이게 하고 있습니다.

근데 질문은 1. setAnimationDidStopSelector 에서 에니매이션이 끝난것을 알기전에 강제로 에니메이션을 멈출수 있나요?
2. 제 경우에는 어떤 경우에 위 코드가 setAnimationDidStopSelector 가 호출되었을때 만 실행되는 것이 아니라 다른 부분에서도 호출하기도 합니다.  근데 문제는 동시에 위 코드가 중복되어서 호출되면 이상하게 작동해요.  그래서 꼭 위 코드를 실행(에니매이션을 commit 하기전에는 반드시 에니메이션을 강제로 멈추던지 아니면 다른 체크를 해야 할것 같은데.....  

혹시 방법이 있으면 부탁드립니다.

꾸벅~

답글 : 
[UIView setAnimationsEnabled:NO];
// 에니메이션을 종료 합니다. 


-일정시간 딜레이 후 함수 호출-
[self performSelector:@selector(playerStop) withObject:nil afterDelay :1.0f];

-(void) playerStop 
{
}


-개발 완료, 베타 테스팅용 Ad Hoc 배포-
http://cafe.naver.com/mcbugi/9042


-테이블뷰에 원격이미지를 넣을경우 스크롤이 느려지는 현상-
LazyTableImages 샘플 http://developer.apple.com/iphone/library/samplecode/LazyTableImages/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009394
AsyncImageView 클래스 http://www.markj.net/iphone-asynchronous-table-image/


-테이블 뷰 섹션별로 이름 주기-
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if( section == 0 ) {
return@"발행한퀴즈";
} elseif( section == 1 ) {
return@"참여한퀴즈";
} else {
return@"진행중인퀴즈";
}
}


-정사각형으로 사진을 CROP 하고, 썸네일 크기에 맞게 리사이즈-
먼저, 출처는 다음 기사입니다.
http://tharindufit.wordpress.com/2010/04/19/how-to-create-iphone-photos-like-thumbs-in-an-iphone-app/ 
 
iPhone 사진앨범의 특징은 가로나 세로가 긴 이미지라 할지라도,
정사각형으로 사진을 CROP 하고, 썸네일 크기에 맞게 리사이즈 시킵니다.
 
위의 기사의 내용을 나름대로 보기 편하게(?) 수정을 했습니다.
 
함수명 - makeThumbnailImage
파라미터 - 원본 이미지, 리사이즈없이 CROP만 할지 여부, 리사이즈할 정사각형 한변의 길이
리턴값 - CROP 및 리사이즈된 이미지
 
- (UIImage*) makeThumbnailImage:(UIImage*)image onlyCrop:(BOOL)bOnlyCrop Size:(float)size
{
 CGRect rcCrop;
 if (image.size.width == image.size.height)
 {
  rcCrop = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
 }
 else if (image.size.width > image.size.height)
 {
  int xGap = (image.size.width - image.size.height)/2;
  rcCrop = CGRectMake(xGap, 0.0, image.size.height, image.size.height);
 }
 else
 {
  int yGap = (image.size.height - image.size.width)/2;
  rcCrop = CGRectMake(0.0, yGap, image.size.width, image.size.width);
 }
 
 CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], rcCrop);
 UIImage* cropImage = [UIImage imageWithCGImage:imageRef];
 CGImageRelease(imageRef);
 if (bOnlyCrop) return cropImage;
 
 NSData* dataCrop = UIImagePNGRepresentation(cropImage);
 UIImage* imgResize = [[UIImage alloc] initWithData:dataCrop];
 
 UIGraphicsBeginImageContext(CGSizeMake(size,size));
 [imgResize drawInRect:CGRectMake(0.0f, 0.0f, size, size)];
 UIImage* imgThumb = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();
 [imgResize release];
 return imgThumb;
}

위 소스를 참고하시면, 이미지를 CROP 하는 방법이나, 이미지를 RESIZE 하는 방법을 참고하실수 있을겁니다.
 
사족을 붙이자면, 왜 Resize 할지 여부를 따로 분리 시킨 이유는 실제로 사용을 해보면 Resize 루틴에서
많은 CPU 부하가 걸립니다. 그래서 UIImageView 에  contentMode를 UIViewContentModeScaleAspectFit 로 설정해서
자체적으로 리사이즈를 하게 하는 방법이 비동기적으로 괜찮습니다. (물론.. 실제 Resize된 이미지가 아니므로 메모리적인 소비는 있습니다.)
 
많은 도움 되셨으면 좋겠네요 ^^


-사진찍을때  아래에서  올라오는  메뉴 UIActionSheet-
http://ykyuen.wordpress.com/2010/04/14/iphone-uiactionsheet-example/


-uibutton disable-
http://www.iphonedevsdk.com/forum/iphone-sdk-development/2499-uibutton-disable.html


-이미지  슬라이드  샘플-
http://lievendekeyser.net/index.php?module=messagebox&action=message&msg_id=1351


-커버플로우  라이브러리-
http://apparentlogic.com/openflow/


-Xcode3.2.3과 SDK4로 업그레이드 후, 기존 앱 업그레이드 하는 법-
XCode3.2.3 과 SDK4로 버전업한 후, 기존 앱을 업그레이드 할 때 간단한 Tip 입니다.
1. XCode3.2.3과 SDK4로 업그레이드 한다. 별도로 기존 XCode 3.1 버전을 따로 보관할 필요가 없습니다.
2. 기존 앱을 새 XCode3.2.3에서 연다.
3.Group & Files를 right click -> Get Info 후
  3-1.General Tab 에서
Project Format 을 Xcode 3.2-compatible 로 바꾼다.
 3-2.Build Tab 에서
 Base SDK를 iPhone Device 4.0(배포시), 혹은 iPhone Simulator 4.0(테스트시) 로 바꾼다
 iPhone OS Deployment Target 을 iPhone OS 3.0 (즉 지원하고자 하는 하위버전으로) 로 바꾼다.
이렇게 하시면 됩니다.


-객체 타입 비교-
if ( [a isKindOfClass:b] )


-문자열 비교-
NSString *strText = idField.text;
if([srText isEqualToString:@"mihr01"])
....
else if([srText isEqualToString:@"mihr02"])
....
else
...
이렇게 하셔도 되고요 완전 같은 스트링이 아니라
 
포함된것을 찾으려면
if([strText rangeOfString:@"mihr01"].length) 


-탭뷰에 스타일시트를 붙일때-
UIActionSheet *popupQuery = [[UIActionSheetalloc]
initWithTitle:nildelegate:self
cancelButtonTitle:@"취소"
destructiveButtonTitle:nil
otherButtonTitles:@"사진찍기", @"기존의사진선택", nil];
popupQuery.actionSheetStyle = UIActionSheetStyleBlackOpaque;
QuizersAppDelegate *appDelegate = (QuizersAppDelegate *)[[UIApplicationsharedApplication] delegate];
[popupQuery showInView:appDelegate.window];


-스크롤  밀어서  데이터  리플래쉬  하기-
소스코드
http://github.com/facebook/three20/tree/master/samples/TTTwitter/
설명
http://www.drobnik.com/touch/2009/12/how-to-make-a-pull-to-reload-tableview-just-like-tweetie-2/


-테이블뷰 위에 검색창 붙이는 방법-
테이블뷰 위에 검색창 넣으신 후에, viewDidLoad 메서드 부분에 [table setContentOffset:CGPointMake(0.0, 44.0) animated:NO];해주시면 처음 보여질 때는 검색창이 안 보이다가 밑으로 땡기면 나타나게 됩니다.


-네트워크  연결  됐는지  확인 Reachability-
http://www.raddonline.com/blogs/geek-journal/iphone-sdk-testing-network-reachability/
http://theeye.pe.kr/entry/how-to-check-network-connection-on-iphone-sdk



-아이폰 강제종료 버튼 이벤트-
아래 메소드가 어플이 종료될 때 수행되는 함수입니다.
종료될 때에 각종 리소스들을 Free시킬 경우에 사용됩니다.
참고하시면 될 듯 합니다~
 - (void)applicationWillTerminate:(UIApplication  *)application



-크랙 방지 클래스-
http://cafe.naver.com/mcbugi/11661



-어플을 강제 종료하는 API 는 아이폰에서 제공하지 않는다?-
http://cafe.naver.com/mcbugi/11803



-탭바 클릭시 바로 UISearchBar 클릭되도록 할려면 어떻게 해야 하나요?-
UISearchBar가 first responder가 되게 하면 됩니다.
[searchBarObj becomeFirstResponder];



-UITextField 입력값 체크하기 : 문자열 길이, 숫자여부 체크-

헤더(.h)에 UITextFieldDelegate 선언

@interface 클 래스명 : UIViewController



구현부(.m)에 다음 메쏘드를 구현하면 됨

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { 

//return NO하면 입력이 취소됨
//return YES하면 입력이 허락됨
//textField 이용해서 어느 텍스트필드인지 구분 가능

//최대길이

int maxLength = 128;

NSString *candidateString;

NSNumber *candidateNumber;


//입력 들어온 값을 담아둔다

candidateString = [textField.text stringByReplacingCharactersInRange:range withString:string];


if(textField == IDField) {
maxLength = 8;
} else if(textField == AgeField) {
//숫자여부 점검

//length가 0보다 클 경우만 체크
//0인 경우는 백스페이스의 경우이므로 체크하지 않아야 한다

if ([string length] > 0) {

//numberFormatter는 자주 사용할 예정이므로 아래 코드를 이용해서 생성해둬야함

//numberFormatter = [[NSNumberFormatter allocinit];

//[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];


//numberFormatter 를 이용해서 NSNumber로 변환

candidateNumber = [numberFormatter numberFromString:candidateString];


//nil이면 숫자가 아니므로 NO 리턴해서 입력취소

if(candidateNumber == nil) {

return NO;

}


//원 래 문자열과 숫자로 변환한 후의 값이 문자열 비교시 다르면

//숫자가 아닌 부분이 섞여있다는 의미임

if ([[candidateNumber stringValuecompare:candidateString] !=  NSOrderedSame) {

return NO;

}


maxLength = 2;

}

}

//길이 초과 점검

if ([candidateString length] > maxLength) {

return NO;

}


return YES;

}

http://cafe.naver.com/mcbugi/37651



-How to split string into substrings on iPhone?-
http://stackoverflow.com/questions/594076/how-to-split-string-into-substrings-on-iphone



-메모리 누수-
http://cafe.naver.com/mcbugi/64257


-디바이스 가로 세로 상태-
UIDeviceOrientationIsLandscape([UIDevicecurrentDevice].orientation) ?


-UITextField 에 자동 포커스 주기-
키보드 올리면서 커서를 넣을때는 아래방법을 이용하시면 됩니다.
[textField becomeFirstResponder]; 
참고로 이건 커서를 빼면서 키보드를 내리실때 사용하시면 되구요...
[textField resignFirstResponder]; 


-홈버튼이 눌렸을 때도 텍스트뷰 내용을 저장하려면 어떻게 해야할까요?-
- (void)applicationWillTerminate:(UIApplication *)application / Application Delegate 메서드 부분에 구현하시면 되지않을가요? 


-3.2 4.0  동영상  플레이-
http://iphonedevelopertips.com/video/getting-mpmovieplayercontroller-to-cooperate-with-ios4-3-2-ipad-and-earlier-versions-of-iphone-sdk.html


-한글완성형(EUC-KR)을 iPhone/Mac에서 사용할 수 있는 언어셋으로 변환하기-
http://blog.backpackholic.tv/160


-인터페이스 함수들을 편하게 가져오는 방법-
http://code.google.com/p/xcode-auto-assistant/


-#pragma mark로 코드 쉽게 구분하기-
http://cafe.naver.com/mcbugi/64408


-os4에서 applicationWillTerminate가 안먹어서 알게된것-
os4에서 applicationWillTerminate: 가 안먹어서 삽질하다가 알아낸 결과입니다.
뒷북 인지는 모르지만 혹시 모르시는 분을 위해서 적어봅니다.
os3.x 에서는 홈버튼을 한번만 누르면 applicationWillTerminate 가 아주 잘 호출됩니다.
하지만 os4 에서는 홈버튼을 한번만 누르면 
applicationDidEnterBackground 가 호출됩니다.
os4 에서 멀티태스킹을 위해서 좀 바뀌었습니다.
os4에서도 홈버튼 한번 누를때 applicationWillTerminate 가 호출되게 하려면
info.plist 에서 'Application does not run in background' 이 속성을 추가해주면 됩니다.
위 속성이 없으면 기본적으로 멀티태스킹이 되는걸로 간주합니다. (진짜 멀티태스킹은 아니지만)
위 속성이 없을때 호출되는 메소드를 실험해 봤습니다.
-----------------------------------------------------------------
처음 어플을 실행시키면
     didFinishLaunchingWithOptions, 
applicationDidBecomeActive 
이 호출되고
홈버 튼을 한번 만 누르면
applicationWillResignActive, 
applicationDidEnterBackground
호출되면서 어플이 종료되고
이상태에서 다시 어플을 실행시키면
applicationWillEnterForeground, 
applicationDidBecomeActive 
호출됩니다.
홈버튼을 두번 누르면
applicationWillResignActive
이 호출됩니다.
----------------------------------------------------------------
'Application does not run in background' 을 체크하면
홈버 튼을 한번만 누르면 applicationWillTerminate 를 호출합니다.
'근데 속성 체크 안했을때 applicationWillTerminate 는 호출이 안되는건지 궁금하네요.
아시는 분 좀 알려주세요.

답글 : 
Applicationwillterminate함수 대신에 applicationDidENterBAckground 사용하라고하네여 이곳에서 공유자원해제나 사용자데이타 저장,타이머 무효화,어플상태정보등 저장을 하라고 합니다. http://cafe.naver.com/mcbugi/65497


-COCOS2D 번개 효과-
http://www.cocos2d-iphone.org/forum/topic/370


-iPhone 4.0 호환 키보드에 버튼 or 뷰 붙이기-
기존꺼에 비해 약간 수정되 었을뿐입니다....
하지만 -_-이거 찾느라 ㅠㅠ;; 

3.1.x에서는 windows 서브뷰에 항상 키보드 뷰가 있었지만 ...
4.0 부터는 windows 에 항상 있는게 아니고, 키보드를 불렀을때 -_- 붙어서 오더라고요.. 그래서

Done 버튼 붙이는 예제 입니다. (Number 패드에)

아래 액션을 Text필드의 BeginTouched 에 연결 시킵니다.
 // 키보드가 나왔을때랑 사라질때의 이벤트를 잡아냅니다.
//3.1.X 에서는 UIKeyboardWillShowNotification 으로 잡지만
// 4.0 때문에 --; DidShow로 잡아줬습니다.
//그래야 윈도우에 키보드가 있더라고요 ;;;
-(IBAction)FieldTouched{
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardDidShowNotification
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
    
    
}

// 키보드가 나왔을때 Done 버튼 붙여주기 
- (void)keyboardWillShow:(NSNotification *)note {  
    
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 163, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setImage:[UIImage imageNamed:@"DoneUp.png"] forState:UIControlStateNormal];
    [doneButton setImage:[UIImage imageNamed:@"DoneDown.png"] forState:UIControlStateHighlighted];
    [doneButton addTarget:self action:@selector(backgroundTap:) forControlEvents:UIControlEventTouchUpInside];

    //3.1.x 와 4.0 호환 키보드 붙이기
    for( UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows] ){
        for( UIView *keyboard in [keyboardWindow subviews] ){
            NSString *desc = [keyboard description];
            if( [desc hasPrefix:@"               [desc hasPrefix:@"               [desc hasPrefix:@"            {
                [keyboard addSubview:doneButton];
            }
        }
    }
    
}

// 키보드가 없어질때 Done 버튼을 삭제 합니다.
- (void)keyboardWillHide:(NSNotification *)note {  
    
    for( UIWindow *keyboardWindow in [[UIApplication sharedApplication] windows] ){
        for( UIView *keyboard in [keyboardWindow subviews] ){
            NSString *desc = [keyboard description];
            if( [desc hasPrefix:@"               [desc hasPrefix:@"               [desc hasPrefix:@"            {
                for(UIView *subview in [keyboard subviews])
                {
                    [subview removeFromSuperview];
                }
                
            }
        }
    }
}

도 움 되시길 바랍니다 ;)
http://cafe.naver.com/mcbugi/62349


-배열내 숫자 값 비교해서 정렬하기-
만약에 객체내의 인스턴스를 키로 정렬할 경우에는 NSSortDescriptor 를
쓰시면 됩니다.
아래는 name으로 정렬한 예입니다.

@interface Test :
NSObject {
NSString *name;
double distance;
}
@property
(nonatomic, retain) NSString *name;
@property double
distance;
@end

@implementation Test
@synthesize name, distance;
@end


아 래는 사용방법입니다.
       Test *t1 = [[Test alloc] init];
Test *t2 = [[Test alloc] init];
Test *t3 = [[Test alloc] init];
[t1 setName:@"마바사"];
[t2 setName:@"아자차"];
[t3 setName:@"가나다"];
[t1 setDistance:1.2];
[t2 setDistance:2.5];
[t3 setDistance:0.5];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:t1];
[array addObject:t2];
[array addObject:t3];
[t1 release];
[t2 release];
[t3 release];
// 이름순으로 정렬
NSSortDescriptor *nameSort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES selector:@selector(localizedCompare:)];
[array sortUsingDescriptors:[NSArray arrayWithObjects:nameSort, nil]];
[nameSort release];
for(Test *t in array) {
NSLog(@"%@ %f", [t name], [t distance]);
}
[array removeAllObjects];


------[결 과]------
2010-07-12 17:46:13.117 Sort[5070:20b] 가나다 0.500000
2010-07-12 17:46:13.125 Sort[5070:20b] 마바사 1.200000
2010-07-12 17:46:13.130 Sort[5070:20b] 아자차 2.500000


p.s. distance로 정렬하고자 한다면 
NSSortDescriptor *distanceSort = [[NSSortDescriptor alloc] initWithKey:@"distance" ascending:YES];
nameSort 대신 distanceSort를 넣으시면 됩니다.
http://cafe.naver.com/mcbugi/65873


-[TIP] 시뮬레이터 사진앨범에 사진넣기-
1) 시뮬레이터를 실행시킵니다.

2) 맥에서 포토라이브러리에 넣을 사진을 시뮬레이터로 Drag&Drop 합니다.

3) 그러면, 사파리가 열리면서 Drag한 이미지가 표시가 될겁니다.

4) 그 표시된 이미지를 마우스로 꾸~~~~~~욱 눌러줍니다.

5) 그러면, 메뉴가 뜨면서 이미지를 저장할건지 복사할건지를 묻습니다.

6) 이미지 저장을 누릅니다.

7) 이제 시뮬레이터의 사진앨범에 가 보시면 아까 저장한 사진이 들어가있을겁니다.

'영삼이의 IT정보' 카테고리의 다른 글

StoreKit  (0) 2012.06.10
iOS 키보드  (0) 2012.06.10
UIImageJPEGRepresentation  (0) 2012.06.04
XHTML/CSS 무료 템플릿 배포사이트  (0) 2012.06.01
메인 runloop 쓰레드에 타이머 동작 시키기  (0) 2012.06.01
Posted by 다오나무
영삼이의 IT정보2012. 6. 4. 13:04

 [[NSData allocinitWithData:UIImageJPEGRepresentation(_image0.4)];


같은 경우 위의 0.4 의 자리에 들어가는 이미지 퀄리티와 바이트 량의 상관관계를 직접 실험해 보았다.



실험 대상 : 1,486,503 바이트 (약 1.5메가) JPEG 이미지. (생강꿀차 사진 ㅋㅋ)


 파라메터 값바이트 (원본과 비교한 %)
-0.2117143 
- 0.1117143 
 - 0.9117143  
-0.1 117143  
-0.01 117143  
0 117143  
0.000001 117143  
0.02 117143  
0.03 117143  
0.04117143  
0.05117143  
0.06117143  
0.067117143  
0.068117144   -> 처음으로 수치 변화
0.07117155
0.079117277
0.08117557
0.081117144
0.085118108
0.9118966
0.1119702 (8.053 %)
0.11119737
0.2136765 (9.200 %)
0.3204806 (13.777 %)
0.4355252 (23.898 %)
0.5531804 (35.775 %)
0.6731074 (49.180 %)
0.71147188 (77.176 %)
0.81326826 (89.258 %)
0.811338302 (90.030 %)
0.891455457 (97.912 %)
0.91470849 (98.946 %)
1.02601934 (175.037 %) -> 1.0 일땐 원본보다큰값
1.12601934 (175.037 %)
2.12601934 (175.037 %)

공식적으로는 0.1에서1.0 사이의 값을 사용하도록 되어있다.

그래도 -,1 이상의 값도 실험해 보았다.


특이점은 1.0일때 원본과 같은 값이 아니라 훨신 큰 바이트 값을 가진다는점이다.

0.9 정도일때 원본과 거의 비슷한 값이다. 서버와 통신을 위해서는 0.3, 0.4 정도값이 적당한 것같다.




그래프로 찍어보면 이런 형태의 수렴 그래프. 뭔가의 루트 값을 이용하는 것같다.


Posted by 다오나무
영삼이의 IT정보2012. 6. 1. 17:27

Smashing Magazine에서 가끔 소개된 XHTML/CSS 무료 템플릿 배포사이트를 정리해보았다.

2008120204

Template Kingdom (12가지) 글꼴 및 PSD 제공

2008120204

Template World (43가지)

2008120204

Open Source Templates (9가지)

2008120204

Open Source Web Design (12가지)

2008120204

Art for the web (53가지)

2008120204

Ex-designz (419가지)

2008120204

CSS Creame (30가지)

2008120204

Solucija (35가지)

2008120204

Free CSS Templates.org (339가지)

2008120204

Six Shooter Media (11가지)

2008120204

Rambling Soul (30가지)

2008120204

styleshout.com (27가지)

2008120204

Open Designs - kohout (9가지)

2008120204

Open Designs - pixelfuze (2가지)

Open Designs - Outsider (14가지)

Open Designs - bradm81 (12가지)

Open Designs - Symisun (2가지)

Open Designs - coll23 (9가지)

Open Designs - ealigam (14가지)

Open Designs - David (6가지)

이상으로 무료로 XHTML/CSS 기반 템플릿을 무료로 다운로드받아 사용할 수 있는 사이트를 정리해보았다. 또한, 웹표준을 공부하는 분들이라면 참고용으로 활용한다면 용이하게 이용할 수 있다

Posted by 다오나무
영삼이의 IT정보2012. 6. 1. 16:25

일반적으로 타이머를 동작시키면 UI 작동중에는 동작이 되질 않는다.


스크롤중이거나 버튼 터치시.. 등등 UI가 먼저 우선 순위인 것이다..


하지만 메인 runloop에 동작시키면 UI보다 우선순위가 될 수 있다..


다음처럼 하면 된다..



 self.timer = [NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(countDown)

                                                        userInfo:nil repeats:YES];

 [[NSRunLoop mainRunLoopaddTimer:self.timer forMode:NSRunLoopCommonModes];

Posted by 다오나무
영삼이의 IT정보2012. 6. 1. 16:18

- (void)myStringExample

{

    // 파일명에서 확장자 얻기

    NSString *fileName = @"somefile.txt";

    NSString *fileExtension = [fileName pathExtension];

    

    // 공백문자 없애기

    NSString *myString = @" one two three ";

    NSString *trimed = [myString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

    

    NSString *string1 = @"some string";

    NSString *string2 = @"some other string";

    NSString *string3 = @"Some StRiNg";

    NSString *string4 = @"some other string";

    

    // 문자열 비교

    NSLog(@"%i",[string2 isEqualToString:string4]);

    NSLog(@"%i",[string1 isEqualToString:string3]);

    NSLog(@"%i",([string1 caseInsensitiveCompare:string3] == NSOrderedSame));

    

    // 스트링을 double, int값으로 변경하기 

    NSString *n = @"12345";

    double d = [n doubleValue];

    int i = [n intValue];

    NSLog(@"%f, %d",d,i);

    

    // URL에서 HTML얻기

    NSURL *url = [NSURL URLWithString:@"http://google.com"];

    NSString *pageContents = [NSString stringWithContentsOfURL:url];

    

    NSLog(@"%@", pageContents);

    

    // 숫자 변경

    NSString *numberString = @"one two three";

    NSRange foundRange = [numberString rangeOfString:@"two"];

    NSString *oneString = [numberString substringToIndex:3];

    NSString *twoString = [numberString substringWithRange:NSMakeRange(43)];

    NSString *threeString = [numberString substringFromIndex:8];

    

    NSString *repeatString = [numberString 

                              stringByReplacingOccurrencesOfString:@"three" withString:@"four"];

    BOOL found = ([numberString rangeOfString:@"two1"].location != NSNotFound);

    

    NSString *stringa = @"one";

    NSString *stringb = [stringa stringByAppendingString:@" two"];

    

    NSLog(@"%i - %i",foundRange.location, foundRange.length);

    NSLog(@"%@",repeatString);

    NSLog(@"[%@] [%@] [%@]",oneString,twoString,threeString);

    NSLog(@"%@",[numberString componentsSeparatedByString:@" "]);

}


- (void)myDateExample

{

    // 현재 날짜시간 얻기

    NSDate *myDate = [NSDate date];

    NSLog(@"%@", myDate);

    

    // 다음 날짜 얻기(초를 기반한 interval 계산)

    NSTimeInterval secondsPerDay = 24*60*60;

    NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow:secondsPerDay];

    NSLog(@"%@", tomorrow);

    

    // 이전 날짜 얻기

    NSDate *now = [NSDate date];

    NSDate *yesterday = [now addTimeInterval:-secondsPerDay];

    NSLog(@"%@", yesterday);

    

    // 날짜 차이 얻기

    NSTimeInterval secondsBetweenDates = [yesterday timeIntervalSinceDate:now];

    NSLog(@"%@", secondsBetweenDates);


    NSDateComponents *comp = [[NSDateComponents allocinit];

    [comp setMonth:06];

    [comp setDay:01];

    [comp setYear:2010];

    NSCalendar *myCal = [[NSCalendar allocinitWithCalendarIdentifier:NSGregorianCalendar];

    NSDate *myDate2 = [myCal dateFromComponents:comp];

    

    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];

    [formatter setDateStyle:NSDateFormatterMediumStyle];

    NSString *friendlyDate = [formatter stringFromDate:now];

    

    NSLog(@"%@", friendlyDate);

    

    [formatter setDateFormat:@"yyyy-mm-dd"];

    NSString *friendlyDate2 = [formatter stringFromDate:now];

    

    NSLog(@"%@", friendlyDate2);

    

}


- (void)myArrayExample 

{

    NSString *string1 = @"one";

    NSString *string2 = @"two";

    NSString *string3 = @"three";

    

    NSArray *myArray = [NSArray arrayWithObjects:string1, string2, string3, nil];

    

    // Array 복사

    NSArray *myArray2 = [NSArray arrayWithArray:myArray];

    

    // 범위를 지정해서 Array 복사

    NSRange range = NSMakeRange(02);

    NSArray *subArray = [myArray subarrayWithRange:range];

    

    int arrayLength = [myArray count];

    NSLog(@"%d", arrayLength);

    

    int arrayLength2 = [subArray count];

    NSLog(@"%d", arrayLength2);



    // 루프를 출력

    for (NSString *obj in myArray) {

        NSLog(@"%@", obj);

    }

    

    // 루프를 거꾸로 출력

    for (NSString *obj2 in [myArray reverseObjectEnumerator]) {

        NSLog(@"%@", obj2);

    }

    

    // 정렬

    [myArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

    

}


- (void)myDictionaryExample 

{

    NSArray *arr1 = [NSArray arrayWithObjects:@"iPhone"@"iPod"nil];

    NSArray *arr2 = [NSArray arrayWithObjects:@"iMac"@"Mac Pro"@"Macbook"@"Macbook Pro"nil];

    

    //  부분에서 오류가 

    NSDictionary *myDict = [[NSDictionary allocdictionaryWithObjectsAndKeys:arr1, @"mobile", arr2, @"computers"nil];

    

    int dictSize = [myDict count];

    NSLog(@"%d", dictSize);

    

}


- (void)myNotificationExample

{

    // Notification 등록

    [[NSNotificationCenter defaultCenteraddObserver:self selector:@selector(doSomething:) name:MY_NOTIFICATION object:nil];

    

    // Notification 호출

    [[NSNotificationCenter defaultCenterpostNotificationName:MY_NOTIFICATION object:nil];

    

}


- (void)doSomething:(NSNotification *) aNote 

{

    NSLog(@"doSomething called...");

    

    // 만약 aNote 통해서 뭔가 전달되었다면

    // [aNote object] 받아서 처리함

    

}


- (void)myTimerExample 

{

    // 타이머 생성

    //NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(myTimerAction:) userInfo:nil repeats:NO];

    

    //[myTimer invalidate];

    // 하루의   

    NSTimeInterval secondsPerDay = 24*60*60;

    NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow:secondsPerDay];

    NSTimer *myTimer = [[NSTimer allocinitWithFireDate:tomorrow interval:10.0 target:self selector:@selector(myTimerAction) userInfo:nil repeats:NO];

    

    [[NSRunLoop mainRunLoopaddTimer:myTimer forMode:NSDefaultRunLoopMode];

    

}


Posted by 다오나무
영삼이의 IT정보2012. 5. 31. 15:19

"나 특정 값을 영구적으로 저장하고 싶어~^^ "

"쉬파 어떤 방법이 있는거야? 파일 입출력 해야되? XML로 저장해야 하나."

"아잉 난 정말 간단한 값인데. 쉬운 방법 없을까?"


이런 고민을 하시는 아이폰 개발을 시작하시는 여러분에게 NSUserDefaults 를 소개합니다


간단한 API !

유용한 기능 !


단 돈 0원에 지금 만나보실 수 있습니다~!



NSUserDefaults 는 사용자 설정을 지원하기 위해 설계되었답니다.


REMOVE_AD 라는 값이 YES면 광고를 제거해주고 NO면 광고를 보여준다.

라는 기능이 필요하다고 합시다.


근데 우리가 이 값을 파일로 가지고 있어야지

앱 실행시마다 초기화 된다면 컨트롤할 방법이 없습니다

(초기에 REMOVE_AD가 NO인데 나중에 인앱결재등을 통해 REMOVE_AD를 YES로 바꿨다 칩시다.

근데 이 값을 파일로 저장해야 REMOVE_AD는 항상 YES일 수 있는 거지요)



위의 예로 한번 구현해 봅시다.


앱이 처음 시작되는 지점이나 

- (void) applicationDidFinishLaunching:(UIApplication*)application <- 뭐 여기 함수 내에? ㅋ

혹은 필요하다고 하는 지점에


NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];


요렇게 인스턴스를 생성합니다. ^^ 쉽습니다~!


    if (![defaults objectForKey:@"REMOVE_AD"]) {

        

        [defaults setObject:@"NO" forKey:@"REMOVE_AD"];

    }


자 요렇게 초기 값을 설정합니다. 위 로직을 이해하셨나요?


[defaults objectForKey:@"키값"] <- 요건 말그대로 키값에 해당하는 오브젝트를 가져오는 부분이구요

[defaults setObject:@"오브젝트여기선 그냥 스트링" forKey:@"키값"]; 

<- 요건 말그대로 키값에 오브젝트 즉 값을 설정하는 부분입니다.


즉 REMOVE_AD 값을 NSUserDefaults에서 찾아서 없다면 NO로 설정하는 부분이고

if문안의  로직은 한번 수행하고 나면 다시는 실행되지 않겠죠 ㅋㅋ


이렇게 값을 설정하고 마지막에


[defaults synchronize];


를 해줘야 합니다.  그래야 완벽히 저장이 되는 거지요 ㅋ

합쳐 놓으면





NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

 if (![defaults objectForKey:@"REMOVE_AD"]) {

        

        [defaults setObject:@"NO" forKey:@"REMOVE_AD"];

 }

[defaults synchronize];







너무나 심플합니다. ㅋ


그리고 앱내에서 인앱을 해서 광고를 제거했다. 그러면




NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

[defaults setObject:@"YES" forKey:@"REMOVE_AD"];

[defaults synchronize];





요렇게 값을 YES로 바꿔버리면 되구요. ^^


실제 광고를 보여주는 로직에서

아래와 같이 제어할 수 있는 겁니다.




NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];


 if ([[defaults objectForKey:@"REMOVE_AD"isEqualToString:@"NO"]) {

        //광고 보여줘잉

 } else {

        //광고 보여주면 안되!!!

 }





정말 간편한 NSUserDefaults 자주 애용해 봅시다 ㅋㅋ

Posted by 다오나무
영삼이의 IT정보2012. 5. 31. 15:06

각 단말기에는 해당 단말기를 식별하는 유일값인 UDID가 존재합니다. iOS 플랫폼의 경우 SDK 상에서 쉽게 이 UDID 값을 추출할 수 있었습니다. 이 UDID는 사용자의 직접적인 개인정보를 이용하지 않고 사용자의 패턴 분석에서부터 타겟광고 소스 등 여러 부분에서 이용하고 있었습니다만 현재 베타테스트가 진행 중인 iOS5에서는 이 UDID 의 이용은 제한될(deprecated) 예정입니다. 이에 따라 애플에서는 UDID보다는 UUID를  생성하여 이용하라고 권고하고 있습니다. UUID는 단말기의 고유값이 아닌 어플리케이션에서 생성한 유일값으로 생성할 때마다 변경되는 랜덤값입니다. 따라서 개발자분들은 이에 대한 대응을 미리 하시는 것이 좋을 것 같아서 정리해보았습니다.

  • uniqueIdentifier 메소드가 사라질 예정

UDID는 단말기를 식별하기 위해 고유하게 할당된 40개의 숫자와 문자열입니다. 이런 고유값은 개인정보이다. 아니다 기기 식별값이므로 개인정보는 아니다라는 논란으로 잠시 인터넷이 뜨거웠던 적이 있습니다. (2011/05/10 서울경제 기사, http://economy.hankooki.com/lpage/it/201105/e20110510173640117700.htm)

이 UDID는 구글, 오픈페인트를 비롯한 여러 광고 및 트래픽 분석툴에 사용되고 있는 상황에서 애플이 드디어 칼질을 가하기 시작했습니다. iOS5 beta 6에서는 UDID를 가져올 때 사용하는 메소드를 없애겠다는 의지로 해당 메소드를 deprecated시키고 대신 Core 레벨에서 랜덤한 UUID를 생성하는 메소드를 이용하라는 권고를 내렸습니다. (Apple Sneaks A Big Change Into iOS 5: Phasing Out Developer Access To The UDID :http://techcrunch.com/2011/08/19/apple-ios-5-phasing-out-udid/).

실제로 iOS5 beta 6에서 [[UIDevice currentDevice] uniqueIdentifier]가 포함된 프로젝트를 빌드하면 아래와 같은 경고가 나타납니다.

  

  • UDID가 아닌 UUID를 이용하라는 권고

애플에서는 UDID값이 아닌 UUID(Universally Unique Identifiers)를 이용하라는 권고를 내렸습니다. CFUUID Documentation을 참조하면 이 UUID는 128-bit 값으로 생성된 유일값이며 이는 시간과 공간값으로 생성된 유일값이므로 중복될 염려가 없다고 합니다.

유일값 생성 방법은 아래와 같으며,

CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *string = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuid);

생성되는 UUID는 아래와 같은 형태의 결과값을 가집니다.

이렇게 생성된 UUID를 NSUserDefaults 등을 이용하여 값을 유지시켜줌으로 UDID와 동일한 역할을 하도록 개발자들의 추가 구현이 필요하다라고 문서에는 나와있습니다. 어느 부분에서는 한 줄이면 가능한 유일값 추출을 이제는 개발자가 직접 신경을 써서 관리하라고하니 한숨이 나오는 건 사실입니다.

  이렇게 생성된 관리를 위한 방법으로는 NSUserDefaults를 이용하여 앱 내부에서 관리하는 방법별도의 서버에 이 값을 저장하여 관리하는 방법, 또는 iOS5 이상의 iCloud를 이용하는 앱이라면 iCloud의 Key-Value Data Storage를 이용하는 방법을 생각해 볼 수 있습니다. 이도 문제가 된다면 Mac Address를 추출하고 이를 해쉬값을 이용(MD5)하는 방법도 최근 iOS 개발자분들이 관심을 가지고 있는 것 같습니다. (GitHub : http://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5).

 

  • UDID vs. UUID

 UDID는 Unique Device Identifier로 기기의 고유값입니다. 하지만 UUID는 앱 자체에서 생성되는 고유값으로 사용자가 사용하는 앱의 고유값으로 볼 수 있습니다. 즉, UUID를 사용하도록 권고하는 것은 단말기의 고유값을 사용하지 말고 앱마다 각자의 고유값을 이용하라는 풀이로 볼 수 있습니다.

  이 두 유일값의 장단점을 간략히 살펴보면 아래 표와 같습니다.

 

  • 당장은 고려하지 않아도 된다?
  •  

Deprecated 된 메소드는 아시다시피 현재 사용하지 못한다는 의미는 아니지만 앱스토어에 앱을 등록할 때 리젝 사유가 될 수 있습니다. 위에서 설명드린대로 경고가 항상 나타난다면 당장 대안을 찾아야하는 상황이지만 프로젝트의 Deployment Target을 5.0 이하. 즉, 4.x나 3.x로 한다면 메소드를 사용이 가능합니다. 물론 개발 상에서 사용가능하다는 것이며 정책상으로 어떻게 될지는 모르는 상황입니다.

UDID를 활용하는 서비스나 앱이 많을 것으로 예상됩니다. iOS5가 정식으로 릴리즈되더라도 당장에 사용못하게 하지는 않을 것으로 예상되지만 미리 준비를 해두시는 것이 좋을 것 같습니다.

아래는 Deployment Target을 4.0으로 설정하는 화면과 설정 이후 빌드한 결과 uniqueIdentifier에 경고가 나타나지 않는 화면입니다.

 

  • UUID가 아닌 다른 유일값 사용에 대해서
  •  

UUID가 아닌 유일값에 대해서는 애플에서는 아직 언급하고 있지 않습니다만 Ethernet의 MAC AddressBundle identifier 등 여러 대안을 생각해볼 수 있습니다. MAC Address의 경우 Cocoa API에는 추출 메소드가 없어 직접 Core에 접근하여 추출을 해야하며, 해당값을 그대로 사용하는 것이 아닌 MD5나 SHA-1 등의 해쉬를 이용하여 보안이슈가 발생되지 않게 해야합니다. 이로 인해 작업 공수가 더 추가된다는 것, 또한 이후에 애플에서 해당값의 사용을 금지할 수도 있다는 잠재적인 위험요소가 있으므로 되도록이면 애플에서 권장하는 UUID를 이용하는 방법으로 문제를 해결하는 것을 추천해드립니다.

 

  • 결론

UDID를 얻어오는 메소드는 iOS5부터 사용할 수 없는, 삭제 예정인 메소드입니다.
- 프로젝트의 Deploy Target을 5.0이 아닌 그 이하 버전으로 설정하는 경우에는 UDID 추출 메소드 사용이 가능합니다.
- 정책상 결정된 부분은 아니지만 애플의 권고는 UUID를 이용하는 것입니다.
- 또한, iOS5가 정식으로 발표된 이후에는 반드시 고려되어야하는 이슈이므로, 미리 이에 대한 대비가 마련되어야 합니다.
- UUID도 단말기의 고유값이 아니므로 서비스의 특성에 따라서는 UDID가 아닌 단말기의 고유값으로 간주할 수 있는 MAC Address를 이용하는 방법 등을 고려할 수 있습니다.
- UDID를 사용하지 못하는 것과 동일하게 MAC Address도 사용이 불가할 수도 있다는 점은 고려하여 대책 마련을 하시는 것이 좋습니다.
- MAC Address를 해쉬처리한 문자열이 단말기의 고유값으로 보는 방안은 애플의 정책에 위배되지 않는다는 가정하에서 현재 단말기의 유일값으로 지정할 수 있는 최상의 방안으로 고려됩니다. (iOS5 정식출시가 되어봐야 알 것 같습니다.)

Posted by 다오나무
영삼이의 IT정보2012. 5. 30. 14:35

ASIHttpRequest라는 좋은 라이브러리를 ARC를 지원하지 않더군요.
ARC와 함께 이 라이브러리를 사용할 수 있는 방법을 알게 되어 정리차원에서 작성합니다.

새 Target을 만들고, 형식은 Cocoa Touch Static Library로 설정합니다. 이름은 적당히 ASIHttpRequest로 정해 줍시다.



Build Setting에서 <count>로 검색하면 Automatic Reference Count 옵션이 보이는데 이것을 NO로 변경해 줍니다.



프로젝트 폴더에 가면, 아까 생성한 Target 이름 (여기서는 ASIHttpRequest) 의 폴더가 있는데, 이 폴더에 
ASIHttpRequest 의 Classes 폴더 내의 모든 파일 (ASIWebPageRequest, CloudFiles, S3, Tests 폴더 내의 파일 제외) 과 
External/Reachability/*.* 을 복사해 줍니다.


빼기(-)를 눌러  Compile Sources 내의 모든 파일을 삭제 한 후 플러스(+)를 눌러서 나오는 화면에서 



Add Other 선택


그리고 방금 복사한 파일을 모두 선택하고 Open을 누릅니다.


Copy는 하지 않습니다.


이건 불필요한 과정이긴 하지만, 왼쪽에 추가된 파일들을 보기 좋도록 ASIHttpRequest 폴더로 이동시켜 줍니다.



Targets에서 App에 해당하는 Target을 선택하고, Target Dependencies 에서 지금까지의 작업으로 추가된 ASIHttpRequest Target을 추가하고,
다음의 Framework들을 추가해 줍니다.
- libASIHttpRequest.a  (방금 생성한 Target)
- SystemConfiguration.framework
- CoreGraphics.framework
- libz.dylib
- CFNetwork.framework
- MobileCoreService.framework

이러한 과정을 거치고 빌드를 해보면 에러 없이 빌드가 될겁니다. 다만 경고가 14개 뜨네요 ㅠㅠ..

Posted by 다오나무
영삼이의 IT정보2012. 5. 29. 15:14

/* 

아래 같은 방식으로 smsURL이라는 주소로 post 형식으로 데이터를 감싸 전송이 가능해진다.

*/

- (void)connectToServer

{

NSString *smsURL = @"http://www.google.co.kr";

NSMutableURLRequest *request = [[[NSMutableURLRequest allocinitautorelease];

NSString *post = [NSString stringWithFormat:@"password=%@&id=%@",@"password",@"id"];

NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

NSString *postLength = [NSString stringWithFormat:@"%d",[postData length]];

[request setURL:[NSURL URLWithString:smsURL]];

[request setHTTPMethod:@"POST"];

[request setValue:postLength forHTTPHeaderField:@"Content-Length"];

[request setValue:@"Mozilla/4.0 (compatible;)" forHTTPHeaderField:@"User-Agent"];

[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

[request setHTTPBody:postData];


[NSURLConnection connectionWithRequest:request delegate:self ];

}


/*

아래 Delegate에서는 HTML이 처리되고 난 후 받는 데이터를 얻을 수 있다.

*/

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

NSString *returnString = [[NSString allocinitWithData:data encoding:NSUTF8StringEncoding];

NSLog(returnString);

}


/* 

아래 Delegate를 이용하면 post를 보낸 후 쿠키를 얻을 수 있다.

*/

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)aResponse

{

NSHTTPCookie *cookie;

int i=0;

for (cookie in [[NSHTTPCookieStorage sharedHTTPCookieStoragecookies])

{

NSLog([cookie description]);

}

}

Posted by 다오나무
영삼이의 IT정보2012. 5. 29. 13:05

PCRE 정규표현식 기본기


http://kr2.php.net/manual/en/ref.pcre.php
http://kr2.php.net/manual/en/reference.pcre.pattern.syntax.php
http://kr2.php.net/manual/en/reference.pcre.pattern.modifiers.php

위 링크의 내용을 바탕으로 기본을 설명합니다.

1. \ : 정규표현식에 사용되는 기호를 문자로써 사용하기 위해 탈출(escape) 시키는 문자.
<?php
preg_match('/\//', '---/---', $matches);
echo $matches[0];
?>
/

2. . : 아무거나 한 글자를 의미 (UTF-8 에서는 글자단위 그 외에는 byte 단위) (개행문자 제외)
3. ^ : 시작을 의미
<?php
echo preg_replace('/^./', '', 'abcd');
?>
bcd

4. $ : 끝을 의미
<?php
echo preg_replace('/.$/', '', 'abcd');
?>
abc

5. * : 앞의 기호의 반복을 의미 없어도 참
6. + : 앞의 기호의 반복을 의미 없으면 거짓
7. [] : [] 안의 내용 중 한글자를 의미 (- 로 구간설정 가능)
8. \d : [0-9] 를 의미
<?php
if(!preg_match('/^[1-9]\d*$/', $_GET['no'])) {
    echo '1 부터 시작하는 수를 적으셔';
    exit;
}
if(!preg_match('/^[a-z]+$/', $_GET['text'])) {
    echo '영문 소문자만 적으셔';
}
?>

9. \s : 공백문자를 의미 (탭 포함)
10. \t : 탭을 의미
11. \r : 개행문자 0x0d 를 의미
12. \n : 개행문자 0x0a 를 의미
<?php
$text = <<<TEXT
가나다 김삼순
킹왕짱     어쭈구리

abcd
TEXT;
print_r(preg_split('/[\s\r\n]+/', $text));
$text = <<<TEXT

?>
Array
(
     [0] => 가나다
     [1] => 김삼순
     [2] => 킹왕짱
     [3] => 어쭈구리
     [4] => abcd
)
<?php
$text = <<<TEXT
이름\t진\t선\t미
김태희\t80\t90\t100
송혜교\t100\t100\t98
TEXT;
$rows = preg_split('/[\r\n]+/', $text);
foreach($rows as $row) {
    $cols[] = preg_split('/\t/', trim($row));
}
print_r($cols);
?>
Array
(
     [0] => Array
         (
             [0] => 이름
             [1] => 진
             [2] => 선
             [3] => 미
         )

     [1] => Array
         (
             [0] => 김태희
             [1] => 80
             [2] => 90
             [3] => 100
         )

     [2] => Array
         (
             [0] => 송혜교
             [1] => 100
             [2] => 100
             [3] => 98
         )

)

13. ? : 존재유무 ()괄호와 함께 쓸 수 있다.
<?php
$text = <<<TEXT
<input type="text" name=asdf value="asdf" />
TEXT;
$cnt = preg_match_all('@([a-z]+)\s*=\s*"?([a-z]+)@', $text, $matches);
unset($matches[0]);
print_r($matches);
?>
Array
(
     [1] => Array
         (
             [0] => type
             [1] => name
             [2] => value
         )

     [2] => Array
         (
             [0] => text
             [1] => asdf
             [2] => asdf
         )

)
<?php
$text = <<<TEXT
<p>asdf <strong>zxcv</strong></p>
<p><strong>zxcv</strong> zxcv zxcv</p>
TEXT;
echo preg_replace('@(<strong>)?zxcv(</strong>)?@', 'qwer', $text);
?>
<p>asdf qwer</p>
<p>qwer qwer qwer</p>

14. .*?, .+? : 매치범위를 최소화 한다.
<?php
$text = <<<TEXT
<a href="a">a</a><a href="b">b</a><a href="c">c</a>
TEXT;
preg_match('@<a .*>@', $text, $matches);
echo $matches[0]."\n";
preg_match('@<a .*?>@', $text, $matches);
echo $matches[0]."\n";
?>
<a href="a">a</a><a href="b">b</a><a href="c">c</a>
<a href="a">

Posted by 다오나무