BLOG main image
Category (326)
News (16)
All about me (1)
Diary (1)
Projects (8)
Programming (95)
Ideas (8)
Treasures (28)
Study (59)
Bookmark (19)
iPhone (77)
만들어보자!! Game Engine fo.. (0)
Android (0)
The matter of a single trade c..
17:23 - Ken Griffey Jr Shoes
The matter of a single trade c..
17:23 - Ken Griffey Jr Shoes
The matter of a single trade c..
17:22 - Ken Griffey Jr Shoes
Concentration and perseverance..
17:19 - Ken Griffey Jr Shoes
http://www.replicaoakleysungla..
05/18 - hgfhg
thanks for sharing
05/16 - replica watches
For Coach handbags alone, eBay..
05/10 - Coach outlet
thanks for sharing
05/10 - Coach outlet
좋은 게시물, 공유를위한 감사합..
05/10 - china wholesale
All of us need to preserve up..
05/07 - replica watches
free microsoft office 2010
free microsoft office 2010
特殊網站設計
特殊網站設計
特殊網站設計
特殊網站設計
Business Idea
Business Idea
surf lessons newport beach
surf lessons newport beach
295,709 Visitors up to today!
Today 2 hit, Yesterday 192 hit
daisy rss
tistory 티스토리 가입하기!
'iPhone/Development'에 해당되는 글 41건
2012/01/10 10:14

#define TCP_NODELAY 0x0001

int opt_val = 1;
setsockopt( sock, IPPROTO_TCP, TCP_NODELAY, &opt_val, sizeof(opt_val));

 

Trackback Address :: http://joyholic.kr/trackback/446 관련글 쓰기
Name
Password
Homepage
Secret
2011/02/07 10:36
http://developer.apple.com/library/ios/#documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html
Trackback Address :: http://joyholic.kr/trackback/435 관련글 쓰기
Name
Password
Homepage
Secret
2011/02/07 10:16
Original : http://improgrammer.com/12



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 <UITextFieldDelegate>



구현부(.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 alloc] init];

//[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];


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

candidateNumber = [numberFormatter numberFromString:candidateString];


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

if(candidateNumber == nil) {

return NO;

}


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

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

if ([[candidateNumber stringValue] compare: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:@"<UIKeyboard"]==YES ||
               [desc hasPrefix:@"<UIPeripheralHostView"] == YES ||
               [desc hasPrefix:@"<UISnap"] == YES )
            {
                [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:@"<UIKeyboard"]==YES ||
               [desc hasPrefix:@"<UIPeripheralHostView"] == YES ||
               [desc hasPrefix:@"<UISnap"] == YES )
            {
                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) 이제 시뮬레이터의 사진앨범에 가 보시면 아까 저장한 사진이 들어가있을겁니다.



위 글이 유용하셨다면 http://durl.kr/23tin 응원 한마디 부탁드립니다. 
Trackback Address :: http://joyholic.kr/trackback/434 관련글 쓰기
Name
Password
Homepage
Secret
2010/06/25 14:07

#if __APPLE__
#include "TargetConditionals.h"
#endif

#if TARGET_IPHONE_SIMULATOR
// jobs which should run on your simulator.
[yourObject doSomethingWithSimulator];
#else //TARGET_IPHONE_SIMULATOR
// jobs which should run on a real device.
[yourObject doSomethingWithDevice];
#endif //TARGET_IPHONE_SIMULATOR
Trackback Address :: http://joyholic.kr/trackback/420 관련글 쓰기
Name
Password
Homepage
Secret
2010/06/14 12:35
뭘까나??..
[UITextField명 becomeFirstResponder];

Trackback Address :: http://joyholic.kr/trackback/413 관련글 쓰기
Name
Password
Homepage
Secret
2010/06/14 11:30
#!/bin/bash
projectName="FlashCard"
xcodebuild -project $projectName.xcodeproj -configuration DIST clean build
rm -rf ~/Desktop/$projectName.zip
cd build/DIST-iphoneos/
zip -y -r ~/Desktop/$projectName.zip $projectName.app
 
Trackback Address :: http://joyholic.kr/trackback/412 관련글 쓰기
Name
Password
Homepage
Secret
2010/06/07 11:10

Creating Xcode project templates

From Mac Guides

Jump to: navigation, search

This guide explains how to create new project templates in Xcode. Project templates appear in the list of project types in the New Project dialog.

  1. Create a new project and setup everything as you'd like (NIB files, graphics, sounds, settings, code etc)
  2. Optionally, build and make sure the project works
  3. Use Finder and locate the project folder for your project you created in step 1
  4. Open another Finder window and navigate to /Library/Application Support/Apple/Developer Tools/Project Templates/. You have two options here:
    • Create a new folder for your custom project templates - this will appear as a category when creating a new project in XCode
    • Choose an already existing folder (eg Application) - this will place the project template in that category
  5. Open the new/chosen category folder and create a new folder inside. You can name this new folder whatever you like and it will appear as the project template name.
  6. Copy all files from the project folder in step 3 to the new template folder created in step 5. Note: If you built the project, delete the build folder from the template folder.
  7. Try to create a new project in Xcode. You should see your project template in one of the original categories or in the category you created, whichever you decided.
Trackback Address :: http://joyholic.kr/trackback/409 관련글 쓰기
Name
Password
Homepage
Secret
2010/05/31 17:39
Originals : http://www.greengar.com/2010/03/iphone-opengl-es-drawing-references/

We’ve been working with lots of OpenGL code today, so I thought I should document some of the resources we’re using. These might prove useful for others, too.

Apple’s GLSprite Sample Code

Framebuffer Object 201 – GameDev.net

Official OpenGL Documentation for glFramebufferTexture2D, which is very closely related to glFramebufferTexture2DEXT() and glFramebufferTexture2DOES() [most importantly, for iPhone OS]

Using Framebuffer Objects to Render to a Texture - iPhone Dev Center

Using a Framebuffer Object as a Texture - Mac OS X Reference Library

Forum – Render to Texture Example – Related to this Developer Forums post on how to Blit from one GL_TEXTURE_2D to another

Framebuffer Object 101

GLPaint Dissected – Forays into iPhone OpenGL ES – Introduction

FBO direction – iDevGames – iPhone Game Developers Forum – Render to texture example

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // notice the 'f'. is this guaranteed to fail?

rendering to an offscreen framebuffer – apple discussion forums

That’s all for now.

Trackback Address :: http://joyholic.kr/trackback/402 관련글 쓰기
Name
Password
Homepage
Secret
2010/05/27 17:34

[NSString stringWithCString:message 
                         encoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR)];

Trackback Address :: http://joyholic.kr/trackback/400 관련글 쓰기
Name
Password
Homepage
Secret
2010/05/11 10:12
defaults write com.apple.Xcode PBXCustomTemplateMacroDefinitions '{"ORGANIZATIONNAME" = "YourCompanyName"; }'
Trackback Address :: http://joyholic.kr/trackback/392 관련글 쓰기
Ken Griffey Jr Shoes | 2012/05/24 17:23 | PERMALINK | EDIT/DEL | REPLY
The matter of a single trade can sppuort a family.The master of seven trades cannot support himself.
Ken Griffey Jr Shoes | 2012/05/24 17:23 | PERMALINK | EDIT/DEL | REPLY
The matter of a single trade can sppuort a family.The master of seven trades cannot support himself.
Name
Password
Homepage
Secret
2010/04/29 17:28

Origins : http://blog.naver.com/melilyoo/140104172738

우선 이곳에서 푸시서비스를 등록해 보자.

 

http://ti-agile.blogspot.com/2010/01/programming-apple-push-notification.html

 

Device에 토큰 받아오는 부분까지 성공했다면.....

 

자바로  프로바이더 부분을 구현해보자.

 

KeyManagerFactory의 인증은 내가 가진 apple의 인증서를 넣어야 한다.

그리고 TrustManagerFactory의 인증은 공인인증된 인증서를 넣어야 한다. 그래서 java의 공인인증서를 넣은것이다.

 

그런다음 소켓을 연결하고 byte형식으로 토큰을 보내면 된다. ^^V

 

 

토큰은 아래와 같이 저장되었다. 알아보기 쉽게 하기 위해서 HEX값으로 표기했다. 보툥 0x를 빼고 저장하던데... 그냥 0x까지 붙여넣었다.

 0x6d0x4b0x950x440x6d0xe30x650x8f0xd90xe30xab0x5c0x090xcb0x970xd20x1b0x6f0x880xfe0x810xa50xf80xf70x030xfa0xeb0x7f0xc00x130xe50xc0

====== Source ======================================================================================================


import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import kr.co.confitech.girlboard.common.RowData;

 

public class APNSProvider{

 private final String HOST = "gateway.sandbox.push.apple.com";
 private final int   POST = 2195;
 private SSLSocket socket = null;

 

 public void provider(String[] tokens, RowData data) throws Exception{

  try{

   // Apple PNS 인증
   char[] password = "confitech".toCharArray();  
   FileInputStream fin = new FileInputStream("C:/Java/jdk1.5.0_16/jre/lib/security/pns.p12");
   KeyStore ks1 = KeyStore.getInstance("PKCS12");
   ks1.load(fin, password);

   KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
   kmf.init(ks1, password);

 

   // 공인 인증서 인증
   char[] password1 = "changeit".toCharArray();
   fin = new FileInputStream("C:/Java/jdk1.5.0_16/jre/lib/security/cacerts");
   KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
   ks.load(fin, password1);

   TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
   tmf.init(ks);
   fin.close();

 

   // 소켓 연결

   SSLContext ctx = SSLContext.getInstance("TLS");  
   ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

   SSLSocketFactory sf = ctx.getSocketFactory();
   socket = (SSLSocket)sf.createSocket(HOST, POST);
   if(!socket.isConnected()){
    return;
   }

   socket.setSoTimeout(10000);
   socket.startHandshake();

 

   String msg = "{\"aps\":{\"alert\":\""+data.get("alert")+"\",\"badge\":"+data.get("badge");
   if(data.get("sound") == null){
    msg = msg + "}}";
   }else{
    msg = msg + ",\"sound\":\""+data.get("sound")+"\"}}";
   }
   System.out.println(msg);


   OutputStream out = socket.getOutputStream();
   
   for(int i=0; i<tokens.length; i++){

    String strToken = tokens[i];

    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    //1. 0
    bout.write((byte)0x00);
    //2. 32 (token length)
    bout.write(to2ByteArray(32));
    //3. token
    for(int j = 0; j < 32; j++){
     String s = strToken.substring((j * 4) + 2, (j * 4) + 4);
     int z = Integer.parseInt(s, 16);     
     bout.write((byte)z);
    } 
    //4. message length
    bout.write(to2ByteArray(msg.getBytes().length));
    //5. message
    bout.write(msg.getBytes());

    // 푸시 보내기

    out.write(bout.toByteArray());
    out.flush();
   }

   out.close();  
   socket.close();

  }catch(Exception e){
   e.printStackTrace();
  }

 }

 /**
  *
  * @param i
  * @return
  */
 public static byte[] to2ByteArray(int i){
  byte[] b = new byte[2];
  b[0] = (byte)((i >>> 8) & 0xFF);
  b[1] = (byte)((i >>> 0) & 0xFF);
  return b;
 }

}

 ====== end ======================================================================================================

Trackback Address :: http://joyholic.kr/trackback/390 관련글 쓰기
Name
Password
Homepage
Secret
2010/04/29 17:27
One of the key limitations of the iPhone is its constraint on running applications in the background. Because of this, applications cannot keep running in the background when the user switches to another application. So, applications that require a constant state of connectivity (such as social networking applications) will not be able to receive timely updates.
To remedy this limitation, Apple released the Apple Push Notification Service (APNs). The APNs is a service that allows your device to be constantly connected to Apple's push notification server. When you want to send a push notification to an application installed on the users' devices, you (the provider) can contact the APNs so that it can deliver a push message to the particular application installed on the intended device.
In this article, you will learn how to perform the various steps needed to create an iPhone application that uses the APNs.

Generating a Certificate Request

The first step to using the APNs is to generate a certificate request file so that you can use it to request for a development SSL certificate later on.
1. Launch the Keychain Access application in your Mac OS X.
2. Select Keychain Access'Certificate Assistant'Request a Certificate From a Certificate Authority (see Figure 1):

Figure 1. Generating a certificate request
3. Enter the information required and check the Saved to disk option. Click Continue (see Figure 2).

Figure 2. Saving the certificate request to disk
4. Save the certificate request using the suggested name and click Save (see Figure 3): Click Done in the next screen.

Figure 3. Naming the certificate request

Creating an App ID

Each iPhone applications that uses the APNs must have a unique application ID that uniquely identifies itself. In this step, you will learn how to create an App ID for push notification.
1. Sign in to the iPhone Developer Program at: http://developer.apple.com/iphone/. Click on the iPhone Developer Program Portal on the right of the page (see Figure 4).

Figure 4. Launching the iPhone Developer Program Portal
2. You should see the welcome page (see Figure 5).

Figure 5. The welcome screen of the iPhone Developer Program Portal
3. Click on the App IDs tab on the left and then click on the New App ID button (see Figure 6).

Figure 6. Clicking on the App ID tab
4. Enter "PushAppID" for the Description and select Generate New for the Bundle Seed ID. For the Bundle Identifier, enternet.learn2develop.MyPushApp. Click Submit (see Figure 7).

Figure 7. Creating a new App ID
5. You should now see the App ID that you have created (together with those you have previously created) (see Figure 8).

Figure 8. Viewing the newly created App ID

Configuring an App ID for Push Notifications

Once an App ID is created, you need to configure it for push notifications.
1. To configure an App ID for push notification, you need to click the Configure link displayed to the right of the App ID. You will now see the option (see Figure 9).

Figure 9. Configuring an App ID for push notification service
Check the Enable for Apple Push Notification service option and click the Configure button displayed to the right of the Development Push SSL Certificate.
2. You will now see the Apple Push Notification service SSL Certificate Assistant screen. Click Continue (see Figure 10).

Figure 10. The Apple Push Notification service SSL Certificate Assistant screen
3. Click the Choose File button to locate the Certificate Request file that you have saved earlier. Click Generate (see Figure 11).

Figure 11. Generating the SSL certificate
4. Your SSL Certificate will now be generated. Click Continue (see Figure 12).

Figure 12. The APNs SSL certificate that is generated
5. Click the Download Now button to download the SSL Certificate. Click Done (see Figure 13).

Figure 13. Downloading the certificate generated
6. The SSL Certificate that you download is named aps.developer.identity.cer. Double-click on it to install it in the Keychain Access application (see Figure 14). The SSL certificate will be used by your provider application so that it can contact the APNs to send push notifications to your applications.

Figure 14. Installing the generated certificate into the Keychain Access application

Creating a Provisioning Profile

The next step is to create a provisioning profile so that your application can be installed onto a real device.
1. Back in the iPhone Development Program Portal, click on the Provisioning tab and click on the New Profile button (see Figure 15).

Figure 15. Selecting the Provisioning tab
2. Type in MyDevicesProfile as the profile name. Select PushAppID as the App ID. Finally, check all the devices that you want to provision (you can register these devices with the iPhone Developer Program Portal through the Devices tab). Click Submit (see Figure 16).

Figure 16. Creating a new provisioning profile
3. The provisioning profile will now be pending approval. After a while, you will see it appear. Click on the Download button to download the provisioning profile (see Figure 17).

Figure 17. Pending the approval of the provisioning profile
4. The downloaded provisioning profile is named MyDevicesProfile.mobileprovision.

Provisioning a Device

With the provision profile created, you will now install it onto a real device.
1. Connect your iPhone or iPod Touch to your Mac.
2. Drag and drop the downloaded MyDevicesProfile.mobileprovision file onto the Xcode icon on the Dock.
3. Launch the Organizer application from within Xcode and select the device currently connected to your Mac. You should see the MyDevicesProfile installed on the device (see Figure 18).

Figure 18. Viewing the installed provisioning profile

Creating the iPhone Application

1. In Xcode, create a new View-Based Application project and name it as ApplePushNotification.
2. Drag and drop a WAV file (shown as beep.wav in this example) onto the Resources folder in Xcode (see Figure 19).

Figure 19. Adding a WAV file to the project
3. Expand on the Targets item in Xcode and select the ApplePushNotification item. Press Command-I. In the Info window, click the Properties tab (see Figure 20).

Figure 20. Entering the App ID for the application
In the Identifier textbox, type <net.learn2develop.MyPushApp.
4. Click on the Build tab and type "Code Signing" in the search box. In the Any iPhone OS Device item, select the profile as shown in Figure 21:

Figure 21. Selecting the profile for code signing
5. In the ApplePushNotificationAppDelegate.m file, type the following code in bold:
#import "ApplePushNotificationAppDelegate.h"
#import "ApplePushNotificationViewController.h"
 
@implementation ApplePushNotificationAppDelegate
 
@synthesize window;
@synthesize viewController;
 
- (void)applicationDidFinishLaunching:(UIApplication *)application {    
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
 
    NSLog(@"Registering for push notifications...");    
    [[UIApplication sharedApplication] 
        registerForRemoteNotificationTypes:
        (UIRemoteNotificationTypeAlert | 
         UIRemoteNotificationTypeBadge | 
         UIRemoteNotificationTypeSound)];
 
}
 
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { 
 
    NSString *str = [NSString 
        stringWithFormat:@"Device Token=%@",deviceToken];
    NSLog(str);
 
}
 
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err { 
 
    NSString *str = [NSString stringWithFormat: @"Error: %@", err];
    NSLog(str);    
 
}
 
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
 
    for (id key in userInfo) {
        NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
    }    
 
}
 
- (void)dealloc {
    [viewController release];
    [window release];
    [super dealloc];
}
 
@end
6. Press Command-R to test the application on a real device. Press Shift-Command-R in Xcode to display the Debugger Console window. Observe carefully the device token that is printed (see Figure 22). In the figure below, the token is:38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7c e90d56e9 fe145bcc 6c2c594b. Record down this device token (you might want to cut and paste it into a text file).

Figure 22. Viewing the device token for push notification
7. If you go to the Settings application on your iPhone/iPod Touch, you will notice that you now have the Notifications item (see Figure 23).

Figure 23. Viewing the Notifications item in the Settings application

Creating the Push Notification Provider

A Push Notification provider is an application written by the application's developer to send push notifications to the iPhone application through the APNs.
Here are the basic steps to send push notifications to your applications via the Apple Push Notification Service (APNs):
1. Communicate with the APNs using the SSL certificate you have created earlier.
2. Construct the payload for the message you want to send.
3. Send the push notification containing the payload to the APNs.
The APNs is a stream TCP socket that your provider can communicate using a SSL secured communication channel. You send the push notification (containing the payload) as a binary stream. Once connected to the APNs, you should maintain the connection and send as many push notifications as you want within the duration of the connection.
Tip: Refrain from opening and closing the connections to the APNs for each push notification that you want to send. Rapid opening and closing of connections to the APNs will be deemed as a Denial-of-Service (DOS) attack and may prevent your provider from sending push notifications to your applications.
The format of a push notification message looks like Figure 24 (figure from Apple's documentation):

Figure 24. Format of a push notification message
For more details, please refer to Apple Push Notification Service Programming Guide.
The payload is a JSON formatted string (maximum 256 bytes) carrying the information you want to send to your application. An example of a payload looks like this:
{
    "aps": { 
        "alert" : "You got a new message!" ,
        "badge" : 5, 
        "sound" : "beep.wav"},
     "acme1" : "bar", 
     "acme2" : 42
}
To save yourself the trouble in developing a push notification provider from scratch, you can use the PushMeBabyapplication (for Mac OS X) written by Stefan Hafeneger (Get it here).
1. Open the PushMeBaby application in Xcode.
2. Right-click on the Resources folder in Xcode and select Add Existing Files…. Select theaps.developer.identity.cer file that you have downloaded earlier (see Figure 25).

Figure 25. Adding the SSL certificate to the application
3. In the ApplicationDelegate.m file, modify the code as shown in bold below:
- (id)init {
    self = [super init];
    if(self != nil) {
        self.deviceToken = @"38c866dd bb323b39 ffa73487 5e157ee5 a85e0b7c e90d56e9 fe145bcc 6c2c594b";
 
        self.payload = @"{\"aps\":{\"alert\":\"You got a new message!\",\"badge\":5,\"sound\":\"beep.wav\"},\"acme1\":\"bar\",\"acme2\":42}";
 
        self.certificate = [[NSBundle mainBundle] 
            pathForResource:@"aps_developer_identity" ofType:@"cer"];
    }
    return self;
}
4. Press Command-R to test the application. You will be asked to grant access to the certificate. Click Always Allow (see Figure 26):

Figure 26. Granting access to the SSL certificate
On the iPhone/iPod Touch, ensure that the ApplePushNotification application is not running. To send a message to the device, click the Push button. The server essentially sends the following message to the Apple Push Notification server:
{
    "aps": { 
        "alert" : "You got a new message!" ,
        "badge" : 5, 
        "sound" : "beep.wav"},
     "acme1" : "bar", 
     "acme2" : 42
}
5. If the message is pushed correctly, you should see the notification as shown in Figure 27.

Figure 27. Receiving a Push Notification message
6. If you now debug the ApplePushNotification application by pressing Command-R and send a push message from the PushMeBaby application, the Debugger Console window will display the following outputs:
2009-11-24 21:11:49.182 ApplePushNotification[1461:207] key: acme1, value: bar
2009-11-24 21:11:49.187 ApplePushNotification[1461:207] key: aps, value: {
    alert = "You got a new message!";
    badge = 5;
    sound = "beep.wav";
}
2009-11-24 21:11:49.191 ApplePushNotification[1461:207] key: acme2, value: 42



From http://mobiforge.com/developing/story/programming-apple-push-notification-services
Trackback Address :: http://joyholic.kr/trackback/389 관련글 쓰기
Name
Password
Homepage
Secret
2010/04/07 15:48
Original : http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/

How to build an Apple Push Notification provider server (tutorial)

July 10, 2009
by David Mytton

One of the widely anticipated features of the new iPhone OS 3.0 is push notifications which allow messages to be sent directly to an individual device relevant to the application that has been installed. Apple have demoed this as useful for news alerts, or IM notifications however it fits in perfectly with the nature of our server monitoring service, Server Density.

Server monitoring iPhone application alert view

As part of the product, we have an iPhone application that includes push notifications as an alerting option so you can be notified via push direct to your iPhone when one of your server alerts have been triggered. This is useful since our app can then be launched to instantly see the details of the server that has caused the alert.

Apple provides detailed code documentation for the iPhone OS code that is needed to implement and handle the alerts on the device but only provides a higher level guide for the provider server side.

As a provider, you need to communicate with the Apple Push Notification Service (APNS) to send the messages that are then pushed to the phone. This is necessary so that the device only needs to maintain 1 connection to the APNS, helping to reduce battery usage.

This tutorial will go into code-level detail about how we built our push notification provider server to allow us to interact with the APNS and use the push notifications with our server monitoring iPhone application. Since we develop in PHP, our examples will be in PHP 5.

Basic Structure

  1. You connect to the APNS using your unique SSL certificate
  2. Cycle through the messages you want to send (or just send 1 if you only have 1)
  3. Construct the payload for each message
  4. Disconnect from APNS

The flow of remote-notification data is one-way. The provider composes a notification package that includes the device token for a client application and the payload. The provider sends the notification to APNs which in turn pushes the notification to the device.

- Apple documentation

APNS Flow

Restrictions

  • The payload is limited to 256 bytes in total – this includes both the actual body message and all of the optional and additional attributes you might wish to send. Push notifications are not designed for large data transfer, only for small alerts. For example we only send a short alert message detailing the server monitoring alert triggered.
  • APNS does not provide any status feedback as to whether your message was successfully delivered. One reason for this is that messages are queued to be sent to the device if it is unreachable, however only the last sent message will be queued – overwriting any previously sent but undelivered messages.
  • Push notifications should not be used for critical alerts because the message will only be delivered if the device has wifi or cellular connectivity, which is why we recommend combining push with another alerting method such as e-mail or SMS for our server monitoring alerts.
  • The SSL certificates used to communicate with APNS, discussed below, are generated on an application level. The implementation discussed in this tutorial only concerns a single iPhone application so if you have several, you will need to adapt the code to use the appropriate certificate(s) where necessary.

Device Token

Each push message must be “addressed” to a specific device. This is achieved by using a unique deviceToken generated by APNS within your iPhone application. Once this token has been retrieved, you need to store it on your server, not within your iPhone application itself. It looks something like this:

c9d4c07c fbbc26d6 ef87a44d 53e16983 1096a5d5 fd825475 56659ddd f715defc

For the Server Density iPhone application, we call the necessary generation methods on app launch and pass it back to our servers via an HTTP API call. This stores the deviceToken in a database on our servers for that user so we can then communicate with the device linked to that user.

Feedback Service

Apple provide a feedback service which you are supposed to occasionally poll. This will provide a list of deviceTokens that were previously but are no longer valid, such as if the user has uninstalled your iPhone application. You can then remove the deviceToken from your database so you do not communicate with an invalid device.

Using the feedback service is not covered by this tutorial.

Certificates

The first thing you need is your Push certificates. These identify you when communicating with APNS over SSL.

Generating the Apple Push Notification SSL certificate on Mac:

  1. Log in to the iPhone Developer Connection Portal and click App IDs
  2. Ensure you have created an App ID without a wildcard. Wildcard IDs cannot use the push notification service. For example, our iPhone application ID looks something like AB123346CD.com.serverdensity.iphone
  3. Click Configure next to your App ID and then click the button to generate a Push Notification certificate. A wizard will appear guiding you through the steps to generate a signing authority and then upload it to the portal, then download the newly generated certificate. This step is also covered in the Apple documentation.
  4. Import your aps_developer_identity.cer into your Keychain by double clicking the .cer file.
  5. Launch Keychain Assistant from your local Mac and from the login keychain, filter by the Certificates category. You will see an expandable option called “Apple Development Push Services”
  6. Expand this option then right click on “Apple Development Push Services” > Export “Apple Development Push Services ID123″. Save this as apns-dev-cert.p12 file somewhere you can access it.
  7. Do the same again for the “Private Key” that was revealed when you expanded “Apple Development Push Services” ensuring you save it as apns-dev-key.p12 file.
  8. These files now need to be converted to the PEM format by executing this command from the terminal:
    openssl pkcs12 -clcerts -nokeys -out apns-dev-cert.pem -in apns-dev-cert.p12
    openssl pkcs12 -nocerts -out apns-dev-key.pem -in apns-dev-key.p12
  9. If you wish to remove the passphrase, either do not set one when exporting/converting or execute:
    openssl rsa -in apns-dev-key.pem -out apns-dev-key-noenc.pem
  10. Finally, you need to combine the key and cert files into a apns-dev.pem file we will use when connecting to APNS:
    cat apns-dev-cert.pem apns-dev-key-noenc.pem > apns-dev.pem

It is a good idea to keep the files and give them descriptive names should you need to use them at a later date. The same process above applies when generating the production certificate.

Payload Contents

The payload is formatted in JSON, compliant with the RFC 4627 standard. It consists of several parts:

  • Alert – the text string to display on the device
  • Badge – the integer number to display as a badge by the application icon on the device home screen
  • Sound – the text string of the name of the sound to accompany the display of the message on the device
  • This tutorial will only deal with the basics by sending a simple alert text string but this can also be another dictionary containing various options to display custom buttons and the like.

Creating the payload

Using PHP it is very easy to create the payload based on an array and convert it to JSON:

$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload = json_encode($payload);

 
Echoing the contents of $payload would show you the JSON string that can be sent to APNS:

{
     "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" }
}

 
This will cause a message to be displayed on the device, trigger the default alert sound and place a “1″ in the badge by the application icon. The default buttons “Close” and “View” would also appear on the alert that pops up.

For the Server Density server monitoring iPhone application, it is important for the user to be able to tap “View” and go directly to the server that generated the alert. To do this, we add an extra dictionary in of our own custom values:

$payload['aps'] = array('alert' => 'This is the alert text', 'badge' => 1, 'sound' => 'default');
$payload['server'] = array('serverId' => $serverId, 'name' => $name);
$output = json_encode($payload);

 
The custom dictionary server is passed to the application on the device when the user taps “View” so we can load the right server. The JSON looks like this:

{
     "aps" : { "alert" : "This is the alert text", "badge" : 1, "sound" : "default" },
     "server" : { "serverId" : 1, "name" : "Server name")
}

 
The size limit of 256 bytes applies to this entire payload, including any custom dictionaries.

The raw interface

Once an alert is generated within Server Density, the payload is built and then inserted into a queue. This is processed separately so that we can send multiple payloads in one go if necessary.

Apple recommends this method because if you are constantly connecting and disconnecting to send each payload, APNS may block your IP.

As described by Apple:

The raw interface employs a raw socket, has binary content, is streaming in nature, and has zero acknowledgment responses.

APNS Binary Format

Opening the connection

The PHP 5 code to open the connection looks like this:

$apnsHost = 'gateway.sandbox.push.apple.com';
$apnsPort = 2195;
$apnsCert = 'apns-dev.pem';

$streamContext = stream_context_create();
stream_context_set_option($streamContext, 'ssl', 'local_cert', $apnsCert);

$apns = stream_socket_client('ssl://' . $apnsHost . ':' . $apnsPort, $error, $errorString, 2, STREAM_CLIENT_CONNECT, $streamContext);

 
If an error has occurred you can pick up the error message from $errorString. This will also contain the details if your SSL certificate is not correct.

The certificate file is read in relative to the current working directory of the executing PHP script, so specify the full absolute path to your certificate if necessary.

Note that when testing you must use the sandbox with the development certificates. The production hostname is gateway.push.apple.com and must use the separate and different production certificate.

Sending the payload

At this point, the code we use loops through all the queued payloads and sends them. Constructing the binary content to send to APNS is simple:

$apnsMessage = chr(0) . chr(0) . chr(32) . pack('H*', str_replace(' ', '', $deviceToken)) . chr(0) . chr(strlen($payload)) . $payload;
fwrite($apns, $apnsMessage);

 
Note that the $deviceToken is included from our database and stripped of the spaces it is provided with by default. We also include a check to send an error to us in the event that the $payload is over 256 bytes.

$apnsMessage contains the correctly binary formatted payload and the fwrite call writes the payload to the currently active streaming connection we opened previously, contained in $apns.

Once completed, you can close the connection:

socket_close($apns);
fclose($apns);

php-apns

There is a free, open source server library that does all the above functionality called php-apns. We chose to implement it ourselves because it has a further dependancy on memcached, we do not want to rely on 3rd party code for large and critical aspects of our code-base and I am apprehensive about the suitability of PHP for running a continuous server process. We do all the above queue processing using our own custom cron system which runs every few seconds – that way PHP scripts do not need to be run as processes, something I’m not sure they were designed to do!

All done

That’s it! If you have any problems, post in the comments below and we’ll do our best to help out. Also, Stack Overflow is your friend.

Trackback Address :: http://joyholic.kr/trackback/387 관련글 쓰기
Name
Password
Homepage
Secret
2010/03/23 09:56
UIButton *btn = [[UIButton alloc] init];
UIImage *img = [UIImage imageNamed:@"image.png"];
[btn setImage:img forState:UIControlStateNormal]
[img release];
Trackback Address :: http://joyholic.kr/trackback/386 관련글 쓰기
Name
Password
Homepage
Secret
2010/03/19 15:20
- (void)loadView {
    [super loadView];
    self.view.autoresizesSubviews = YES;
    self.view.autoresizingMask = {UIViewAutoresizingFlexibleWidth | UIViewAutosizingFleszbleHeight};
}

Trackback Address :: http://joyholic.kr/trackback/385 관련글 쓰기
Name
Password
Homepage
Secret
2009/10/29 09:54
Original : http://www.therareair.com/2009/01/01/tutorial-how-to-compile-openssl-for-the-iphone/


This is a quick tutorial to show you how to minimally compile a version of the openssl and crypto libraries for the iPhone.
 

Download and Configure OpenSSL

First thing to do is grab the openssl source.  You can get that here.  I’ll be using openssl-0.9.8i for this demo.  Unzip this file (mines on the desktop).  Open up a terminal and go to the unzipped folder and run the default configuration.  The argument passed is where your ‘make install’ will place the compiled libraries. You should replace this with your path.

cd Desktop/openssl-0.9.8i
./config --openssldir=/Users/airpard/Desktop/openssl_arm/

Edit the Makefile

Next thing to do is open up the make file.  This is named “Makefile” in the current directory you should already be in with the terminal.  Here are the list of changes to make:

Find CC= cc and change it to:
CC= /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.0

Find -arch i386 in CFLAG and change it to:
-arch armv6

Find CFLAG and add to the BEGINNING!!:
-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk

Find SHARED_LDFLAGS=-arch i386 -dynamiclib and change it to:
SHARED_LDFLAGS=-arch armv6 -dynamiclib


Fix Build Error

If you build it at this point you may have noticed a build error. To fix this open up ui_openssl.c. This is located in openssl-0.9.8i/crypto/ui/ folder. If you have a text editor with line numbers, head down to line 403. Otherwise do a text search to make this change:

static volatile sig_atomic_t intr_signal;
to 
static volatile int intr_signal;

Save your changes and you should now be able to build with no errors.

Build Libraries

make
make install

That’s it. You’ll notice that everything was moved to the path provided in step 1 when configuring openssl. Remember to add the include folder to your Xcode project. Also, remember these libraries are only built for the iPhone and will not work in the simulator. You can change all the armv6 references to i386 and build it again if you choose to. Happy Coding!

Examples

Some people had some questions about how to use the libraries in an Xcode project. Here is a simple xcode project including just the linking of the libraries and adding of the header files: openssl_tutorial

For the lazy people.  Compiled libraries: compiled_libraries

Responses

Hi,

Thanks for the tutorial. One question – must I build this the same (but change to i386) to make a working lib for the iphone simulator?

How do you make the project contain both a working simulator lib and the actually iphone (arm) lib?

BTW, make seems to compile everything fine and then:

ld: unknown option: -openssldir=/Users/liamjfoy/Viewcurl/libcurl/openssl_arm/
collect2: ld returned 1 exit status
make[2]: *** [link_app.] Error 1
make[1]: *** [openssl] Error 2
make: *** [build_apps] Error 1

Hi Liam — I haven’t messed with openssl in the simulator for awhile, but since openssl is part of OS X you may get away with just building it for the phone (unless they have fixed this simulator bug).

If you are going to build both libraries and wish to run them in both the simulator and iPhone there are a few options. The one I like is to create three targets in Xcode. One being the iPhone application for armv6 architecture. The second target all the same except building for the i386 simulator. And a third target being ‘All’ that builds both targets. This is a of type ‘Aggregate’ under the other tab in the New Target wizard. If you only want to maintain one target you can simply link both libraries in the same target, no harm in doing this but remember to build it in the phone ;p

Liam — In regards to your error. The second line (the config line) uses a double dash. Don’t copy and paste that weird dash in there.

Thanks eric I’ve fixed everything now. I’ll let you know with regards to the first question I asked :) thanks for the tutorial!

Liam

Thanks for the peer coding ;p

Just so you know I’m trying to build libcurl with SSL support for the iPhone. I can build both of them on there own so tonight I’m going to try and make libcurl use the openssl lib your tutorial helped me to create :-) (I see you work for apple! hi apple! haha)

Sounds cool. Let me know how it works out. And Hello to you ;p

Hey eric – I’ve look around for some documentation with regards to using the i386 build of the lib and arm build of the lib in my project. Do you know of any good tutorials :) ?

i’m building ssh for the iphone. i’ve built ssl as per your instructions, and included the libs in the resources for my xcode project. we want to base building ssh off of openssl, rather than the ssl include files and such that come with mac os.

problem is that there are a number of multiple definitions between ssh’s sha2.h and ssl’s sha.h. when i use the mac version, it compiles ok, when i use openssl’s version, i get a lot of conflicts. i assume i want to be using ssh’s definitions, so i need to keep sha2.h intact.

have you seen this issue? i’m on openssl 0.9.8j and openssh 5.1p1.

thanks.

Mickey – You should have no problems if you add the include folder in the downloaded version of openssl to the header search path for the target. I’ve used ssh for multiple projects with no conflicts.

which directory? when i look in the directory include/openssl under the source directory, i see all the include files are links. when i look under the project i set up and compiled according to your instructions, i have a directory openssl_arm/openssl/include. the files sha.h in these 2 directories have 2 completely different sizes. i assume i should be using the original includes?

unfortunately, i get the same thing either directory i use. if i then copy the sha.h file from /usr/include/openssl, and substitute it, the problem goes away.

any thoughts? do i have a version incompatibility between openssh and openssl?

another issue you may be able to point me in the right direction. even before i downloaded openssl, openssh compiled just fine for mac os on the command line. ssh runs, no problem.

when in xcode for the iphone, i’m getting undefined symbols, like BN_new().

BN_new() is not defined anywhere in openssh, and sure enough, a nm(1) reveals:

U _BN_new()

for ssh. there are no other libs compiled with ssh except for what is built there.

BN_new() IS defined in openssl, and i have included the library i built following your instructions as a resource in my xcode project, and it shows up as a toolbox.

do you have any idea as to why these are coming up undefined?

thanks again…

Mickey- After you’re done compiling in the output folder there should be a lib and include folder. These are the folders to add to your project. Within the project, select your iPhone target and hit command-i. Find the user header paths. Select the box to always use user header paths. Then add ‘include/openssl’ to the user header paths. Link to the new libraries and that should be all you have to do.

Wow, what a great find — thanks a lot for the tutorial!

I’m also trying to get OpenSSH working with your OpenSSL output. I’m compiling OpenSSH from the command line. I tried to replicate the tricks you used in your OpenSSL method above, but I couldn’t find any mention of i386 (so I wasn’t sure if the armv6 options were required or not). I got the following errors:

1) I got an error where it tried to look for some resolv8_compat.h and nameser8_compat.h files. I fixed that by copying these files from /usr/include

2) It couldn’t find the appropriate libs. I tried copying the output libs from your project to the iPhone SDK lib folder, and then adding an appropriate -L LDFLAG for the iPhone SDK lib folder, but I think the architecture flag isn’t set correctly, since I get a bunch of errors:

/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.0 -o ssh ssh.o readconf.o clientloop.o sshtty.o sshconnect.o sshconnect1.o sshconnect2.o mux.o -L. -Lopenbsd-compat/ -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr/lib -fstack-protector-all -arch armv6 -lssh -lopenbsd-compat -lcrypto -lz
ld warning: in openbsd-compat//libopenbsd-compat.a, file is not of required architecture
ld warning: in /usr/lib/libcrypto.dylib, missing required architecture arm in file
Undefined symbols:
“_BN_copy”, referenced from:
_key_from_private in libssh.a(key.o)
_key_from_private in libssh.a(key.o)

[......around 50-100 lines.....]

“_RSA_new”, referenced from:
_key_new in libssh.a(key.o)
_key_demote in libssh.a(key.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [ssh] Error 1

I tried a bunch of things but couldn’t figure out what the problem is.

I’m using the latest official stable OpenSSH source code (specifically http://mirror.planetunix.net/pub/OpenBSD/OpenSSH/portable/openssh-5.1p1.tar.gz).

If you’re up for putting up a new tutorial, openssh would be a really great one to do!

eric – thanks for the response. that is what i am doing. i did have to pull the sha.h from /usr/include /openssl to get it to compile, but it did. however, i’m getting duplicate symbols on linking. SHA256_Init(() is defined both in sha256.o in openssl, and in sha2.o of ssh. same function name, different function contents. i don’t see how these can coexist. that is why i was wondering if i have versions of the two that aren’t compatible.

by the way, do you mean adding ‘include/openssl’ or the full pathname?

Strat – To build for i386 just run the config as you normally would. So basically you will just do step one of the tutorial. Skip the Makefile edits and just make;make install.

thanks for the post eric. a slightly cleaner option might be to add an entry in Configure per the install instructions. I.e. duplicate the line in Configure that begins with “darwin-i386-cc”. Change occurrences of i386 on the line to armv6, change cc to the toolchain compiler, and add the -isysroot flag. Now doing

./Configure darwin-armv6-cc –prefix=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr

gets you the proper makefile and will install in the toolchain directory.

Marc

Hey, thanks a million for the tutorial and the binaries! You saved me a *lot* of frustration. In return, here’s a tip on how to avoid setting up multiple projects for simulator vs. device:

lipo libcrypto_arm.a libcrypto_i386.a -create -output libcrypto.a

Do the same for libssl.a and bingo, you’ve got universal libraries that will work in either environment!

Hello Guys

I am iPhone developer, I want to build one iPhone application using SSH, As I have downloaded openSSL from above link, I am’t able to use OpenSSL in my project, So can you please provide me any sample of xCode with simple connection with Server or any sample command?

thanks
Jayanti

Thank you very much for the tutorial! I’m trying to recompile some opensource packages for iPhone and this HOWTO is exactly I was looking for! Now I have successfully compiled openssl-0.9.8k for iPhoneOS 3.0 and some other openssl related packages.

But I’m still having problems recompiling ipsec-tools package. It successfully links my precompiled openssl libraries but later make fails with the following error:

Undefined symbols:
“_yywrap”, referenced from:
_yylex in token.o
_input in token.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[4]: *** [setkey] Error 1
make[3]: *** [all] Error 2
make[2]: *** [all-recursive] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

Is this bug somehow specific to iPhone platform or I just missed some important flags when configuring? Would someone help please as I have no more ideas where to look for the issue..

What would you charge to get a basic SSH implementation up and working, I want to drop it into my project and send a message of where to connect (with user/pwd/server/etc) and the command I want executed. The class should close the connection and return the output from the command executed.

Trackback Address :: http://joyholic.kr/trackback/382 관련글 쓰기
Name
Password
Homepage
Secret
2009/07/10 01:38

Summary

If you need to find your iPhone serial number, International Mobile Equipment Identity (IMEI) number, identifier, or ICCID number this article shows you several different ways you can locate it.

Click one of the items below to see how to view this info:

  • In iTunes

    • When iPhone is connected
    • When iPhone is not connected
  • On iPhone

    • In the iPhone About screen
    • On the SIM tray of iPhone 3G or on the back of the original iPhone
  • On a Mac using Apple System Profiler

  • On your iPhone packaging

Products Affected

iPhone, iTunes, iPhone 3G

When iPhone is connected

Note: Some carriers may not store the phone number on the SIM card so the data may not be available in iTunes. If that is the case, use one of the other methods to find the phone number. See HT2232 for more information.

  1. Connect your iPhone to your computer.
  2. When your iPhone appears in iTunes 7.6 or later, select it.
  3. Click the Summary tab, and your iPhone's serial number  and phone number will display on screen as shown below:

     

  4. If you click the words "Phone Number" in this tab iTunes will also display the IMEI of your iPhone as shown below. If you click "IMEI," iTunes will display the ICCID. If you click "Serial Number" iTunes will display the identifier. 


     

Note: You can choose Edit > Copy to put the serial number on the Clipboard. You can then paste the serial number into an email or web page (for service or registration for example).

When iPhone is not connected

Note: Some carriers may not store the phone number on the SIM card so the data may not be available in iTunes. If that's the case, use one of the other methods to find the phone number. See HT2232 for more information.

Open iTunes and mouse over a device backup:

  1. If you are using iTunes 8.1 or later, open Preferences in iTunes (In Mac OS X, choose iTunes > Preferences. In Windows, choose Edit > Preferences).
  2. Click the Devices tab.
  3. Position the mouse over a backup to display the phone number, serial number, and IMEI of the backed up iPhone.


  1. If you are using iTunes 7.6.2 or later, you can also hold down the Control key and choose Help > About iTunes (Windows) or iTunes > About iTunes (Mac).
  2. Release the Control key.
  3. As the iTunes and QuickTime version information scrolls, you will see the last connected iPhone's serial number and IMEI.

About Screen Tips:
  • Hold down the Option key (Shift key in Windows) to reverse the scrolling.
  • Press the Space bar to pause the scrolling.
  • You can copy this information onto the Clipboard and and paste it into a document.

    In Mac OS X, choose Edit > Copy (or Command-C).
    In Windows, press Control-C

On the SIM tray of iPhone 3G

On the the back of the original iPhone

Your original iPhone serial number and IMEI are engraved on the back metal case as shown in the photo below:

iPhone About screen

You can find your iPhone serial number,IMEI, and ICCID in the About screen on your iPhone. From the Home screen, tap Settings > General > About and scroll down.

In Apple System Profiler

When iPhone is in recovery mode, iTunes will display n/a for the Serial Number and IMEI, but if you have the latest version of iTunes installed, you can use Apple System Profiler on your Mac to view the Serial Number and IMEI:

iPhone packaging

If you still have the original packaging that your iPhone came in, you can find your iPhone serial number and IMEI printed on the barcode label that's affixed to the packaging.

Trackback Address :: http://joyholic.kr/trackback/380 관련글 쓰기
Name
Password
Homepage
Secret
2009/07/10 01:35

There is no oficial way to get it, but....

in the apples private framework "CoreTelephony.framework" (Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.0.sdk/System/Library/PrivateFrameworks/CoreTelephony.framework)

There is a method __CTGetIMEI

If you know, how to work with private frameworks, it can help you. ;)

Trackback Address :: http://joyholic.kr/trackback/379 관련글 쓰기
Name
Password
Homepage
Secret
2009/06/08 14:55
Originals : http://iphonedevelopertips.com/cocoa/launching-other-apps-within-an-iphone-application.html

Launching Other Apps within an iPhone Application

In an earlier post I talked about how to launch the browser from within an iPhone application using the UIApplciation:openURL: method.

It is also possible to use this same technique to launch other applications on the iPhone that are very useful.

Examples of some of the key applications that you can launch via URL are:

  • Launch the Browser (see earlier post )
  • Launch Google Maps
  • Launch Apple Mail
  • Dial a Phone Number
  • Launch the SMS Application
  • Launch the Browser
  • Launch the AppStore

Launch Google Maps

The URL string for launching Google Maps with a particular keyword follows this structure:

http://maps.google.com/maps?q=${QUERY_STRING}

The only trick to this is to ensure that the value for the ${QUERY_STRING} is properly URL encoded. Here is a quick example of how you would launch Google Maps for a specific address:

1
2
3
4
5
6
7
8
9
10
11
// Create your query ...
NSString* searchQuery = @"1 Infinite Loop, Cupertino, CA 95014";
 
// Be careful to always URL encode things like spaces and other symbols that aren't URL friendly
searchQuery =  [addressText stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
 
// Now create the URL string ...
NSString* urlString = [NSString stringWithFormat:@"http://maps.google.com/maps?q=%@", searchQuery];
 
// An the final magic ... openURL!
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlText]];

Launch Apple Mail

Also very useful, is the ability to enable a user to quickly send an email by launching the email client in compose mode and the address already filled out. The format of this URI should be familiar to anyone that has done any work with HTML and looks like this:

mailto://${EMAIL_ADDRESS}

For example, here we are opening the email application and filling the “to:” address with info@iphonedevelopertips.com :

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"mailto://info@iphonedevelopertips.com"]];

Dial a Phone Number (iPhone Only)

You can use openURL: to dial a phone number. One advantage this has over other URLs that launch applications, is that the dialer will return control back to the application when the user hits the “End Call” button.

Anyone familiar with J2ME or WML will find this URL scheme familiar:

tel://${PHONE_NUMBER}

Here is an example of how we would dial the number (800) 867-5309:

1
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://8004664411"]];

NOTE When providing an international number you will need to include the country code.

Launch the SMS Application

Also not supported by the iPod Touch, is the ability to quickly setup the SMS client so that your users can quickly send a text message. It is also possible to provide the body of the text message.

The format looks like this:

sms:${PHONENUMBER_OR_SHORTCODE}

NOTE: Unlike other URLs, an SMS url doesn’t use the “//” syntax. If you add these it will assume it is part of the phone number which is not.

1
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms:55555"]];

NOTE: According to the official SMS specification, you should be able to send a body as well as the phone number by including “?body=” parameter on the end of the URL … unfortunately Apple doesn’t seem to support this standard.

Launching the AppStore

Finally, it is worth noting that you can launch the AppStore and have the "buy" page of a specific application appear. To do this, there is no special URL scheme. All you need to do is open up iTunes to the application you want to launch; right-click on the application icon at the top left of the page; and select Copy iTunes Store URL .

The URL will look something like this:

http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=291586600&mt=8

Launching the AppStore URL is exactly the same as you would launch the browser. Using the link above, here is an example of how we would launch the AppStore:

1
2
NSURL *appStoreUrl = [NSURL URLWithString:@"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=291586600&amp;mt=8"];
[[UIApplication sharedApplication] openURL:appStoreUrl];
Cocoa

Comments

23 Responses to “Launching Other Apps within an iPhone Application”
  • URL schemes are great, but one important piece of information that you didn’t mention is that openURL: returns a boolean that can be used to determine whether the device is able to handle the URL.

    For example if you do tel: or sms: on an iPod touch it will return NO and you can display an error message.

    This becomes critical when you use URL schemes for applications you can download from the AppStore. My app, for example, allows you to add bookmarks to Delicious, but obviously the ‘yummy:’ URL scheme won’t work if it’s not installed!

  • Raj says:

    What about launching some other 3rd party application. Or starting some other process from one process?

  • Rodney says:

    @Stephen that is a great point. Thanks for the comment.

    @Raj it is possible to invoke a 3rd party application ONLY if said application has taken the necessary steps to register the URL scheme with the phone. I’ll try to dig up an example to illustrate how this is done.

    The URL scheme is the text before the “://” in the URL so if you wanted to create a scheme “foo” a URL would look like “foo://….”. You should even be able to pass parameters in the URL. I’ve not tried to do this yet, but as soon as I find out how I’ll post back here.

    - Rodney

  • Darren says:

    @Stephen:
    Is that correct? It may be true for tel: and sms: URL schemes, but I don’t think it applies to custom URL schemes.

    In my testing openUrl: always returns YES, even when called with an unsupported URL scheme. I can’t find a way to prevent the OS from displaying its own “Unsupported URL” alert message, nor a way to query for supported URL schemes.

  • Darren, yes it does work even for custom URL schemes. The iPhone sometimes gets confused if you install and remove applications with URL schemes:

    http://openradar.appspot.com/6045562

    Maybe that’s what you’re seeing?

    And no, there’s no (documented) way of discovering whether a URL scheme is supported. The way I do it try it and if it fails then disable the option next time. It’s imperfect but as far as I know the best you can do at the moment.

  • David Heacock says:

    Does anyone know how to launch a custom application from an email or sms?

    Cheers

  • @David Heacock

    The process of launching an application is as simple as including a URL in the email or sms message. Follow the steps in this article to register your application to respond to a particular URL and then just put that URL in your message.

    NOTE: There is currently no push support so the user will still need to click the URL for it to actually open the application.

  • @David Heacock

    I forgot which article this was … the article you need that explains how to register your own application URL is located here:

    http://iphonedevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html

    Cheers,
    Rodney

  • Dho says:

    Anyway to launch the iPod app to start playing a certain song?

  • Rodney says:

    @Dho

    To my knowledge this is not possible today.

  • Scenario says:

    I’ve seen that Apple’s own iPhone apps can send an email from a special mailer view that comes and goes, within the app– similar to how we are allowed to pick and even add/edit Contacts from within our apps.

    Does anyone know if this “SendMail” API has been made available to us in the SDK?

  • @Scenario: nope, the “SendMail” API is not available unless you’re Apple. The only option is to use the mailto: URL scheme. Or include your own SMTP client.

    Also, I found that I now see what @Darren is getting. This certainly worked in iPhone OS 2.0. Looks like something broke.

  • gabe says:

    Thanks guys, now how do you launch iphone’s built-in address book?

    Generally code samples talk about creating own interface into the address database (e.g. using AddressBookUI), but say you want your app to just launch iphone’s “Contacts” app? Thx. Gabe.

  • @Gabe … I am not aware of a way to launch the Address book external to an App. Let us know if you find anything.

  • Pranathi says:

    Hi,
    I have an app in which I need to play a video. Can you tell me if there is a way I can do it without using YouTube? Does QT player support being invoked using URL? Also, once the video is completed, I would like my application to be restored? Is it possible?

    Appreciate any pointers on this.

    Thanks.

  • anil says:

    Hi,
    I want to open the calendar application from my custom application. What URL i can use for that.?

  • kanayl says:

    Hi
    i am trying openURL for mailto functionality but no success (in simulator) using 2.2.1. can any body tell where is problem
    Also i want to enter date from my app into iphone calender, any body have any idea?

    Thanks

  • @kanayl

    The simulator does not come loaded with the email application that is why you can’t use the mailto functionality in the simulator.

    As for the calendar, there is not currently a way to do this.

  • Raji says:

    I am trying openurl for call option, Once the call ended it returns back to my application (restarting the application). Can anyone help me , i want to return back to the same place where i clicked to call.

    Thanks

  • Hi Raji, I’m afraid that it can’t be done with the publicly available APIs.

  • Raji says:

    Thanks Stephen.

  • rob says:

    Hi,

    I’m want to open an app if it’s also installed on the device, and notify the user otherwise, but the app hangs on the openurl line of code, so never beeps? Any ideas how I can work around this anyone?

    BOOL win = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];

    if( win == 0 ) { void NSBeep(); };

  • Rob,

    NSBeep isn’t available as part of the iPhone’s API.

    Cheers,
    –> Stephen

Trackback Address :: http://joyholic.kr/trackback/377 관련글 쓰기
Name
Password
Homepage
Secret
2009/05/13 18:20
Original : http://developer.apple.com/iphone/library/technotes/tn2009/tn2242.html

Resolving "0xE800003A", applications not launching and "missing entitlement"

If your application fails to launch on the device with an error of "0xE800003A", it generally means your application is signed in a way that prevents it from launching on the device on which it's running.

There are a number of reasons why this might happen. The most common reasons are an incorrect (or no) Code Signing Identity was selected in Xcode's Build Info pane or a mismatch between your App ID (in your provisioning profile) and your Bundle Identifier (in your Info.plist).

Resolve the former issue by ensuring you've selected the correct Code Signing Identity (under the grey provisioning profile name); resolve the latter issue by ensuring your App ID and Bundle ID match; they need to be identical to run your application on the device. This document provides background and details.

Another common cause is you're doing an Ad Hoc distribution and haven't added and configured the Entitlements.plist, as described in the "Building your Application with Xcode for Distribution" section of the iPhone Developer Program Portal User Guide in the iPhone Portal.

Other causes include not adding the device UDID to your provisioning profile or having multiple iPhone Developer (or Distribution) certificates. Read this document for more on this and other possible causes and resolutions.





Mismatch between App ID and Bundle Identifier

If your App ID (in your provisioning profile) and your Bundle Identifier (in your Info.plist) do not match, your application won't launch on the device. Check your Console log for an "entitlement 'application-identifier' has value not permitted by provisioning profile" error to confirm this mismatch (see Listing 1).

Listing 1: A Console Log error pointing to a App ID/Bundle ID mismatch.

Mon Sep 22 19:38:20 unknown securityd[391] <Error>: mobile_installat[399] SecItemCopyMatching: missing entitlement
Mon Sep 22 19:38:20 unknown mobile_installation_proxy[399] <Error>: entitlement 'application-identifier' has value not permitted by a provisioning profile
Mon Sep 22 19:38:20 unknown mobile_installation_proxy[399] <Error>: verify_executable: Could not validate signature: e8008016

[...]

Mon Sep 22 19:38:20 unknown mobile_installation_proxy[399] <Error>: install_application: Could not preflight application install
Mon Sep 22 19:38:20 unknown mobile_installation_proxy[399] <Error>: handle_install: Installation failed

To resolve this, make sure your App ID and your Bundle Identifier match. For example, if your App ID is A1B2C3D4E5.com.yourcompany.productname then your Bundle Identifier needs to be com.yourcompany.productname.

IMPORTANT: The 10-character prefix in the App ID is not included in the Bundle Identifier when entering it into Xcode.

If you created an App ID with a wildcard ("*") at the end of the ID (e.g. A1B2C3D4E5.com.yourcompany.*), you have more flexibility in your choice of Bundle Identifier, as you can use almost anything in place of the wildcard. For example, if you had two applications, you'd be able to use the same App ID (and therefore the same provisioning profile), simply by changing the Bundle Identifier in your project.

  • App ID: A1B2C3D4E5.com.yourcompany.*

  • Bundle ID for Application 1: com.yourcompany.product1

  • Bundle ID for Application 2: com.yourcompany.product2

You can even enter just a wildcard as your App ID (e.g. A1B2C3D4E5.*). This gives you ultimate flexibility as you'd be able to use any Bundle Identifier at all. This is the easiest setup because it requires no changes to your default Bundle Identifier in your project.

IMPORTANT: The App ID seed prefix (in these examples, "A1B2C3D4E5") is unique to you. Any applications you create which share the same App ID will have access to the same Keychain "slice" associated with that App ID. Consider the security implications of this if you develop applications that shouldn't share Keychain information. Generally, use different App IDs for unrelated applications.

A brief digression

The default Bundle Identifier in new projects is com.yourcompany.${PRODUCT_NAME:identifier}. "${PRODUCT_NAME:identifier}" is a variable and will be replaced by the name of your application. This is a source of confusion as you might change your project or application name over the course of development, which changes the effective Bundle Identifier.

If you keep the default Bundle Identifier, and you haven't used the wildcard in your App ID, changing your product name will cause the 0xE800003A error. If you think there's a chance you'll change your project or application name in the future, do one of two things:

  • Create and use a wildcard ("*") in your App ID (e.g. A1B2C3D4E5.com.yourcompany.*); or,

  • Replace the default Bundle Identifier with an explicit one (e.g. com.yourcompany.yourproductname)

Back to Top

Important caveats for selecting and using a Bundle Identifier

Selecting and using a Bundle Identifier (and by extension, an App ID) has these important caveats:

  • While you can change your Bundle Identifer at will prior to placing your application for sale in the App Store, once it's available for sale, you cannot change your Bundle Identifier. Choose one carefully. Fortunately, the Bundle Identifier is not publicly displayed, so it does not have any marketing requirements, nor a need to be clever. It only needs to be unique within the App Store. We recommend using reverse domain notation (com.yourcompany) as the basis of your Bundle ID, especially if you own your domain name. An alternative is reverse email address notation (e.g. com.domainname.username)

  • The Bundle Identifier (and App ID) is an example of a "Uniform Type Identifier" (UTI), so you can only use valid UTI characters for your Bundle Identifier. In particular, you can't use spaces or underscores. From "The UTI Character Set:

    "You may use the Roman alphabet in upper and lower case (A–Z, a–z), the digits 0 through 9, the dot (“.”), and the hyphen (“-”). This restriction is based on DNS name restrictions, set forth in RFC 1035.... Uniform type identifiers may also contain any of the Unicode characters greater than U+007F.... Any illegal character appearing in a UTI string—for example, underscore ("_"), colon (":"), or space (" ")—will cause the string to be rejected as an invalid UTI. At the API layer, no error is generated for invalid UTIs."

    If your project name or application name contains a space or other illegal character, either use an explicit Bundle ID (e.g. A1B2C3D4E5.com.yourcompany.yourproductname) instead of the default Bundle Identifier, or change your Product Name in your Target's Build Info pane.

    WARNING: While an invalid UTI may work when testing on your device, it will generally cause an error when uploaded to the App Store.

Back to Top

Ad Hoc Distribution not properly configured

If you're doing an Ad Hoc distribution, you must properly configure your project to include an Entitlements.plist file and uncheck the get-task-allow checkbox (which sets it to False). You can confirm this is the cause of your errors by looking in the Console for errors similar to that in Listing 2

Listing 2: A Console Log error pointing to an improperly configured Ad Hoc Distribution.

Tue Nov 11 14:20:24 unknown mobile_installation_proxy[2012] <Error>: install_embedded_profile: Skipping the installation of the embedded profile
Tue Nov 11 14:20:24 unknown securityd[2004] <Error>: mobile_installat[2012] SecItemCopyMatching: missing entitlement
Tue Nov 11 14:20:25 unknown mobile_installation_proxy[2012] <Error>: entitlement 'get-task-allow' has value not permitted by a provisioning profile
Tue Nov 11 14:20:25 unknown mobile_installation_proxy[2012] <Error>: verify_executable: Could not validate signature: e8008016

[...]

Tue Nov 11 14:20:25 unknown mobile_installation_proxy[2012] <Error>: install_application: Could not preflight application install
Tue Nov 11 14:20:25 unknown mobile_installation_proxy[2012] <Error>: handle_install: Installation failed

See the "Building your Application with Xcode for Distribution" section of the iPhone Developer Program Portal User Guide in the iPhone Portal for instructions on setting up your Entitlements.plist.

Back to Top

Other causes and resolutions

While a mismatch between the App ID and the Bundle Identifier or an improperly configured Ad Hoc distribution are the most common causes of this error, there are others:

Missing or incorrect Unique Device Identifier (UDID)

Your provisioning profile may not include the UDID of the device to which you're deploying. This may happen when you add a new device to your development pool, when you're doing an Ad Hoc distribution, or if you forget to send the provisioning profile to your Ad Hoc testers.

It may also include an incorrect UDID, either because it was mistyped, or because it's not all lowercase (which would happen when copying UDIDs from iTunes 7).

Back to Top

Revoked certificates

If you've revoked your "iPhone Developer" or "iPhone Distribution" certificates, kept the old certificates on your Keychain, and your provisioning profile or project continue to reference the old certificate, Xcode may sign your application with a certificate that's different from the one in your provisioning profile. You should delete the revoked certificates (after making a backup, of course), and update and install your provisioning profiles.

Back to Top

Document Revision History

Date Notes
2009-05-11 First Version

Posted: 2009-05-11

Trackback Address :: http://joyholic.kr/trackback/376 관련글 쓰기
Name
Password
Homepage
Secret
2009/04/07 13:14

original : http://www.gamedev.net/reference/articles/article2008.asp


A Guide To Starting With OpenAL 
by Lee Winder


Download the sample code for this article here.

So, What Exactly Is OpenAL?

OpenAL is a (smallish) API that is designed to aid cross platform development, specifically in the area of sound and music.  It is designed to be very simple at the expense of (personally speaking) functionality e.g. Panning is not supported (though some people would claim that today's 3D games would rarely, if ever, use features like that), though through clever coding, it is possible to simulate all the missing features.

Its style is influenced by OpenGL, in regards to function / variable name layout, type definitions etc. so any seasoned OpenGL coder will easily be able to find their way around, but even to novices, it is simple and easy to understand (even the docs are helpful!).

Okay, now you know a little about it, let's see how to use it!

Where Can I Get My Hands On It?

Of course, the first thing you need to do is actually get the OpenAL SDK.  You can do this by going to www.openAL.org .  It's only about 7MB, so it shouldn't take that long to do.  When you've installed it (for the sake of this article, I installed it at C:\oalsdk), have a quick look at the docs and the examples to see how simple it is to use.

Initialization

What we need to do first is to set up OpenAL so we can actually use its feature set.  This is extremely simple to do:

// Init openAL
alutInit(0, NULL);
// Clear Error Code (so we can catch any new errors)
alGetError();

That's it, now we are ready to use it!

Sources, Buffers and Listeners

Before we carry on, I'll explain the main concept behind OpenAL.  The API uses 3 main components: sources, buffers and listeners.  Here is a quick explanation of each -

Sources: A source in OpenAL is exactly what it sounds like, a source of a sound in the world.  A source is linked to one or more buffers, and then asked to play them.  They have position and orientation in the world, as well as velocity, for doppler effects.

Listener: A listener is (simply put) the ears of the world.  It is generally set at the location of the player, so that all sounds will be relative to the person playing.  This could be the actual camera location, or some other random position, whatever you want…

Buffers: Buffers are exactly like any other kind of sound buffers you may have used.  Sound is loaded into the buffer, and then the sound in the buffer is played.  The thing that differs from normal is that no functions directly call the buffer.  Instead, they are linked to a source (or multiple sources) and then the sources themselves play, playing the sound from the buffers in the order that they have been queued.

Okay, now that we know about the things that make OpenAL what it is, how do you use them?  Well, read on…

How Do We Create What We Need?

Buffers

The first things we should create are buffers, so we can actually store the sound we want to play. This is done with one simple call

ALuint buffers[NUM_BUFFERS];

// Create the buffers
alGenBuffers(NUM_BUFFERS, buffers);
if ((error = alGetError()) != AL_NO_ERROR)
{
  printf("alGenBuffers : %d", error);
  return 0;
}

All this does is create however many buffers you wish, ready to be filled with sound.  The error checking is there for completeness.

The buffers do not need to be created at the start of the program; they can be created at any time.  However, it's (in my opinion) neater if you create everything you need when you start.  Of course, this isn't always possible, so create them in exactly the same way if you need to.

Now, let's load in the sound(s) we want to use

ALenum     format;
ALsizei    size;
ALsizei    freq;
ALboolean  loop;
ALvoid*    data;

alutLoadWAVFile("exciting_sound.wav", &format, &data, &size, &freq, &loop);
if ((error = alGetError()) != AL_NO_ERROR)
{
  printf("alutLoadWAVFile exciting_sound.wav : %d", error);
  // Delete Buffers
  alDeleteBuffers(NUM_BUFFERS, buffers);
  return 0;
}

This loads in the file we have requested and fills in the given the data.  Again, the error check is there for completeness.  Note though the call to alDeleteBuffers(…).  Even though it has failed, we need to clean up after ourselves, unless of course we want memory leaks ;)…  There is also a function (alutLoadWAVMemory(…) ) that lets you load the data from memory.  Take a peek at the documentation for notes on that one.

Now that we have loaded in the sound, we need to fill up one of the buffers with the data.

alBufferData(buffers[0],format,data,size,freq);
if ((error = alGetError()) != AL_NO_ERROR)
{
  printf("alBufferData buffer 0 : %d", error);
  // Delete buffers
  alDeleteBuffers(NUM_BUFFERS, buffers);
  return 0;
}

This takes the data we received from alutLoadWAVFile(…) and puts it into the buffer, ready for it to be assigned to a waiting source and played.  Again, notice how we delete the buffers if we fail.

Now that the buffer is filled with data, we still have the sound data in memory also, taking up valuable space.  Get rid of it with:

alutUnloadWAV(format,data,size,freq);
if ((error = alGetError()) != AL_NO_ERROR)
{
  printf("alutUnloadWAV : %d", error);
  // Delete buffers
  alDeleteBuffers(NUM_BUFFERS, buffers);
  return 0;
}

This just deletes the no longer needed sound data from memory, as the data we actually need is stored in the buffer!

Sources

Okay, so we have loaded the sound into the buffer, but as I said earlier, we can't play it until we have attached it to a source.  Here's how to do that!

ALuint source[NUM_SOURCES];
// Generate the sources
alGenSources(NUM_SOURCES, source);
if ((error = alGetError()) != AL_NO_ERROR)
{
  printf("alGenSources : %d", error);
  return 0;
}

The above piece of code creates all the sources we need.  This is exactly the same procedure as alGenBuffers(…), and the same rules apply.    It is common to have far more sources than buffers, as a buffer can be attached to more than one source at the same time.  Now that the source is created we need to attach a buffer to it, so we can play it…

Attaching buffers to sources is again very easy.  There are two ways to do it:  One way is to attach a single buffer to the source, whereas the other way is to queue multiple buffers to the source, and play them in turn.  For the sake of this article, I'm just going to show you the first way.

alSourcei(source[0], AL_BUFFER, buffers[0]);
if ((error = alGetError()) != AL_NO_ERROR)
{
  printf("alSourcei : %d", error);
  return 0;
}

This takes the buffer and attaches it to the source, so that when we play the source this buffer is used.  The function alSourcei(…) is actually used in more than one place (in that it is a generic set integer property function for sources).  I won't really go into this here, maybe another day.

Now that we have set the source and buffer, we need to position the source so that we can actually simulate 3D sound.  The properties we will need to set are position, orientation and velocity.  These are pretty self explanatory, but I'll mention velocity a little.  Velocity is used to simulate a doppler effect.  Personally, I can't stand doppler effects so I set the array to 0's, but if you want the effect, the effect will be calculated in respect to the listener's position (That's coming up next!)

Okay to set these values, you use one simple function.

ALvoid alSourcefv(ALuint source,ALenum pname,ALfloat *values);

This function is similar to the alSourcei(…) function except this is a generic function to set an array of floats as a source property, where ALfloat *values will be an array of 3 ALfloats.  So, to set our position, velocity and orientaion we call :

alSourcefv (source[0], AL_POSITION, sourcePos);
alSourcefv (source[0], AL_VELOCITY, sourceVel);
alSourcefv (source[0], AL_DIRECTION, sourceOri);

These variables default them selves to 0 if you do not set them, although it is more than likely that you will.  I haven't included it here, but it is best to check for errors in the standard way, because it's a good idea to catch them as they happen.

Okay, that is a source set up, now we need one more thing - the Listener.

Listeners

As I said before, the listener is the ears of the world, and as such, you can only have one of them. It wouldn't make sense to have more than one, as OpenAL wouldn't know which one to make the sounds relevant to.  Because there is only ever one, we do not need to create it, as it comes ready made.  All we have to do is set where it is, the direction it is facing and its velocity (again for doppler effects).  This is done in exactly the same way as sources with the one function

ALvoid alListenerfv(ALenum pname,ALfloat *values);

This works in exactly the same way as alSourcefv(…) and alSourcei(…) except it works on the listener.  As I said, the listener comes ready made; you do not have to specify it.  To set the position, orientation and velocity call:

alListenerfv(AL_POSITION,listenerPos);
alListenerfv(AL_VELOCITY,listenerVel);
alListenerfv(AL_ORIENTATION,listenerOri);

Again, it will be a good idea to check for errors.  One thing to note here is that in this case, orientation is an array of 6 ALfloat's .  The first three define its look at direction, while the second three define the 'up' vector.  Once this is done, everything is finally set up (It wasn't that hard was it?).  Now we can get down to the thing we are all here for:  Playing the sound at last

The Hills Are Alive, With The Sound of Music (!)

alSourcePlay(source[0]);

Yup, that's it.  That's all that is required to play your sample.  OpenAL will calculate the volume regarding the distance and the orientation.  If you specified a velocity for either sources or listeners you'll also get doppler effects.  Now that it's playing, we might need it to stop playing…

alSourceStop(source[0]);

Or reset it to the start of the sample…

alSourceRewind(source[0]);

Or pause it…

alSourcePause(source[0]);

To unpause it, just call alSourcePlay(…) on the sample.

I've rushed through those, but they really are that simple.  If you have a look at the OpenAL Specification and Reference document, on page 32, it will tell you exactly the actions that will happen if you call these functions on a source, depending on its state.  It's simple enough, but I'm not going to go into it now.

That's all you need to do to get OpenAL up and running, but what about shutting it down?

Shutting It All Down

Shutting down is even easier than it was to set everything up.  We just need to get rid of our sources, buffers and close OpenAL.

alDeleteSources(NUM_SOURCES, source);
alDeleteBuffers(NUM_BUFFERS, buffers);

This will delete all the sources in that array of sources.  Make sure you have deleted all of them before you call the next line.

alutExit();

And that's it. OpenAL is now shut down and you can carry on with what ever you want to do next

As this is the first article I have written, I hope it is of some use to at least one person.  There's lots more to OpenAL, but this simple how-to should easily get you set up so you can look at the more complicated features (if there are any) of the API.

Lee Winder 
Leewinder@hotmail.com


Trackback Address :: http://joyholic.kr/trackback/375 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/23 18:36

http://discussions.apple.com/message.jspa?messageID=8256419#8256419

Trackback Address :: http://joyholic.kr/trackback/370 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/20 10:16
Original : http://discussions.apple.com/thread.jspa?messageID=7512737

Topic : iPhone SDK: How to create an image from raw data

Topic Archived This topic has been archived - replies are not allowed.


This question is answered. "Helpful" answers available: 2 . "Solved" answers available: 1 .



            Permlink
            Replies : 7 - Last Post : Jul 7, 2008 12:11 AM by: asnor
ceoyoyo

Posts: 21
Registered: Aug 30, 2006
iPhone SDK: How to create an image from raw data
Posted: Apr 30, 2008 12:23 PM
 

Creating a UIImage from some form of bitmap file format is easy, whether you let UIImage load the file itself or create it with an NSData. But what if you have raw bitmap data in memory and you want to create an image?

In Cocoa NSBitmapImageRep can be created by passing it a pointer to a block of memory and the relevant heigh, width, bit depth etc. information. From that you can easily create an NSImage. There doesn't seem to be anything equivalent on the iPhone. CGImage can be created but it looks like you have to write a CGImageProvider. CGBitmapContextCreate takes a void * to a block of memory. Does it clear that block?

Is there a good way to do this?

MacBook Pro / Core Duo Mini   Mac OS X (10.5.2)    
Andrew Rennard


Posts: 142
From: UK
Registered: Sep 29, 2004
Re: iPhone SDK: How to create an image from raw data
Posted: May 2, 2008 9:10 AM   in response to: ceoyoyo
 

Here's how I'm reading raw image data from a file, and creating an UIImage with it:

NSData *imageData = some_image_data
UIImage *theImage = [UIImage alloc] initWithData:imageData;

uh - unfortunately this forum software doesn't like square brackets, so you'll have to pretend there's brackets around the UIImage message....

Message was edited by: Andrew Rennard

Mac Mini   Mac OS X (10.4.8)    
Harland Macia


Posts: 153
From: Canterbury, NH
Registered: Sep 25, 2005
Re: iPhone SDK: How to create an image from raw data
Posted: May 2, 2008 9:54 AM   in response to: Andrew Rennard
 

Since I just spent 10 minutes trying to find out how to post code blocks I'd figured I share...

The brackets work for me... Enclose the code in a block starting and ending with { code }...code in curley braces without spaces.

NSDate *imageData = some_image_data;
UIImage *theImage = [[UIImage alloc] initiWithData:imageData];


MacBookPro   Mac OS X (10.5.2)   iPhone  
ceoyoyo

Posts: 21
Registered: Aug 30, 2006
Re: iPhone SDK: How to create an image from raw data
Posted: May 2, 2008 2:29 PM   in response to: Andrew Rennard
 

That works if your image data is in some kind of format UIImage recognizes, like TIFF or JPEG. Mine is just raw RGB values. I got it working using CGBitmapContextCreate(). It's basically the same way I ended up doing it with NSImageRep/NSImage on the Mac. I still think it would be handy to have as a method of NSImage AND of UIImage.

MacBook Pro / Core Duo Mini   Mac OS X (10.5.2)    
asnor

Posts: 43
Registered: Jul 1, 2008
Re: iPhone SDK: How to create an image from raw data
Posted: Jul 4, 2008 12:10 AM   in response to: ceoyoyo
 

Hi ceoyoyo , can you give me some help , now i just want to create an image from rgb565 raw data , but meet a problem , and my code is here :

//////////////////////////////////////////////////////////////////////////
NSString *imagePath = [NSBundle mainBundle] pathForResource: @"mobile" ofType: @"rgb";
NSFileHandle* file = NSFileHandle fileHandleForReadingAtPath:imagePath;
NSData* imageData = file readDataToEndOfFile;

size_t width = 240;
size_t height = 320;
size_t bitsPerComponent = 5;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
size_t components = CGColorSpaceGetNumberOfComponents( colorSpace );
size_t bytesPerRow = (width * bitsPerComponent * components + 7)/8;
const void* data = imageData bytes;
CGContextRef context = CGBitmapContextCreate((void*)data, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaNoneSkipFirst);
///////////////////////////////////////////////////////////////////////////

till the program run to CGBitmapContextCreate , it always return nil , i don't know why , pls do me a favour.

  Mac OS X (10.5.3)   iPhone  
ElNono

Posts: 15
From: USA
Registered: Jun 9, 2008
Re: iPhone SDK: How to create an image from raw data
Posted: Jul 4, 2008 6:48 PM   in response to: asnor
 

You can't do RGB565 on a CGImageRef/CGContextRef. The only 5bpp modes supported are 1555 ARGB or 5551 RGBA. If you just need to display the image, use OpenGL. One of the supported texture formats is RGB565. If you need to save the image then you're going to have to pre-convert it to RGB888.

     
asnor

Posts: 43
Registered: Jul 1, 2008
Re: iPhone SDK: How to create an image from raw data
Posted: Jul 6, 2008 6:17 PM   in response to: ElNono
 

ElNono , thanks very much for your suggestion , i will try it at once.

  Mac OS X (10.5.3)   iPhone  
asnor

Posts: 43
Registered: Jul 1, 2008
Re: iPhone SDK: How to create an image from raw data
Posted: Jul 7, 2008 12:11 AM   in response to: ElNono
 

ElNono wrote:
You can't do RGB565 on a CGImageRef/CGContextRef. The only 5bpp modes supported are 1555 ARGB or 5551 RGBA. If you just need to display the image, use OpenGL. One of the supported texture formats is RGB565. If you need to save the image then you're going to have to pre-convert it to RGB888.

hi ElNono , i have test the RGB888 data now , the image can show , but another problem is the image just like serveral picture over lap together , also is blurred , my code is here:

const size_t width = 1024;
const size_t height = 768;
const size_t bitsPerComponent = 8;
const size_t bitsPerPixel = 32;
const size_t bytesPerRow = (bitsPerPixel * width)/8;
CGBitmapInfo bitmapInfo = kCGImageAlphaPremultipliedLast;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

NSString *imagePath = [NSBundle mainBundle] pathForResource: @"Test" ofType: @"rgb";
NSFileHandle* file = NSFileHandle fileHandleForReadingAtPath:imagePath;
NSData* imageData = file readDataToEndOfFile;
CGContextRef context = CGBitmapContextCreate((void*)imageData bytes, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);
CGImageRef imageRef = CGBitmapContextCreateImage (context);
UIImage*rawImage = UIImage imageWithCGImage:imageRef;
CGColorSpaceRelease(colorSpace);
CGContextRelease(context);
CGImageRelease(imageRef);

  Mac OS X (10.5.3)   iPhone  
Trackback Address :: http://joyholic.kr/trackback/368 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/19 21:26
Original : http://craiggiles.wordpress.com/2009/01/


Parsing XML on the iPhone

Since I am developing a game engine that I would like to re-use, I have chosen to host all game data in the form of XML files. There are various reasons for doing this, partly because I can make game editors (Map Editor, Item Editor, NPC Editor, etc) and partly because I value using re-useable code. 

In order to get it all working, I had to explore the NSXMLParser given by the iPhone SDK. With XNA and the .NET framework, I got used to reading in XML in a very specific way, and the iPhone does it quite differently. Currently, my test map’s XML file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Map>
	<MapName>Test Map</MapName>
	<MapContentName>Map001</MapContentName>
	<MapDimensions>
		<MapWidth>5</MapWidth>
		<MapHeight>5</MapHeight>
	</MapDimensions>	

	<TileDimensions>
		<TileWidth>32</TileWidth>
		<TileHeight>32</TileHeight>
	</TileDimensions>	

	<SpriteSheetName></SpriteSheetName>
	<MapLayers>
		<BaseLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</BaseLayer>
		<MiddleLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</MiddleLayer>
		<TopLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</TopLayer>
		<AtmosphereLayer>0, 1, 0, 0, 0, 0, 0, 0, 0</AtmosphereLayer>
		<CollisionLayer>0, 0, 0, 0, 0, 0, 0, 0, 0</CollisionLayer>
	</MapLayers>
</Map>

In order to read in the XML, there are 3 methods that you need to implement. Since your XML parser goes line by line, you will need to write a method that starts an element, ends an element, and reads a character. Such as:

  1.   
  2. // Start of element   
  3. - (void)parser:(NSXMLParser *)parser   
  4.             didStartElement:(NSString *)elementName   
  5.             namespaceURI:(NSString *)namespaceURI   
  6.             qualifiedName:(NSString *)qName   
  7.             attributes:(NSDictionary *)attributeDict   
  8. {   
  9. }   
  10.   
  11. // Found Character   
  12. - (void)parser:(NSXMLParser *)parser foundCharacters:(NSMutableString *)string   
  13. {   
  14. }   
  15.   
  16. // End Element   
  17. - (void) parser:(NSXMLParser *)parser   
  18.             didEndElement:(NSString *)elementName   
  19.             namespaceURI:(NSString *)namespaceURI   
  20.             qualifiedName:(NSString *)qName   
  21. {   
  22. }  

Once you have these methods set up, all you really need to do is populate them. For instance, in the “Start Element” method, if your “elementName” = “MapName” (in the above XML case) you would allocate the map classes NSString like so;

  1.   
  2. mapName = [NSMutableString string];  

When you found a character, you would store those into a string, and when the end of the element is reached, you would put that string into whatever element it was reading. For example, the map name:

  1.   
  2. mapName = stringValueFromFoundCharacter;  

Not too hard, but wasn’t easy to figure out either.. At least I know it and now can implement readers for every data that I wish to store as XML!

Trackback Address :: http://joyholic.kr/trackback/367 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/19 21:19
Original : http://craiggiles.wordpress.com/2009/01/28/iphone-gaming-framework-screen-manager-update/

iPhone Gaming Framework: Screen Manager Update

I don’t have time to write up a complete tutorial, but I will soon.. but I wanted to show just how the screen manager works. First, the video so you have an idea;

Click here for iPhone Screen Management Demo
Since I am on OSX, I am working on a way to record videos and upload them to youtube like I did with windows. When I do, I’ll embed them into the page again. For now, this solution works.

As you can see, the transitions and everything works just like an XNA project would. As said before, I converted Jeff’s GLViewController to be my screen manager. To use it, what you would do is something like the following;

  1.   
  2. TitleScreen *newScreen = [[TitleScreen alloc] init];   
  3. [controller addScreen:newScreen];   
  4. [newScreen release];  

the addScreen method will retain the screen, load any content the screen will need in the game, and then add it to the screens array. Since the controller is handling the screen, and has retained the screen, we then need to release it. It is now in the controllers hands!

The controller knows if a screen is a popup screen (ala dialog box) or a full game screen (ala battle screen / inventory screen / main game screen, etc) and will transition based on what kind of screen it is. Popups get no transition, full screens will get the fade effect seen in the video. Same for transitioning off. To exit a screen, you would do the following;

  1.   
  2. if (condition == true)   
  3. {   
  4.     //in the game screens "update" method. Self refers to the game screen   
  5.     [self exitScreen];   
  6. }  

the game screen will handle any transitions if it needs to.. popup’s will just pop off the stack.

One other thing that I found really interesting, was input handling. since the iPhone uses an event like system, the moment you touch the screen the iPhone sends a message saying “HEY! I’ve been touched!” What I’ve done was create an InputManager class that takes that input, and stores it in either the previousInputState, currentInputState, or queryInputState. Obviously the previous and current input states are self explanitory, the queryInputState is the state that has happened but has not been committed quite yet (meaning, the screen manager has not updated the input state quite yet) The screen manager would then update the input state, and filter it to the top-most screen.

What I would like to do, is create a project template for this framework for any 2d developer wishing to get started in iPhone Games Development. Obviously this template will be an ongoing project, and as improvements are made the template will be updated. My problem, is google has been unhelpful for trying to create a template file. If anyone knows of a good tutorial to look at, or good reading material, please send it my way! I can be reached at my listed email address ( CraigGiles9@yahoo.com ) If I can’t find a way to convert this into a template, the best way to distribute this would be to zip it up and that would be a pain when you want to start a new project.

Later this weekend, I will try to do a full writeup of the screen management system. Until then, happy coding!

Trackback Address :: http://joyholic.kr/trackback/366 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/19 21:16
Original : http://craiggiles.wordpress.com/2009/02/18/iphone-gaming-framework-amendment/

iPhone Gaming Framework: Amendment

Its been great to see a lot of you take apart the code and really see what you can do! There have been several people who have been in contacts with me via email, trying to get everything up and running.. but as you may have known, there are a few things missing from the tutorials. This is the amendment, going to patch up the final few things to get you back on track!

First thing is in the GLView.m file. We have a screen manager, but we are not telling the game to update or draw through the screen manager. Lets fix that! Go into your -(void)drawView method, and right below the glBindFrameBufferOES() call, you should have a [controller drawView:self]; … we’re going to change that to the following:

  1. //   
  2. //  Update the view   
  3. //   
  4. [controller updateView:self WithTime:(float)[animationTimer timeInterval]];   
  5. //   
  6. //  Draw the view   
  7. //   
  8. [controller drawView:self WithTime:(float)[animationTimer timeInterval]];  

You’re going to call the controllers updateView and drawView methods, and pass in a time interval from the animationTimer. Now the controller will update and draw the game screens!

Secondly, There were a few people who never added a blankTexture to their project. I suggest opening an image editor, creating a black image called “blankTexture.png” and drag it into your resources file. You’ll notice, in the loadContent method, the screen manager allocates memory for the input manager, sets landscape mode, and then right after that loads in a blankTexture.png. If it doesn’t have one, it can’t load it.

Next amendment is more of a “clean up” since I didn’t fully understand how the retain / release system worked (Hey! i’m still a new mac developer too! :D ) In your addScreen method, you don’t need a [screen retain] since adding it to the screens NSMutableArray will retain the object. Likewise in the releaseScreen method, you’ll need to take out the [screen release] unless you like having your game crash when releasing a screen that has already been deallocated :)

With everything working, you’ll notice that your textures are being drawn “upside down” … well since we changed the way the coordinate system worked, and Apples “Texture2D” class works with the previous coordinate system, that will need to be changed. There are a few ways to do this; some people who really know their OpenGL suggested to flip the image before binding it.. the approach I took was just to adjust the vertices in the Texture2D draw methods.

This goes into your “drawAtpoint” method, comment out the current array:

  1. //   
  2. //  Modified by Craig Giles to flip the texture upside down while using my coord system   
  3. //   
  4. GLfloat     vertices[] =   
  5. {   
  6.     -width / 2 + point.x,   height / 2 + point.y,   0.0,   
  7.     width / 2 + point.x,    height / 2 + point.y,   0.0,   
  8.     -width / 2 + point.x,   -height / 2 + point.y,  0.0,   
  9.     width / 2 + point.x,    -height / 2 + point.y,  0.0   
  10.   
  11. };  

This goes into your “drawAtRect” method, comment out the current array:

  1. //   
  2. //  Modified by Craig Giles to flip the texture upside down while using my coord system   
  3. //   
  4. GLfloat vertices[] =   
  5. {   
  6.     rect.origin.x,                          rect.origin.y + rect.size.height,       0.0,   
  7.     rect.origin.x + rect.size.width,        rect.origin.y + rect.size.height,       0.0,   
  8.     rect.origin.x,                          rect.origin.y,                          0.0,   
  9.     rect.origin.x + rect.size.width,        rect.origin.y,                          0.0   
  10.   
  11. };  

I think thats all the changes. Thanks again for everyones feedback on the last few writeups! I am looking over a few documents sent to me about templates, so I can release this as a starting template. Will let everyone know more when I can! As always, feel free to email me or post a comment if you need help with something.

Trackback Address :: http://joyholic.kr/trackback/365 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/19 19:49
Original : http://craiggiles.wordpress.com/2009/02/03/iphone-gaming-framework-stage-2-tutorial/


iPhone Gaming Framework: Stage 2 Tutorial

NOTE:: I am still looking for a good way to turn this into a template and release it for anyone wishing to install this for the base of their game. If you know of a good resource for doing so, please let me know, as google has been fairly unhelpful as of this point.

Welcome back everyone! Did you all finish Stage 1 of the tutorial? If not, please do that, as we are going to be building off stage 1 in our next tutorial. Stage 1 can be found HERE

Okay, now that stage 1 is done, you have a working screen management system… except you don’t have an input manager to help you with input management! Remember my note from previous tutorials, there are MANY solutions to a problem, and this is just one of many. Our input class works as follows: If a touch is detected, the GLViewController will send a message to the input manager, and that message will be stored in an input “state” called “queryState.” Before the view controller updates any of the game screens, it will send a message to the input manager to update the input, and this is when the input is changed from the “queryState” to “currentState” and the current state is then set to the previous state.

So lets look at the code, yeah? First the InputManager.h file

  1.   
  2. //   
  3. //  The input manager is a helper class that houses any input   
  4. //  that can be obtained by the game engine. As a touch is detected   
  5. //  on screen, it will send a message to the input helper. The input   
  6. //  helper will then hold onto that message and filter it into the   
  7. //  current state on the next game loop. The current state is moved   
  8. //  to the previous state, and any incoming touches are then put   
  9. //  back into the query state, waiting to be updated.   
  10. //   
  11. //  This method of updating lets the game filter updates to the top-most   
  12. //  game screen and not have to worry about un-focused screens handling   
  13. //  input that was not intended for them.   
  14. //   
  15. //  Created by Craig Giles on 1/3/09.   
  16. //   
  17.   
  18. #import <Foundation/Foundation.h>   
  19. #import "InputState.h"   
  20.   
  21. @interface InputManager : NSObject   
  22. {   
  23. @private  
  24.     bool isLandscape;   
  25.     InputState *currentState;   
  26.     InputState *previousState;   
  27.     InputState *queryState;   
  28. }   
  29.   
  30. @property (nonatomic, readwrite) bool isLandscape;   
  31. @property (nonatomic, readonly) InputState *currentState;   
  32. @property (nonatomic, readonly) InputState *previousState;   
  33.   
  34. - (void) update:(float)deltaTime;   
  35.   
  36. //   
  37. //  Touch events   
  38. //   
  39. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer;   
  40. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer;   
  41. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer;   
  42. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view WithTimer:(NSTimer *)deltaTimer;   
  43.   
  44. //   
  45. //  Helper Methods   
  46. //   
  47. - (void) update:(float)deltaTime;   
  48. - (bool) isButtonPressed:(CGRect)rect;   
  49. - (bool) isButtonHeld:(CGRect)rect;   
  50. - (void) convertCoordinatesToLandscape;   
  51.   
  52. //   
  53. //  Class methods   
  54. //   
  55. + (bool) doesRectangle:(CGRect)rect ContainPoint:(CGPoint)point;   
  56.   
  57. @end  

And the .m file

  1.   
  2. //   
  3. //  The input manager is a helper class that houses any input   
  4. //  that can be obtained by the game engine. As a touch is detected   
  5. //  on screen, it will send a message to the input helper. The input   
  6. //  helper will then hold onto that message and filter it into the   
  7. //  current state on the next game loop. The current state is moved   
  8. //  to the previous state, and any incoming touches are then put   
  9. //  back into the query state, waiting to be updated.   
  10. //   
  11. //  This method of updating lets the game filter updates to the top-most   
  12. //  game screen and not have to worry about un-focused screens handling   
  13. //  input that was not intended for them.   
  14. //   
  15. //  Created by Craig Giles on 1/3/09.   
  16. //   
  17.   
  18. #import "InputManager.h"   
  19.   
  20. @implementation InputManager   
  21.   
  22. //   
  23. //  Getters / Setters   
  24. //   
  25. @synthesize isLandscape;   
  26. @synthesize currentState;   
  27. @synthesize previousState;   
  28.   
  29. //   
  30. //  Initialization   
  31. //   
  32. - (id) init   
  33. {   
  34.     self = [super init];   
  35.     if (self != nil)   
  36.     {   
  37.         //   
  38.         //  Allocate memory for all of the possible states   
  39.         //   
  40.         currentState = [[InputState alloc] init];   
  41.         previousState = [[InputState alloc] init];   
  42.         queryState = [[InputState alloc] init];   
  43.   
  44.         //   
  45.         //  Set the initial coords for the touch locations.   
  46.         //   
  47.         currentState.touchLocation = CGPointMake(0, 0);   
  48.         previousState.touchLocation = CGPointMake(0, 0);   
  49.         queryState.touchLocation = CGPointMake(0, 0);   
  50.     }   
  51.     return self;   
  52. }   
  53.   
  54. //   
  55. //  Deallocation   
  56. //   
  57. - (void) dealloc   
  58. {   
  59.     [currentState release];   
  60.     [previousState release];   
  61.     [queryState release];   
  62.     [super dealloc];   
  63. }   
  64.   
  65. //   
  66. //  Update the input manager. This method will take the   
  67. //  values in updateState and apply them to the current state.   
  68. //  in essence, this method will "query" the current state   
  69. //   
  70. - (void) update:(float)deltaTime   
  71. {   
  72.     //  Sets previous state to current state   
  73.     previousState.isBeingTouched = currentState.isBeingTouched;   
  74.     previousState.touchLocation = currentState.touchLocation;   
  75.   
  76.     //  Sets the current state to the query state   
  77.     currentState.isBeingTouched = queryState.isBeingTouched;   
  78.     currentState.touchLocation = queryState.touchLocation;   
  79.   
  80.     //  converts the coordinate system if the game is in landscape mode   
  81.     [self convertCoordinatesToLandscape];   
  82. }   
  83.   
  84. //   
  85. //  Touch events   
  86. //   
  87. //  These events are filtered into the input manager as they occur.   
  88. //  Since we want to control how our input, we are going to use a   
  89. //  queryState as the "Live" state, while our current and previous   
  90. //  states are updated every loop. For this reason, we are always   
  91. //  modifying the queryState when these touch events are detected,   
  92. //  and the current state is only modified on [self update:deltaTime];   
  93. //   
  94. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer   
  95. {   
  96.     queryState.isBeingTouched = YES;   
  97.     queryState.touchLocation = [[touches anyObject] locationInView:view];   
  98. }   
  99.   
  100. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer   
  101. {   
  102.     queryState.isBeingTouched = YES;   
  103.     queryState.touchLocation = [[touches anyObject] locationInView:view];   
  104. }   
  105.   
  106. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view  WithTimer:(NSTimer *)deltaTimer   
  107. {   
  108.     queryState.isBeingTouched = NO;   
  109.     queryState.touchLocation = [[touches anyObject] locationInView:view];   
  110. }   
  111.   
  112. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)view WithTimer:(NSTimer *)deltaTimer   
  113. {   
  114.     queryState.isBeingTouched = NO;   
  115. }   
  116.   
  117. //   
  118. //  When in landscape mode, the touch screen still records input   
  119. //  as if it were in portrait mode. To get around this, if we   
  120. //  are writing a game in landscape we need to adjust the coordinate   
  121. //  system on the touchscreen to match that of our world.   
  122. //   
  123. - (void) convertCoordinatesToLandscape   
  124. {   
  125.     //  If we are not in landscape mode, don't convert anything   
  126.     if ( !isLandscape )   
  127.         return;   
  128.   
  129.     //  Otherwise, we will need to take the current touch location   
  130.     //  swap the x and y values (since in landscape, the portrait   
  131.     //  coordinate system means x will point up / down instead of   
  132.     //  left / right) and move the y position to match our origin   
  133.     //  point of (0,0) in the upper left corner.   
  134.     int x = currentState.touchLocation.y;   
  135.     int y = (currentState.touchLocation.x - 320);   
  136.   
  137.     //  make sure we take the absolute value of y, since if we didn't   
  138.     //  y would always be a negative number.   
  139.     y = abs(y);   
  140.   
  141.     //  Since we were converting the current state, we need to update   
  142.     //  the current touch location   
  143.     currentState.touchLocation = CGPointMake( x, y );   
  144. }   
  145.   
  146. //   
  147. //  Looks at the previous state, and the current state to determine   
  148. //  weather or not the button (rectangle) was just pressed and released.   
  149. //   
  150. - (bool) isButtonPressed:(CGRect)rect   
  151. {   
  152.     //   
  153.     //  If the current state is not being touched   
  154.     //  and the previous state is being touched, the   
  155.     //  user just released their touch. This is   
  156.     //  personal preference really, But i've found with   
  157.     //  my XNA programming, that its better to detect if   
  158.     //  a button was just released rather than if it was   
  159.     //  just pressed in when determining a button press.   
  160.     //   
  161.     if ( !currentState.isBeingTouched &&   
  162.          previousState.isBeingTouched )   
  163.     {   
  164.   
  165.         return  [InputManager doesRectangle:rect ContainPoint:currentState.touchLocation];   
  166.     }   
  167.   
  168.     return NO;   
  169. }   
  170.   
  171. //   
  172. //  Looks at the previous state, and the current state to determine   
  173. //  weather or not the button (rectangle) is being held down.   
  174. //   
  175. - (bool) isButtonHeld:(CGRect)rect   
  176. {   
  177.     //   
  178.     //  If the current state and the previous states   
  179.     //  are being touched, the user is holding their   
  180.     //  touch on the screen.   
  181.     //   
  182.     if ( currentState.isBeingTouched &&   
  183.          previousState.isBeingTouched )   
  184.     {   
  185.         return  [InputManager doesRectangle:rect ContainPoint:currentState.touchLocation];   
  186.     }   
  187.   
  188.     return NO;   
  189. }   
  190.   
  191. //   
  192. //  Helper method for determining if a rectangle contains a point.   
  193. //  Unsure if this will stay in the input helper or be moved to some   
  194. //  sort of "RectangleHelper" class in the future, but for now this   
  195. //  is a good spot for it. Remember, this works with our current coord   
  196. //  system. If your engine uses a different coord system (IE: (0,0) is at   
  197. //  the bottom left of the screen) you'll need to modify this method.   
  198. //   
  199. + (bool) doesRectangle:(CGRect)rect ContainPoint:(CGPoint)point   
  200. {   
  201.     //   
  202.     //  If the rectangle contains the given point, return YES   
  203.     //  Otherwise, the point is outside the rectangle, return NO   
  204.     //   
  205.     if (point.x > rect.origin.x &&   
  206.         point.x < rect.origin.x + rect.size.width &&   
  207.         point.y > rect.origin.y &&   
  208.         point.y < rect.origin.y + rect.size.height)   
  209.     {   
  210.         return YES;   
  211.     }   
  212.   
  213.     return NO;   
  214. }   
  215.   
  216. @end  

InputState just contains 2 values, and I have chosen to set them as the following:

  1.   
  2. #import <Foundation/Foundation.h>   
  3.   
  4. @interface InputState : NSObject   
  5. {   
  6.     bool isBeingTouched;   
  7.     CGPoint touchLocation;   
  8. }   
  9.   
  10. @property (nonatomic, readwrite) bool isBeingTouched;   
  11. @property (nonatomic, readwrite) CGPoint touchLocation;   
  12.   
  13. @end   
  14.   
  15. //   
  16. //  Implementation of InputState   
  17. //   
  18. @implementation InputState   
  19.   
  20. @synthesize isBeingTouched;   
  21. @synthesize touchLocation;   
  22.   
  23. - (id) init   
  24. {   
  25.     self = [super init];   
  26.     if (self != nil) {   
  27.         isBeingTouched = NO;   
  28.         touchLocation = CGPointMake(0, 0);   
  29.     }   
  30.     return self;   
  31. }   
  32.   
  33. @end  

It should be a good time to point out, that the input manager changes the coordinates of the actual touch, depending on if you’re playing your game in landscape mode or normal mode. One of the problems I was having, before I realized what was really happening, was my coordinates for the touch screen and coordinates for the game world were different. For example, my touch screen coordinates, if held landscape, (0,0) was in the lower left corner, while in the world coordinates, (0,0) was in the upper left corner. This gave me problems, as you can imagine.

In order to change this, I wrote a method that will convert the coordinates system if the screen is detected in landscape mode. It should be pointed out, that if you’re using a different origin point for your world (IE: Lower left corner instead of upper left) you’re conversions will have to be done differently.

Another method that is currently in the input manager class, is the [self doesRectangle:rect ContainPoint:touchLocation]; Inside this method, you’ll see that both current and previous states are being used in order to detect if a touch is being “touched” or “held.” This can be done differently, but the way I’ve chosen to implement it, is as follows;

if the button was just RELEASED (current state is not pressed, but previous state was) than the button was just “pressed.”

This is important to note, because it means if the user touches the screen, and holds their finger down, it won’t register as a “button press” until they release their finger. Some people prefer to do the opposite, meaning if the current state was just pressed and the previous state was un-pressed. Use what you feel comfortable with.

So now all we need to do is add a game screen or two, right? Well, I told you that I would help you get up a paused screen. This will help you learn how to get any sort of game screen up and running. First, lets take a look at the PausedScreen.h file

  1.   
  2. //   
  3. //  The paused screen is just an overlay popup screen that is   
  4. //  displayed to the user when the game is paused.   
  5. //   
  6. //  Created by Craig Giles on 1/5/09.   
  7. //   
  8.   
  9. #import <Foundation/Foundation.h>   
  10.   
  11. #import "GameScreen.h"   
  12. #import "InputManager.h"   
  13. #import "Texture2D.h"   
  14.   
  15. @interface PausedScreen : GameScreen   
  16. {   
  17.     Texture2D *pausedText;   
  18.     double alphaValue;   
  19. }   
  20.   
  21. @property (nonatomic, retain) Texture2D *pausedText;   
  22.   
  23. - (void) loadContent;   
  24. - (void) unloadContent;   
  25.   
  26. - (void) handleInput:(InputManager *)input;   
  27. - (void) update:(float)deltaTime    OtherScreenHasFocus:(bool)otherFocus    CoveredByOtherScreen:(bool)coveredByOtherScreen;   
  28. - (void) draw:(float)deltaTime;   
  29.   
  30. @end  

If you notice, several of these methods are in “GameScreen.h” right? You’ll also notice the LACK of touch event classes. All input is handled by the input manager, and will be called from the view controller (the [self handleInput:input] method) Aah now you are getting why I went the touch manager route instead of re-writing every single “touchEvent” method in each game screen!

There are several methods that every game screen needs in order to function properly. It will need a loadContent / unloadContent methods, handleInput method, and the update / draw methods. Also keep in mind, every game screen will need to call the [super update:deltaTime...], and every screen (other than the paused screen, which is a popup screen) will need to call the [super draw:deltaTime]; within its draw method.

So now you have the basics of the game screen, let me show you the .m file.

  1.   
  2. //   
  3. //  The paused screen is just an overlay popup screen that is   
  4. //  displayed to the user when the game is paused.   
  5. //   
  6. //  Created by Craig Giles on 1/5/09.   
  7. //   
  8.   
  9. #import "PausedScreen.h"   
  10.   
  11. @implementation PausedScreen   
  12.   
  13. @synthesize pausedText;   
  14.   
  15. //   
  16. //  Initialize the pause menu screen   
  17. //   
  18. - (id) init   
  19. {   
  20.     self = [super init];   
  21.     if (self != nil)   
  22.     {   
  23.         //  flag that there is no need for the game to transition   
  24.         //  off when the pause menu is on top of it   
  25.         self.isPopup = YES;   
  26.   
  27.     }   
  28.     return self;   
  29. }   
  30.   
  31. //   
  32. //  Load all content associated with the paused screen   
  33. //   
  34. - (void) loadContent   
  35. {   
  36.     //   
  37.     //  Since this is a popup screen, we will over-ride the   
  38.     //  view controllers transition time and set this to instantly   
  39.     //  transition on and off.   
  40.     //   
  41.     self.transitionOnTime = 0;   
  42.     self.transitionOffTime = 0;   
  43.   
  44.     //  set the paused text   
  45.     pausedText = [[Texture2D alloc] initWithString:@"Paused\nTap screen to unpause"  
  46.                                         dimensions:CGSizeMake(self.viewport.size.width, self.viewport.size.height)   
  47.                                          alignment:UITextAlignmentCenter   
  48.                                           fontName:@"Zapfino"  
  49.                                           fontSize:32];   
  50.   
  51.     //  The alpha value of the background. below   
  52.     //  the paused text.   
  53.     alphaValue = 0.75f;   
  54. }   
  55.   
  56. - (void) unloadContent   
  57. {   
  58.     //TODO: all unload content goes here   
  59.     [pausedText release];   
  60.     [super unloadContent];   
  61. }   
  62.   
  63. - (void) handleInput:(InputManager *)input   
  64. {   
  65.     //  If the 'tap here to resume' button was pressed   
  66.     //  resume game   
  67.     if ([input isButtonPressed:self.viewport])   
  68.     {   
  69.         [self exitScreen];   
  70.     }   
  71. }   
  72.   
  73. - (void) update:(float)deltaTime    OtherScreenHasFocus:(bool)otherFocus    CoveredByOtherScreen:(bool)coveredByOtherScreen   
  74. {   
  75.     //TODO: Update logic goes here   
  76.   
  77.     //  Update the base class   
  78.     [super update:deltaTime OtherScreenHasFocus:otherFocus CoveredByOtherScreen:coveredByOtherScreen];   
  79. }   
  80.   
  81. - (void) draw:(float)deltaTime   
  82. {   
  83.     //  Darken the screen to alert the player that it has been paused   
  84.     [self.controller fadeBackBufferToBlack:alphaValue];   
  85.   
  86.     [pausedText drawInRect:CGRectMake(self.viewport.size.width / 4,   
  87.                                       self.viewport.size.height / 4,   
  88.                                       self.viewport.size.width / 2,   
  89.                                       self.viewport.size.height / 2)];   
  90. }   
  91. @end  

One thing to take note, since the PausedScreen is a popup screen, it has overwritten the transition on and transition off values sent to it by the view controller. Any game screen can do the same, for example if you are transitioning to a screen that you’ve made your own custom transition, turn the view controllers transition off and let the screen transition itself. (IE: a battle screen.)

So there you have it! I don’t remember if textures are drawing upside down with this coord system, but if they are, all you have to do is edit the Texture2D.m file to fix that. If you don’t know how, send me an email and I’ll show you how I did it, but there are several ways of doing it.

I hope you enjoyed my heavily commented code for the screen manager, input manager, and game screen classes. This should give you the basic knowledge to get up and running with your own iPhone OpenGL applications. If you found these useful, let me know and I’ll write up some more when I have the time. I’m still learning all of this myself, but sharing my knowledge will lead to more interesting games for everyone! Keep in mind these are very basic systems and can be heavily expanded on by creative programmers. Can’t wait to see what you guys come up with!

Happy coding all!

28 Comments so far

  1. Andrew Wilson on

    Hi Craig

    Thanks a bunch for those two tutorials, this is really going to help when I get my teeth into the iPhone. Currently i’m finishing up an xna project and simultaniously reading through a book on iPhone development(oddly enough it’s the one you reccomended a few posts back)(boy is it different to c#) but after I get both of then done then I’m going to start with the iphone stuff straight away, and this will come in very useful. While I’m here, do you know of any good tutorials for OpenGLes, especially 2D stuff? I’m mainly looking for basic moving/animating sprites including rotating scaling etc, or is this covered in the book.

    Anyway, thanks again for the tutorials.

  2. Craig on

    Good book eh? It teaches you the basics, but isn’t really meant for games or anything. If you look at the sections talking about CoreAnimation, Quartz, or OpenGL, you’ll notice they’re kinda quick.

    Learning OpenGL es was tough for me… the initial learning curve is pretty high. I would suggest starting with the nehe tutorials at gamedev.net, and search Jeff’s blog for his “converting Nehe tutorials to the iPhone” since OpenGL != OpenGL ES in a few ways.

    The commands you’ll want to get familiar with is glOrthof (if you look in the screen manager setup, its there.. that sets up your screen for you) which will use a 2d projection. glRotatef(value, x, y, z) will rotate an object by value on the x, y, or z plane. I have not played around with scale yet, but there is a command for that too.

    If you have any specific questions when you get into the iPhone, let me know and i’ll see if i can dig up some info. Trying to learn OpenGL was very hard, but once it “clicked” enogh to where I could write a small game (which I am in the process now) … its glorious :)

  3. Andrew Wilson on

    thanks for the info, i’m sure it’ll come in useful.

  4. Sam Green on

    Thanks for the writeups!

    Found the following sites for Template info:

    http://www.macresearch.org/custom_xcode_templates
    http://briksoftware.com/blog/?p=28
    http://guides.macrumors.com/Creating_Xcode_project_templates

    Hopefully one of those will help you. :]

  5. Craig on

    Thanks Sam, I’ll look into those and see if any helps! If i can get it up and running (probably sometime after this weekend) i’ll release the base screen manager / input manager / etc as a template for anyone wishing to start with it. Could also make your own tweaks to it (obviously since the input manager is very basic at this point, compared to what you could do with it)

  6. Josh on

    Hey

    I sent you an email and I don’t know if you got it. I’m really looking forward to this being worked on further. I agree that it probably won’t be the best, at least in the beginning, but I’ve been having a lot of problems finding help for game-specific iPhone programming. I tried using cocos2d, sio2, and also oolong. These three have been heavily recommended, but I couldn’t get my head around them. I’m really looking forward to seeing what you do with this project.

    I have to mention as well, you said that you’re really heavy on commenting code. That’s great, the libraries I mentioned above don’t contain enough of it. I would deeply suggest you continue this even if you do decide not to. It really helps.

    Thanks Craig

  7. Craig on

    My work and class schedule has gotten me a little bit behind on emails.. I have read them all but have not yet been able to reply. I, like you, also checked out Cocos2D, SIO2, and Oolong… and they are powerful for what they do, but hell if I knew how to use them :) although Cocos would be the easiest to learn, since it has a very active community.

    I hope the screen / input / gamescreen classes in my first two tutorials were helpful for you. Were you able to get anything up and running? I was sent a few links to some template information, so I’ll try to put the workings of a “Base Game Framework” in a template for anyone wanting to use or expand on whats been talked about here.

    Commenting code has been a great thing for me.. Obviously the comments on the screen manager were excessive, but when I code its not far from what you’ll find in my private code as well. If I don’t get a chance to work on a project for a few weeks, I want to know everything that the code does (including my thought process as to why it does it) I remember my first RPG project for Dream Build Play… I went back to look at that engine and was surprised that… I didn’t know what anything did! Never again! From now on, all of my code will be fully commented :) and I always recommend the same for everyone.. it will help you out in the long run, guaranteed!

  8. Josh on

    Thanks for the quick reply.

    I totally understand you being busy. I’m actually off this week from work and I really want to get the backbone of my game built.

    I wasn’t able to do too much with it because I guess you never had us write a TitleScreen.m/h file structure, which caused some errors. Although it seems like those are the only issues.

    I do have a question, I don’t know a lot of OpenGL. Will I need to know a certain amount of it to do what you’re trying to do here?

    Thanks again

  9. Craig on

    Any game screen should be pretty easy.. just need to make sure each gamescreen implements some features (IE: All game screens need to inherit from the GameScreen.m class, and should also call the super’s update and draw methods.)

    Here are the methods in my TitleScreen.h , they are generally the ones you’ll use for most of your game screens.

    - (void) loadContent;
    - (void) unloadContent;

    - (void) handleInput:(InputManager *)input;
    - (void) update:(float)deltaTime OtherScreenHasFocus:(bool)otherFocus CoveredByOtherScreen:(bool)coveredByOtherScreen;
    - (void) draw:(float)deltaTime;

    If you need help populating those methods, let me know… although it shouldn’t be too difficult. As for OpenGL? You don’t need to know a “lot” of it, but you should udnerstand what its doing. If you’re doing 2d games, you’ll just want to make a texture2d instance, (IE Texture2D *sprite;) and you’ll do mostly [sprite drawInRect:spriteBoxGoesHere];

    But as always, if you run into trouble.. just post here. I found a few bugs in the screen manager that I’ll address if i can get a template up and running… nothing major, things like not needing to [screen retain] and [screen release] in the add and release methods (apparently adding an instance to an NSMutableArray retains it autmatocially… which shows just how much of a mac programmer i am :D )

  10. Josh on

    Thanks for the quick replies.

    That’s good to hear, because most people are telling me to use OpenGL. As per their instructions, I also have the sample code for Touch Fighter and CrashLanding, but they haven’t helped as much. Although CrashLanding should help me a little bit.

    I could possibly need help with that. I’m relatively new to programming; don’t let that mistake me for a complete beginner. I know the background of C in general and I have enough friends to guide me through harder problems.

    I seriously think that as soon as you get that template ready, I’ll be very excited (no pressure :]). I have to hand it to you, you seem very experienced with this type of thing so I’m happy that I’ll have the chance to see what you make of this.

    That’s the one issue though, basically I’m a slow learner, if you show me code that hasn’t really been commented on, or it’s just very plain, I’m not able to learn anything from it.

    But thanks a lot.

  11. mc on

    This is good stuff Craig. I’m working my way through this tutorial and am learning alot. However, I was wondering how to import 3ds max files into an iphone app. When googling it, it didn’t seem like there is a ‘best’ solution.

  12. Craig on

    I don’t know the best solution either, its not a problem I’ve had to solve yet :( I would look into Jeff’s blog at http://iphonedevelopment.blogspot.com/ as I know he was working on an object importer.. although I do not know the status of his project.

  13. Paul on

    This demo is very helpful, but I am having a little trouble getting it up and running, and although I have been programming for decades now, programming for the Mac and the iPhone is new to me (like everyone else it seems).

    For starters, for whatever the reason I get warnings about the locations of the frameworks when I run. It all compiles, but I get output in the console that it is looking for UIKit, OpenGLES, and CoreGraphics in /System/Frameworks rather than in /Developer/Platforms tree. I am not sure this is causing a problem or not.

    Also, whenever I run I crash with a runtime error “*** -[GLViewController drawView:]: unrecognized selector sent to instance 0×525df0″, which seems to happen right after it exits the application delegate class applicationDidFinishLaunching function.

    Any ideas?

  14. Craig on

    Are you able to compile and run the basic framework given by Jeff from iphonedevelopment?
    If you look at your frameworks folder in xcode, does it include the CoreGraphics.framework / OpenGLES / UIKit / QuartzCore / Foundation.frameworks ?

    I’ve never received that runtime error before.. although it sounds like a framework isn’t hooked up right. I’d make sure you can compile Jeff’s framework first, and if you can, then build on top of that.

    If you’re using the OpenGL application framework provided by apple, you can still do this… but you’ll be doing somewhat different steps to get it working. I just used Jeff’s template because it was easier for me.

  15. Paul on

    I can compile and run the template. It does not do anything other than give me a blank screen but there are no errors in the console.

    When I run it with your modifications, I get the above error on the line:

    [controller drawView:self];

    in GLView drawView function.

  16. Craig on

    I just posted an amendment to the tutorial series on the front page, should help with your problem. There is no drawView method with those parameters in our controller, we needed to adjust that to call the correct draw and update methods for our controller. There are a few other things in the amendment as well, should take a look at it :)

  17. Jonathan on

    Hi,

    Thanks for this very interesting tutorial, i have managed to get everything sorted however i have one problem. When i compile i get the following error, have you got any idea what is going wrong with this, i am guessing their is some sort of duplicate reference but i just dont understand whats wrong.

    Thanks for any help

    cd “/Users/badwolf/In Development/iGame”
    setenv MACOSX_DEPLOYMENT_TARGET 10.5
    setenv PATH “/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin”
    /Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.0 -arch i386 -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.0.sdk “-L/Users/badwolf/In Development/iGame/build/Debug-iphonesimulator” “-F/Users/badwolf/In Development/iGame/build/Debug-iphonesimulator” -filelist “/Users/badwolf/In Development/iGame/build/iGame.build/Debug-iphonesimulator/iGame.build/Objects-normal/i386/iGame.LinkFileList” -mmacosx-version-min=10.5 -framework Foundation -framework UIKit -framework CoreGraphics -framework OpenGLES -framework QuartzCore -o “/Users/badwolf/In Development/iGame/build/Debug-iphonesimulator/iGame.app/iGame”
    ld: duplicate symbol .objc_class_name_InputState in /Users/badwolf/In Development/iGame/build/iGame.build/Debug-iphonesimulator/iGame.build/Objects-normal/i386/GLViewController.o and /Users/badwolf/In Development/iGame/build/iGame.build/Debug-iphonesimulator/iGame.build/Objects-normal/i386/iGameAppDelegate.o
    collect2: ld returned 1 exit status

  18. Craig on

    I’m not quite sure, if its a code error i could spot it but I’m really bad at errors like this. It doesn’t even compile correct? I would try it one step at a time.. first get the framework from Jeff’s blog, then compile… then add a few modifications and Compile… see what is breaking for you.

  19. Eskema on

    Awesome tutorials, but for now, i cant understand how to manage different windows, i dont see any function to swap beetwen windows, how can i change from menu windows to options windows,etc,etc?
    You call exitscreen to kill actual screen, but how to change to another?
    thanks :)

  20. Craig on

    Think of this system as a stack like system. You can see and interact with the top most object on the stack, but in order to dig deeper and interact with the 2nd object, you need to pop the top object off the stack.

    That being said, this system wasn’t built as a stack for the reason you mentioned… its possible to modify it to make a screen a ‘focal point’ of input so you can interact with any screen that is set as the focal point. How you would do that is up to you, i can think of a few ways off the top of my head that would take advantage of the multi-touch interface of hte iPhone (such as 2 to 3 finger swipes that could swap between screens)

    I would suggest draw out what you want to do on paper, and find a way to do it in code. If you want to interact with one screen at once, how do you make that screen the focus of your program? What if you want to change the focus from one screen to another? Its doable, and could be quite interesting in the right developers hands.

  21. Eskema on

    I asked you because i dont understand your stack system, i never used anything like that. I always use a simple statemanager in my main file.
    So, while statemanager->isrunning == true{
    switch states->getstate(){
    case state->menu: loadmenu(), etc, etc.
    But as i said i dont understand this method how it works, because i dont see any method, or value to select wich screen i wanna draw.
    I keep looking your source trying to understand how it works :)

  22. Craig on

    That is one way to do it, and I did that for one of my early projects.. but I found it to be too cumbersome :(

    Think of the screen manager like this; You are in the MainGame of your program, and you open up an InventoryScreen. There are now 2 screens on the stack;

    InventoryScreen
    MainGame

    Lets say in that inventory screen, you select an item that you want to equip… a message pops up saying “Do you wish to equip this item? Y/N” That msg is its own screen called MessageBoxScreen. You now have 3 windows;

    (notice new windows get added to the top)
    MessageBoxScreen
    InventoryScreen
    MainGameScreen

    The way the screen manager handles this, is the following. In your view controllers update function, it will go through the stack from the top to the bottom and update all the screens logic (animations, timers, etc) and give the TOP MOST SCREEN the opportunity to handle input (so message box will work with any input, but inventory screen and MainGame will NOT… but those two will still update their logic)

    With me so far? This makes it so if you’re game uses something like a “tap to move” function, and you tap the screen saying “Yes, get rid of this message box” your character won’t move to that location too :) But when you have all of your inventory screens open and all that, your game still updates itself like animations and timers and what not… because what if your screen doesn’t take up the entire menu? Do you really want your game to pause itself?

    Okay so thats the update function.. but what about the draw function? This one is quite easy if you look at the code… because it will just go through the entire stack bottom to top (not top to bottom) drawing each screen. The reason it goes bottom to top is like an artist, drawing the base first, then anything on top of it later. If you drew the message box first, then you drew the main game after it, the message box would be hidden behind the main game.

    Thats the basics… make sense? So the short answer to your question; all game screens will get drawn, and all game screens will get updated.. but if they’re the top-most screen they’re given the chance to update input.

  23. Eskema on

    Thanks a lot, another question if dont mind…. I have the mainscreen, now if i tap the screen i load another screen, but i dont delete the actual screen, so new screen should be added to screenmanager. Now if i tap the new screen with [self exitscreen], i should go back to my mainscreen, but the app delete the actual screen and crash, instead of return to my mainscreen, it seems like the mainscreen doesnt exist anymore. maybe im doing something wrong, any point?

  24. Cooslick on

    I was getting the same error as Jonathan and manged to overcome this by spliting the InputState.h file into a .h and .m file.

    Great tutorial Craig, i’ve been looking for something like this for a few weeks now. I’ve managed to get the framework up and running and have a basic screen. Hope to now begin developing on this further.

    Thanks!

  25. Craig on

    @Cooslick
    Awesome to hear man. Good luck on your projects! Keep me informed with what you come up with :)

    @Eskema
    I would have to see the code Eskema. My suggestion is to set a brakepoint and trace the code, see what its doing. Maybe its getting released unexpectedly? I would have to know more information.

  26. Eskema on

    Actually i get 3 warnings in gamescreen.m
    -removescreen (twice) and fadetoblack.. are giving me a warning, telling that those methods doesnt exit.
    So when i use [self exitscreen] i get the “EXC_BAD_INSTRUCTION” error. I think the screen isnt released properly.
    Maybe you can show us how to move beetween 2 screens, so that way we can figure out what are we doing bad.
    Thanks :)

  27. Craig on

    To add a screen, you do what was done in the screen manager; create the screen, and then call the [controller addScreen:screen];

    if you’re calling [self exitScreen]; you should be inside the screen, since you’re telling the screen “hey, i want to die now” .. is this correct?

    again i can’t determine what is going on with just a few code samples. I would suggest running a break point at various points and really figure out what is going on. It will help you long term too, since you’ll understand the controller much better and be able to debug things that crop up.

  28. Eskema on

    Ok here we go, in glviewcontroller i have my titlescren call. So the app starts and show that screen :) , now i created my titlescreen.m and in there, in handleinput function i put the same call to create another window
    InGame *InGameScreen = [[InGame alloc] init];
    [controller addScreen:InGameScreen];
    [InGameScreen release];

    Now i created a new window and when i tap the titlescreen, my ingame screen shows, so i assume that i have 2 screens right now:
    ingame screen
    title screen
    right?
    Now ingame screen adds the pausedscreen, again the same call in handleinput
    PausedScreen *InPauseScreen = [[PausedScreen alloc] init];
    [controller addScreen:InPausedScreen];
    [InPausedScreen release];

    Actually im in the ingame screen, so i tap the screen and the pausescreen popsup, again if code its correct i have 3 screens

    pausescreen
    ingamescreen
    titlescreen

    Now if i tap the pausescreen, it will dissapear and return to ingame screen, but the app closes and get an exception in [self exitscreen].

    Here i am stuck with this, the breakpoints tells that the problem its in exitscreen, but you show us the code works, so im unable to find out any point.

Trackback Address :: http://joyholic.kr/trackback/364 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/19 19:46

iPhone Gaming Framework: Stage 1 Tutorial

Buckle in guys, this is going to be a rather large tutorial. The goal for this tutorial is to get a basic screen management system up and running, ready to start writing game code. I would like to start off by saying the following: This is not the only way to get a project up and running! There are many many many ways of solving problems in the programming world. Some people might prefer to use Cocos2D for the iPhone, while others might prefer to roll their own engine from scratch. I did this more as a learning process for myself, and now that I’ve learned what I could, i thought I should share the knowledge to everyone else who is struggling with the problems that I’ve solved.

Also, keep in mind that this screen management system is basically a port of the GameStateManagement demo from the XNA sample ( http://creators.xna.com/ ) from C# to Objective-C with some modifications. Anyone currently using XNA should have a fairly easy time porting this over, as a lot of the code should be recognizable to you.

So, now that I’ve got that out of the way, lets begin! Your first step is going to head over to Jeff’s blog iPhoneDevelopment and pick up the Updated OpenGL Xcode Project Template.

Next step, is to follow his directions and install it! Once you have it installed, load a new project using his template. You will find that a few things are different, and a whole lot is added. Open up the GLView.m in the classes subdirectory, and add the following four methods:

  1.   
  2. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event   
  3. {   
  4.     [controller touchesBegan:touches withEvent:event InView:self  WithTimer:animationTimer];   
  5. }   
  6.   
  7. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event   
  8. {   
  9.     [controller touchesMoved:touches withEvent:event InView:self  WithTimer:animationTimer];   
  10. }   
  11.   
  12. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event   
  13. {   
  14.     [controller touchesEnded:touches withEvent:event InView:self  WithTimer:animationTimer];   
  15. }   
  16.   
  17. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event   
  18. {   
  19.     [controller touchesCancelled:touches withEvent:event InView:self  WithTimer:animationTimer];   
  20. }  

What this is going to do, is when your iPod touch or iPhone is touched, a message is sent to the GLView. We are going to capture that message, and send it to the GLViewController. Okay, got that done? GREAT! Now comes the fun stuff.

Open up your GLViewController.h file. You are going to be putting in quite a bit of code, and i’ll explain everything when we do the .m file, so for right now just adjust your .h file to look like the following. You’ll see the .m file is HEAVILY commented to show what everything is and what it does, and i’ll make some additional notes here as well… so here is the GLViewController.h file.

  1.   
  2. //   
  3. //  The View Controller is a service which mananges one or more GameScreen   
  4. //  instances. It maintains a stack of screens, calls their Update and Draw   
  5. //  methods at the appropriate times, and automatically routes the input to   
  6. //  the topmost active screen.   
  7. //   
  8. //  Created by XNA Development Team ( http://creators.xna.com/ ) as a   
  9. //  ScreenManager.cs GameComponent.   
  10. //   
  11. //  Adapted for iPhone Game Development by Craig Giles on 1/1/09.   
  12. //   
  13.   
  14. //   
  15. //  Import statements   
  16. //   
  17. #import <UIKit/UIKit.h>   
  18. #import <OpenGLES/EAGL.h>   
  19. #import <OpenGLES/ES1/gl.h>   
  20. #import <OpenGLES/ES1/glext.h>   
  21.   
  22. #import "Texture2D.h"   
  23. #import "InputManager.h"   
  24. #import "GameScreen.h"   
  25. #import "TitleScreen.h"   
  26.   
  27. @class GLView;   
  28. @interface GLViewController : UIViewController   
  29. {   
  30.     NSMutableArray *screens;   
  31.     NSMutableArray *screensToUpdate;   
  32.     InputManager *input;   
  33.     Texture2D *blankTexture;   
  34.   
  35.     bool isInitialized;   
  36.     bool traceEnabled;     
  37.   
  38.     UIView *gameView;   
  39.     CGRect viewport;   
  40. }   
  41.   
  42. //   
  43. //  Properties   
  44. //   
  45. @property (nonatomic, retain) NSMutableArray *screens;   
  46. @property (nonatomic, retain) NSMutableArray *screensToUpdate;   
  47. @property (nonatomic, retain) InputManager *input;   
  48. @property (nonatomic, retain) Texture2D *blankTexture;   
  49.   
  50. @property (nonatomic, readwrite) bool isInitialized;   
  51. @property (nonatomic, readwrite) bool traceEnabled;   
  52.   
  53. @property (nonatomic, retain) UIView *gameView;   
  54. @property (nonatomic, readwrite) CGRect viewport;   
  55.   
  56. //   
  57. //  Methods   
  58. //   
  59. - (void) setupView:(GLView*)view;   
  60. - (void) loadContent;   
  61. - (void) addScreen:(GameScreen *)screen;   
  62. - (void) removeScreen:(GameScreen *)screen;   
  63. - (void) releaseScreen:(GameScreen *)screen;   
  64. - (void) updateView:(GLView *)view WithTime:(float)deltaTime;   
  65. - (void) drawView:(GLView *)view WithTime:(float)deltaTime;   
  66. - (void) traceScreens;   
  67. - (void) fadeBackBufferToBlack:(double)alpha;   
  68.   
  69. //   
  70. //  Touches events   
  71. //   
  72. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;   
  73. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;   
  74. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;   
  75. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer;   
  76.   
  77. @end  

Its a good idea to look through the .h file to see what you can do with the screen manager. Obviously you can do the touch events (remember we connected those from the GLView?) but also, looking at the methods you will be able to add and remove screens from the screen manager, update and draw, fade back buffer to black, and a few other things. Lets see how it all works!

  1.   
  2. //   
  3. //  The View Controller is a service which mananges one or more GameScreen   
  4. //  instances. It maintains a stack of screens, calls their Update and Draw   
  5. //  methods at the appropriate times, and automatically routes the input to   
  6. //  the topmost active screen.   
  7. //   
  8. //  Created by XNA Development Team ( http://creators.xna.com/ ) as a   
  9. //  ScreenManager.cs GameComponent.   
  10. //   
  11. //  Adapted for iPhone Game Development by Craig Giles on 1/1/09.   
  12. //   
  13.   
  14. //   
  15. //  Import commands from Jeff's template   
  16. //   
  17. #import "GLViewController.h"   
  18. #import "GLView.h"   
  19. #import "OpenGLCommon.h"   
  20. #import "ConstantsAndMacros.h"   
  21.   
  22. //   
  23. //  This indicates weather or not the game will be played in   
  24. //  landscape or portrait mode. While in landscape mode, the   
  25. //  screen will be rotated, but also the input will be off.   
  26. //  Touch coordinates for the screen will have to be converted   
  27. //  before it reaches the input manager class.   
  28. //   
  29. const bool LANDSCAPE_MODE = NO;   
  30.   
  31. //   
  32. //  The time it takes for a game screen to transition   
  33. //  These can be over written in the game screen init.   
  34. //  If there is no values in the game screen itself, these   
  35. //  will be used as the default values.   
  36. //   
  37. const float TRANSITION_ON_TIME = .70f;   
  38. const float TRANSITION_OFF_TIME = .20f;   
  39.   
  40. //   
  41. //  Implementation of the Screen Manager class   
  42. //   
  43. @implementation GLViewController   
  44.   
  45. //   
  46. //  Getters / Setters   
  47. //   
  48. @synthesize screens;   
  49. @synthesize screensToUpdate;   
  50. @synthesize input;   
  51. @synthesize blankTexture;   
  52.   
  53. @synthesize isInitialized;   
  54. @synthesize traceEnabled;   
  55.   
  56. @synthesize gameView;   
  57. @synthesize viewport;   
  58.   
  59. //   
  60. //  Setup View handles setting up OpenGL's Projection Matrix and   
  61. //  enables all states needed for rendering the game to screen.   
  62. //   
  63. -(void)setupView:(GLView*)view   
  64. {   
  65.     //  Set the view to the gameView   
  66.     gameView = view;   
  67.   
  68.     //  Modify the Projection matrix   
  69.     glMatrixMode(GL_PROJECTION);   
  70.     glLoadIdentity();   
  71.   
  72.     //   
  73.     //  Orthof projection is used for 2d games. This sets the coordinates to   
  74.     //  (0, 0) at the top left corner of the screen, and as you move downward   
  75.     //  your y value will increase. As you move to the right, your x value will   
  76.     //  increase.   
  77.     //  (left, right, bottom, top, near, far)   
  78.     //   
  79.     //  If the game is going to be played in landscape mode, enable   
  80.     //  it via the bool switch at the top of the GLViewController.m file.   
  81.     if ( LANDSCAPE_MODE )   
  82.     {   
  83.         viewport = CGRectMake(0, 0, 480, 320);   
  84.         glViewport(0, 0, viewport.size.height, viewport.size.width);   
  85.         glRotatef(-90, 0, 0, 1);   
  86.         glOrthof(0, viewport.size.width, viewport.size.height, 0, -10.0, 10.0);     
  87.   
  88.     }   
  89.     else    //  Game is to be played in portrait   
  90.     {   
  91.         viewport = CGRectMake(0, 0, 320, 480);   
  92.         glViewport(0, 0, viewport.size.width, viewport.size.height);   
  93.         glOrthof(0.0, viewport.size.width, viewport.size.height, 0.0, -1.0, 1.0);      
  94.   
  95.     }   
  96.   
  97.     //   
  98.     //  Setup Model view matrix   
  99.     //  Load graphics settings   
  100.     //   
  101.     glMatrixMode(GL_MODELVIEW);   
  102.   
  103.     glDisable(GL_DEPTH_TEST);   
  104.     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);   
  105.     glEnable(GL_BLEND);    
  106.   
  107.     //  needed to draw textures using Texture2D   
  108.     glEnable(GL_TEXTURE_2D);   
  109.     glEnableClientState(GL_TEXTURE_COORD_ARRAY);   
  110.     glEnableClientState(GL_VERTEX_ARRAY);   
  111.   
  112.     //  enables alpha for transparent textures   
  113.     //  I forget where I got these commands, iDevGames.net I think   
  114.     glAlphaFunc(GL_GREATER, 0.1f);   
  115.     glEnable(GL_ALPHA_TEST);   
  116.   
  117.     //   
  118.     //  Setup clear color (cornflower blue'ish)   
  119.     //  Call me crazy, but I got so used to this color developing   
  120.     //  for XNA. This is a little nod to the Microsoft Development   
  121.     //  Team :)   
  122.     //   
  123.     glLoadIdentity();   
  124.     glClearColor(.39f, 0.58f, 0.920f, 1.0f);    
  125.   
  126.     //   
  127.     //  Call the view controllers loadContent method   
  128.     //   
  129.     [self loadContent];   
  130.   
  131. }   
  132.   
  133. //   
  134. //  Loads all content needed to run the screen manager. This is seperated   
  135. //  from the setupView method in order to seperate what is needed from OpenGL   
  136. //  to setup the screen, and what is needed from the screen manager to set   
  137. //  up the game structure.   
  138. //   
  139. - (void)loadContent   
  140. {   
  141.     //   
  142.     //  Allocate memory for your arrays to hold the Screens "stacks."   
  143.     //  All game screens will be housed in this array for easy manipulation.   
  144.     //   
  145.     screens = [[NSMutableArray alloc] init];   
  146.     screensToUpdate = [[NSMutableArray alloc] init];   
  147.   
  148.     //   
  149.     //  Allocate memory for the input manager and the blankTexture used   
  150.     //  to fade the screen in / out.   
  151.     //   
  152.     input = [[InputManager alloc] init];   
  153.     input.isLandscape = LANDSCAPE_MODE;   
  154.     blankTexture = [[Texture2D alloc] initWithImage:[UIImage imageNamed:@"blankTexture.png"]];   
  155.   
  156.     for (GameScreen *screen in screens)   
  157.         [screen loadContent];   
  158.   
  159.     //   
  160.     //  Once we are initialized, set the bool values to appropriate values.   
  161.     //   
  162.     isInitialized = YES;   
  163.     traceEnabled = NO;   
  164.   
  165.     //   
  166.     //  Adds a title screen to the game stack. This will be taken out   
  167.     //  later, and right now is only used for debugging purposes. It   
  168.     //  will be replaced with your splash screen or game introduction   
  169.     //  screen.   
  170.     //   
  171.     TitleScreen *newScreen = [[TitleScreen alloc] init];   
  172.     [self addScreen:newScreen];   
  173.     [newScreen release];   
  174. }   
  175.   
  176. //   
  177. //  When the view controller exits, we will need to clean up any memory used.   
  178. //   
  179. - (void)dealloc   
  180. {   
  181.     //   
  182.     //  setup a delete screens array and add all of the current game screens   
  183.     //  to this array. We will then cycle through all game screens, unloading   
  184.     //  their content, and releasing them from the view controller. After all   
  185.     //  is said and done, we will then remove the deleteScreens array, and   
  186.     //  continue on releasing any other memory allocated for the view controller.   
  187.     //   
  188.     NSMutableArray *deleteScreens = [[NSMutableArray alloc] initWithArray:screens];   
  189.   
  190.     for (GameScreen *screen in deleteScreens)   
  191.     {   
  192.         [self removeScreen:screen];   
  193.         [self releaseScreen:screen];   
  194.     }   
  195.   
  196.     [deleteScreens release];   
  197.     [screens release];   
  198.     [screensToUpdate release];   
  199.     [input release];   
  200.     [blankTexture release];   
  201.   
  202.     [super dealloc];   
  203. }   
  204.   
  205. //   
  206. //  If the game is going over memory, this method will be called by the device   
  207. //  warning that we are running low on memory and should release any un needed   
  208. //  items.   
  209. //   
  210. - (void)didReceiveMemoryWarning   
  211. {   
  212.     //  <<TODO: Unload any un-needed game content here>>   
  213.     [super didReceiveMemoryWarning];   
  214. }   
  215.   
  216. //   
  217. //  Add a screen to the view controller   
  218. //   
  219. - (void) addScreen:(GameScreen *)screen   
  220. {   
  221.     //   
  222.     //  When adding a screen to the view controller, we will be   
  223.     //  setting some default values for the screen, and then call   
  224.     //  the screens "loadContent" method. Once everything is loaded,   
  225.     //  the view controller will retain the screen and add it to the   
  226.     //  screens array.   
  227.     //   
  228.     screen.controller = self;   
  229.     screen.viewport = self.viewport;   
  230.     screen.transitionOnTime = TRANSITION_ON_TIME;   
  231.     screen.transitionOffTime = TRANSITION_OFF_TIME;   
  232.     screen.currentScreenState = TransitionOn;   
  233.     screen.transitionPosition = 1;   
  234.     [screen loadContent];   
  235.   
  236.     [screen retain];   
  237.     [screens addObject:screen];   
  238. }   
  239.   
  240. //   
  241. //  Unload all game content from the screen. This in turn   
  242. //  sets a flag within the screen itself, that the content has   
  243. //  been unloaded, and in the controllers Update method, all game   
  244. //  screens that have been unloaded will be released from memory.   
  245. //   
  246. - (void) removeScreen:(GameScreen *)screen   
  247. {   
  248.     //unload any content it has stored   
  249.     [screen unloadContent];   
  250. }   
  251.   
  252. //   
  253. //  Release all game screens from memory, that have had their content   
  254. //  unloaded. This will release all screens themselves, as well as remove   
  255. //  them from the screens arrays.   
  256. //   
  257. - (void) releaseScreen:(GameScreen *)screen   
  258. {   
  259.     //  remove the screen from all screen arrays   
  260.     [screens removeObject:screen];   
  261.     [screensToUpdate removeObject:screen];   
  262.   
  263.     //  deallocate any memory used for the screen   
  264.     [screen release];   
  265. }   
  266.   
  267. //   
  268. //  Update every screen in the screens stack, keeping track   
  269. //  of which screens are covered and which are fully active.   
  270. //  if a screen is fully active and "on top" of the stack, it   
  271. //  should receive any input.   
  272. //   
  273. - (void) updateView:(GLView *)view WithTime:(float)deltaTime   
  274. {   
  275.     //  Read the touch input   
  276.     [input update:deltaTime];   
  277.   
  278.     //  make a copy of hte master screen list, to avoid confusion if   
  279.     //  the process of updating one screens adds or removes others.   
  280.     [screensToUpdate removeAllObjects];   
  281.   
  282.     for(GameScreen *screen in screens)   
  283.         [screensToUpdate addObject:screen];   
  284.   
  285.     bool otherScreenHasFocus = NO;   
  286.     bool coveredByOtherScreen = NO;   
  287.   
  288.     //  loop as long as there are screens waiting to be updated   
  289.     while ([screensToUpdate count] > 0)   
  290.     {   
  291.         //  pop the topmost screen off the waiting list   
  292.         GameScreen *screen = [screensToUpdate objectAtIndex:([screensToUpdate count] - 1)];   
  293.   
  294.         [screensToUpdate removeObjectAtIndex:[screensToUpdate count] - 1];   
  295.   
  296.         //  update the screen   
  297.         [screen update:deltaTime OtherScreenHasFocus:otherScreenHasFocus   
  298.                                 CoveredByOtherScreen:coveredByOtherScreen];   
  299.   
  300.         if ([screen currentScreenState] == TransitionOn ||   
  301.             [screen currentScreenState] == Active)   
  302.         {   
  303.             //  if this is the first active screen we came across,   
  304.             //  give it a chance to handle input.   
  305.             if (!otherScreenHasFocus)   
  306.             {   
  307.                 [screen handleInput:input];   
  308.                 otherScreenHasFocus = YES;   
  309.             }   
  310.   
  311.             //  if this is an active non-popup, inform any subsequent   
  312.             //  screens that they are covered by it   
  313.             if (![screen isPopup])   
  314.                 coveredByOtherScreen = YES;   
  315.   
  316.         }   
  317.     }   
  318.   
  319.     //  do we need to print the debug trace?   
  320.     if (traceEnabled)   
  321.         [self traceScreens];   
  322.   
  323.     //   
  324.     //  For every screen that had their content unloaded.. release   
  325.     //  the memory used for that screen here. We do this up front   
  326.     //  to ensure that any released screen doesn't get their update   
  327.     //  or draw methods called, when there is nothing to update or draw.   
  328.     //   
  329.     for (GameScreen *screen in screens)   
  330.     {   
  331.         if (screen.hasBeenUnloaded)   
  332.         {   
  333.             [self releaseScreen:screen];   
  334.         }   
  335.     }   
  336. }   
  337.   
  338. //   
  339. //  Draw the game screens from "Bottom to Top." This is done   
  340. //  in order to ensure that any pop'up screens are drawn on top   
  341. //  of the full screen below it.   
  342. //   
  343. - (void) drawView:(GLView *)view WithTime:(float)deltaTime   
  344. {   
  345.     //  Clear the screen to preset color before drawing   
  346.     glClear(GL_COLOR_BUFFER_BIT);   
  347.   
  348.     //  Draw every screen in the screens array   
  349.     for (GameScreen *screen in screens)   
  350.     {   
  351.         //if the screens content has been unloaded, don't draw   
  352.         if (screen.hasBeenUnloaded)   
  353.             continue;   
  354.   
  355.         [screen draw:deltaTime];   
  356.     }   
  357. }   
  358.   
  359. //   
  360. //  Helper method designed to draw the screen names currently   
  361. //  in the game stack in order to see if they are being added   
  362. //  and removed correctly.   
  363. //   
  364. - (void) traceScreens   
  365. {   
  366.     //  <<TODO: Input code to draw the screen names>>   
  367. }   
  368.   
  369. //   
  370. //  Helper method to draw a translecent black fullscreen sprite, used   
  371. //  for fading screens in and out, and for darkening the background   
  372. //  behind pop up screens.   
  373. //   
  374. - (void) fadeBackBufferToBlack:(double)alpha   
  375. {   
  376.     glColor4f(alpha,alpha,alpha,alpha);   
  377.     [blankTexture drawInRect:self.viewport];   
  378.     glColor4f(1, 1, 1, 1);   
  379. }   
  380.   
  381. //   
  382. //  When the screen is touched by the user, the GLView will pass along a message   
  383. //  to the view controller that the screen has been touched. The view controller   
  384. //  will take the message, and pass it along to the input manager where the   
  385. //  necessary information will be stored and filtered to the game screen that   
  386. //  will handle the user input.   
  387. //   
  388. //  In order for this to work, in your GLView, you need to write the following   
  389. //  4 methods:   
  390. //  - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event   
  391. //  - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event   
  392. //  - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event   
  393. //  - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event   
  394. //   
  395. //  Those methods will call the methods below.   
  396. //   
  397. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer   
  398. {   
  399.     [input touchesBegan:touches withEvent:event InView:touchView  WithTimer:timer];   
  400. }   
  401.   
  402. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer   
  403. {   
  404.     [input touchesMoved:touches withEvent:event InView:touchView  WithTimer:timer];   
  405. }   
  406.   
  407. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer   
  408. {   
  409.     [input touchesEnded:touches withEvent:event InView:touchView  WithTimer:timer];   
  410. }   
  411.   
  412. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event InView:(UIView *)touchView WithTimer:(NSTimer *)timer   
  413. {   
  414.     [input touchesCancelled:touches withEvent:event InView:touchView  WithTimer:timer];   
  415. }   
  416.   
  417. @end  

As you can see, this is a pretty good sized class. What makes it bigger is I have a nasty habit of commenting everything to hell! I always believe it is best to comment heavily, because if you come back a year later and want to adjust your game, comments make it very helpful for remembering what does what.

The comments in the GLViewController (screen manager) class explains what everything does, but if you have any questions feel free to post them here.

So… now we need a game screen or two!! Remember, the following code should never be used to make a game screen directly. What I mean is, use this as a super class and inherit from it with your screens. For example, your TitleScreen should inherit from GameScreen. Make sense?

here is the GameScreen.h file

  1.   
  2. //   
  3. //  A screen is a single layer that has update and draw logic, and which   
  4. //  can be combined with other layers to build up a complex screen system   
  5. //  or menu system, or even dialog system.   
  6. //   
  7. //  Developed by XNA Development Studio ( http://creators.xna.com/ )   
  8. //  Modified for the iPhone Gameing Framework by Craig Giles on 1/1/09.   
  9. //   
  10.   
  11. #import <Foundation/Foundation.h>   
  12.   
  13. #import <OpenGLES/EAGL.h>   
  14. #import <OpenGLES/ES1/gl.h>   
  15. #import <OpenGLES/ES1/glext.h>   
  16.   
  17. #import "InputManager.h"   
  18. #import "Texture2D.h"   
  19.   
  20. //   
  21. //  Enum to describe the screens transition state   
  22. //   
  23. enum ScreenState {   
  24.     TransitionOn = 0,   
  25.     Active,   
  26.     TransitionOff,   
  27.     Hidden   
  28. };   
  29.   
  30. //   
  31. //  Forward Declarations   
  32. //   
  33. @class GLViewController;   
  34.   
  35. @interface GameScreen : NSObject   
  36. {   
  37. @private  
  38.     GLViewController *controller;   
  39.     CGRect viewport;   
  40.   
  41.     bool hasBeenUnloaded;   
  42.     bool isPopup;   
  43.   
  44.     float transitionOnTime;   
  45.     float transitionOffTime;   
  46.     float transitionPosition;   
  47.     float transitionAlpha;   
  48.     enum ScreenState currentScreenState;   
  49.   
  50.     bool isExiting;   
  51.     bool isActive;   
  52.     bool otherScreenHasFocus;   
  53. }   
  54.   
  55. @property (nonatomic, retain) GLViewController *controller;   
  56. @property (readwrite) CGRect viewport;   
  57.   
  58. @property (readwrite) bool hasBeenUnloaded;   
  59. @property (readwrite) bool isPopup;   
  60.   
  61. @property (readwrite) float transitionOnTime;   
  62. @property (readwrite) float transitionOffTime;   
  63. @property (readwrite) float transitionPosition;   
  64. @property (readwrite) float transitionAlpha;   
  65.   
  66. @property (readwrite) enum ScreenState currentScreenState;   
  67.   
  68. @property (readwrite) bool isExiting;   
  69. @property (readwrite) bool isActive;   
  70. @property (readwrite) bool otherScreenHasFocus;   
  71.   
  72. - (void) loadContent;   
  73. - (void) unloadContent;   
  74.   
  75. - (void) handleInput:(InputManager *)input;   
  76. - (void) update:(float)deltaTime    OtherScreenHasFocus:(bool)otherFocus    CoveredByOtherScreen:(bool)coveredByOtherScreen;   
  77. - (bool) updateTransition:(float)deltaTime  TransitionTime:(float)transition    Direction:(int)direction;   
  78. - (void) draw:(float)deltaTime;   
  79.   
  80. - (void) exitScreen;   
  81.   
  82. @end  

and the GameScreen.m file

  1.   
  2. //   
  3. //  A screen is a single layer that has update and draw logic, and which   
  4. //  can be combined with other layers to build up a complex screen system   
  5. //  or menu system, or even dialog system.   
  6. //   
  7. //  Developed by XNA Development Studio ( http://creators.xna.com/ )   
  8. //  Modified for the iPhone Gameing Framework by Craig Giles on 1/1/09.   
  9. //   
  10.   
  11. #import "GameScreen.h"   
  12.   
  13. @implementation GameScreen   
  14.   
  15. //   
  16. // Properties   
  17. //   
  18. @synthesize controller;   
  19. @synthesize viewport;   
  20.   
  21. @synthesize hasBeenUnloaded;   
  22. @synthesize isPopup;   
  23.   
  24. @synthesize transitionOnTime;   
  25. @synthesize transitionOffTime;   
  26. @synthesize transitionPosition;   
  27. @synthesize transitionAlpha;   
  28.   
  29. @synthesize currentScreenState;   
  30.   
  31. @synthesize isExiting;   
  32. @synthesize otherScreenHasFocus;   
  33.   
  34. @dynamic isActive;   
  35. - (bool) isActive   
  36. {   
  37.     return !otherScreenHasFocus &&   
  38.     (currentScreenState == TransitionOn ||   
  39.      currentScreenState == Active);   
  40. }   
  41.   
  42. //   
  43. // Constructor(s) / destructors   
  44. //   
  45. - (id) init   
  46. {   
  47.     self = [super init];   
  48.     if (self != nil)   
  49.     {   
  50.         //initializations go here   
  51.         isExiting = NO;   
  52.     }   
  53.     return self;   
  54. }   
  55.   
  56. - (void) dealloc   
  57. {   
  58.     //Deallocations go here   
  59.     [super dealloc];   
  60. }   
  61.   
  62. //   
  63. // Loads all content associated with the current screen   
  64. //   
  65. - (void) loadContent   
  66. {   
  67.   
  68. }   
  69.   
  70. //   
  71. // Unloads all content associated with the current screen   
  72. //   
  73. - (void) unloadContent   
  74. {   
  75.     //  Release the screen manager   
  76.     [controller release];   
  77.   
  78.     //  inidicate that the screens content has been unloaded   
  79.     hasBeenUnloaded = YES;   
  80. }   
  81.   
  82. //   
  83. // Allows the screen to perform its update logic.   
  84. //   
  85. - (void) handleInput:(InputManager *)input   
  86. {   
  87. }   
  88.   
  89. //   
  90. //  Updates the base screen. Since any game screen   
  91. //  wil be inheriting from this class, the game screen will   
  92. //  call this update method. This update just helps with the   
  93. //  transition between two screens, and if a screen is   
  94. //  transitioning on and off.   
  95. //   
  96. - (void) update:(float)deltaTime    OtherScreenHasFocus:(bool)otherFocus    CoveredByOtherScreen:(bool)coveredByOtherScreen   
  97. {   
  98.     otherScreenHasFocus = otherFocus;   
  99.   
  100.     if (isExiting)   
  101.     {   
  102.         //if the screen is going to die, it should transition off   
  103.         currentScreenState = TransitionOff;   
  104.   
  105.         if (![self updateTransition:deltaTime TransitionTime:transitionOffTime Direction: 1])   
  106.         {   
  107.             //when transition finishes, remove the screen   
  108.             [controller removeScreen:self];   
  109.         }   
  110.     }   
  111.     else if (coveredByOtherScreen)   
  112.     {   
  113.         //if the screen is covered by another, it should transition off   
  114.         if ([self updateTransition:deltaTime TransitionTime:transitionOffTime Direction: 1])   
  115.         {   
  116.             //scren is still transitioning   
  117.             currentScreenState = TransitionOff;   
  118.         }   
  119.         else  
  120.         {   
  121.             //transition has finished   
  122.             currentScreenState = Hidden;   
  123.         }   
  124.     }   
  125.     else  
  126.     {   
  127.         if ([self updateTransition:deltaTime TransitionTime:transitionOnTime Direction: -1])   
  128.         {   
  129.             //still busy transitioning   
  130.             currentScreenState = TransitionOn;   
  131.         }   
  132.         else  
  133.         {   
  134.             //transition finished   
  135.             currentScreenState = Active;   
  136.         }   
  137.     }   
  138. }   
  139.   
  140. //   
  141. //  Helper method for updating the screen transition position   
  142. //  (how much the screen has faded in / out)   
  143. //   
  144. - (bool) updateTransition:(float)deltaTime TransitionTime:(float)time Direction:(int)direction   
  145. {   
  146.     //  how much should we move by?   
  147.     float transitionDelta;   
  148.   
  149.     if (time <= 0)   
  150.         transitionDelta = 1;   
  151.     else  
  152.         transitionDelta = deltaTime / time;   
  153.   
  154.     //update the transition position   
  155.     transitionPosition += transitionDelta * direction;   
  156.   
  157.     //did we reach the end of the transition?   
  158.     if (direction < 0 && transitionPosition <= 0 ||   
  159.         direction > 0 && transitionPosition >= 1)   
  160.     {   
  161.         //clamp transition position to 0, 1, or value;   
  162.         if (transitionPosition >= 1)   
  163.             transitionPosition = 1;   
  164.         else if (transitionPosition <= 0)   
  165.             transitionPosition = 0;   
  166.   
  167.         return NO;   
  168.     }//end "end of transition"   
  169.   
  170.     //otherwise, we are still busy transitioning   
  171.     return YES;   
  172. }   
  173.   
  174. //   
  175. //  Each screen will have their own draw method. EVERY SCREEN   
  176. //  should call [super draw:deltaTime] in order to draw   
  177. //  the fade correctly when the screen manager wishes to fade   
  178. //  the screen in or out.   
  179. //   
  180. - (void) draw:(float)deltaTime   
  181. {   
  182.     [self.controller fadeBackBufferToBlack:self.transitionPosition];   
  183. }   
  184.   
  185. //   
  186. // Tells the screen to go away. Unlike [controller removeScreen] which   
  187. // instantly kills the screen, this method respects the transition timings   
  188. // and will give the scren a chance to gradually transition off.   
  189. //   
  190. - (void) exitScreen   
  191. {   
  192.     if (transitionOffTime == 0)   
  193.     {   
  194.         //if the screen has zero transition time, kill it   
  195.         [controller removeScreen:self];   
  196.     }   
  197.     else  
  198.     {   
  199.         //otherwise flag that it should transition off and exit   
  200.         isExiting = YES;   
  201.     }   
  202. }   
  203.   
  204. @end  

Well that does it for the screen manager and the game screen classes.. But keep in mind.. this will NOT build until the InputManager is built. Why don’t you try to fiddle with that for a while, see what you can come up with? I’ll post Part 2 of this tutorial detailing how I did my input manager and two screens (TitleScreen and PausedScreen) in my next update.

Two thing before I go: I would really like to find a way to turn this into a template for anyone wishing to use it, but I simply do not know how. If you know how to do so, please send me an email at:
CraigGiles9@yahoo.com

Secondly, if you have any questions, comments, sly remarks, please post them. I am very good at reading everyones comments, and getting back to you if needed. You can either post a comment or send me an email and I’ll get back to you.

EDIT:
I just wanted to let everyone know that there have been a few changes to this article since first posting. I just modified the code within the GLViewController in several places. The following changes were made:
- Added [self releaseScreen:screen]; in the dealloc method inside the for loop.
- added const bool LANDSCAPE_MODE = NO; at the top of the view controller, and an if / else statement in the setup view method to help with setting up a landscape view rather than a portrait view. (The first screen manager was written for only portrait view)
- added input.isLandscape = LANDSCAPE_MODE; to the loadContent method.

Again, there are too many people to thank for helping me to get to where I am with my current knowledge. I hope this was informational to a few of you! Happy coding everyone!

6 Comments so far

  1. [...] detailed article about writing code especially for developers who have experience with XNA [...]

  2. Craig White on

    Hi, excellent post. This could be a great starting point for anyone trying to make a game. I haven’t tried the code yet but will sometime in the near future. Keep it up.

    I’m not sure if this is what you mean by creating a template, but any project you create in Xcode can be used as a template by placing here:

    Library/Application Support/Developer/Shared/Xcode/ProjectTemplates/MacFUSE/MyProject

    Cheers!

  3. Craig on

    I think I tried that and it didn’t work like I wanted it too.. but I’ll re-look into it. Thanks for the heads up!

  4. mc on

    have you had any problems loading a project using jeff’s template onto an actual iphone? sometimes i get these info.plist null errors but when it does load, it loads as a glgravity app.

  5. Devang on

    i am getting file not found errors for
    #import “Texture2D.h”
    #import “InputManager.h”
    #import “GameScreen.h”
    #import “TitleScreen.h”
    I did exactly as described above, but was not able to compile.
    Thanks in advance.

  6. Craig on

    I’m going to assume you have not created any of hte above files or gone to Stage 2 tutorial (so you have not created the import manager or the GameScreen classes) ?

Trackback Address :: http://joyholic.kr/trackback/363 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/17 22:15

Access the Address Book

I got a request on how do I access the address book in the iPhone. So I took around 30 minutes to learn how and here is how we will do it. 

First create a new View-Based Application and call it addressBook.

Now the first thing we want to do is setup the 4 IBOutlets and the 1 IBAction for our project. We also need to include the headers for the address book framework. So open up addressBookViewController.h and you want to make it look like the following.

#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
@interface addressBookViewController : UIViewController  {
	IBOutlet UIButton *button;
	IBOutlet UILabel *firstName;
	IBOutlet UILabel *lastName;
	IBOutlet UILabel *number;
}

-(IBAction)getContact;

@end

Now that they are added we need to add in the framework files. So you will right click on the addressBook in the Targets option on the left panel and click on Get Info.

At the bottom there is a + and click that and you need to add the following items in AddressBook.framework and AddressBookUI.framework

Now lets layout our view. So double click on addressBookViewController.xib. You want your view to look like the following.

I used the —–’s just so you can see there is a UILabel there. Now we need to setup the connections for the 4 outlets and the one action. You want it to look like the following

So now lets open up addressBookViewController.m and we want to add in the following methods.

-(IBAction)getContact {
	// creating the picker
	ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
	// place the delegate of the picker to the controll
	picker.peoplePickerDelegate = self;

	// showing the picker
	[self presentModalViewController:picker animated:YES];
	// releasing
	[picker release];
}

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
    // assigning control back to the main controller
	[self dismissModalViewControllerAnimated:YES];
}

- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {

	// setting the first name
    firstName.text = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);

	// setting the last name
    lastName.text = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);	

	// setting the number
	/*
	 this function will set the first number it finds

	 if you do not set a number for a contact it will probably
	 crash
	 */
	ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty);
	number.text = (NSString*)ABMultiValueCopyValueAtIndex(multi, 0);

	// remove the controller
    [self dismissModalViewControllerAnimated:YES];

    return NO;
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
    return NO;
}

Now we can click build and go and see the following


As always you can grab the source here.

Comments

13 Responses to “Access the Address Book”

  1. Using iPhone Address Book - iPhone Dev SDK Forum on September 19th, 2008 3:30 pm

    [...] just wrote up one on my blog Iphone Noob

  2. Retrieving contacts info - iPhone Dev SDK Forum on September 20th, 2008 8:51 am

    [...] iPhone noob just posted an article about this: Iphone Noob

  3. Justin on October 2nd, 2008 5:42 am

    Did you just pull this straight from the AddressBook Programming Guide? You really should reference your sources :)

    Have you had any success modifying the people-picker at all to get it to link up with the navigation controller from the rest of an application?

    /J

  4. Amit on October 8th, 2008 3:10 am

    Is it possible to replace or extend the default phone/contact application in iPhone? I will be building an new contact application and I dont to override the default one so that when a user clicks the iPhone default icon for contacts (or phone) then it either invokes my application or gives me some way to extend its functionality?

    Is it really possible?

  5. iSpazio AccessContact - iSpazio Developer Program #7 | iSpazio - Il Blog sull'iPhone più letto in Italia e nel Mondo on October 23rd, 2008 9:11 am

    [...] creata in italiano da Andrea Busi per iSpazio.net. Trovare la guida originale a questo indirizzo: “Access the Address Book: Iphone Noob”. I meriti quindi relativamente alla versione inglese, sono del legittimo [...]

  6. The Bubi Devs » DevTutorial #7 - AccessContact on October 31st, 2008 12:13 pm

    [...] e “The Bubi Devs”. Trovare la guida originale a questo indirizzo: “Access the Address Book: Iphone Noob”. I meriti quindi relativamente alla versione inglese, sono del legittimo [...]

  7. Doug Diego » Blog Archive » iPhone Address Book on November 10th, 2008 8:38 pm
  8. lakshmikanthreddy on January 6th, 2009 2:38 pm

    thank you ,

    thanks a lot , this application has been very much useful for me .

    lakshmi kanth .

  9. kislay sharma on January 19th, 2009 8:50 am

    can any one tell me how to create a new contact detail from coding itself like we can fetch the data from contact list So how to save from application to contact list

  10. Alex on January 22nd, 2009 4:28 pm

    Hi Everybody, I try to use the iPhone Calendar from my ipa. Therefore, could you please let me know the correct way to implement the iCal interface? Is this possible?

    Thanks a lot for any help about it,
    Alex

  11. Agustin on February 20th, 2009 3:31 pm

    Hi There,

    Is there a way to access to country codes from the iphone contacts to integrated to my application. Or do I have to create my own contries table?

    Thanks.

  12. Yasser on February 24th, 2009 11:25 am

    Hello,
    i can’t find AddressBookUI.framework on the list of FrameWork !!!!

  13. Yasser on February 24th, 2009 12:05 pm

    that’s Work. Thanks.

Trackback Address :: http://joyholic.kr/trackback/361 관련글 쓰기
Name
Password
Homepage
Secret
2009/03/13 13:20
on_lazy_ptr in general
FROM : Nick Zitzmann
DATE : Thu Nov 13 03:13:31 2008

Yesterday, I was building some open source code that depended on a  
third-party library, liboil. Liboil is a library that defines most of  
its symbols as generic pointers, then provides architecture-specific  
implementations of each function, and these implementations are  
assigned to the memory addresses of those pointers at initialization  
time. I'm guessing they did this so they could support a very broad  
number of architectures and CPU features.

The problem is, when linking it against the project that was using it,  
I got a linker error like this:

Undefined symbols:
  "_some_function", referenced from:
      _some_function$non_lazy_ptr in some_source.o

So I searched Google for non_lazy_ptr, and saw lots of other people  
who have had this problem compiling various projects out there on Mac  
OS X, and no one really knew what was causing this to happen, or how  
to fix it.

So what causes these non_lazy_ptr linker errors, and how do I properly  
fix them? My interim solution was to use the -U linker option to make  
the linker dynamically look up the symbol, but I suspect that wasn't  
the correct solution...

Nick Zitzmann
<http://seiryu.home.comcast.net/>
Trackback Address :: http://joyholic.kr/trackback/358 관련글 쓰기
Name
Password
Homepage
Secret
prev"" #1 #2 next