아이폰어플개발정보2010. 9. 12. 21:18
아이폰 어플 개발에서 TableView 넣는 방법 간단 정리

1. UIView 밑에 TableView 생성


2. TableView 클릭 + 컨트롤키누르고 file's owner로 드래그 datasource,delegate 2개 클릭


3. 필수함수인 2개를 코딩



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

static NSString *cIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cIdentifier];

if(cell == nil){

cell = [[[UITableViewCellalloc]

initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:cIdentifier]

autorelease];

}

cell.textLabel.text = @"table";

return cell;

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

return5;

}




출처 : http://blog.naver.com/PostList.nhn?blogId=hana_815¤tPage=49
Posted by 오늘마감

댓글을 달아 주세요

아이폰어플개발정보2010. 9. 12. 21:18
navigationBar에컬러주는 방법

self.navigationController.navigationBar.tintColor[UIColor colorWithRed:0.20392f green:0.19607f blue:0.61176f alpha:1.0f];



출처 : http://blog.naver.com/PostList.nhn?blogId=philipousys¤tPage=13
Posted by 오늘마감

댓글을 달아 주세요

아이폰어플개발정보2010. 9. 11. 09:27
아이폰 어플 개발할때 pickerView 세팅하는 방법

pickerView의 디스플레이될 데이타항목 세팅시 나타낼것

#pragma mark -

#pragma mark UIPickerViewDataSource

//picker의 선택항목이 두개일때

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component

{

NSString *returnStr = @"";

// note: custom picker doesn't care about titles, it uses custom views

if (pickerView == myPickerView)

{

if (component == 0)

{

returnStr = [pickerViewArray objectAtIndex:row];

}

else

{

returnStr = [[NSNumber numberWithInt:row] stringValue];

}

}

return returnStr;

}

//각 분리된 항목별 디스플레이면적

- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component

{

CGFloat componentWidth = 0.0;

if (component == 0)

componentWidth = 240.0;// first column size is wider to hold names

else

componentWidth = 40.0;// second column is narrower to show numbers

return componentWidth;

}

//

- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component

{

return40.0;

}

//갯수

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component

{

return [pickerViewArraycount];

}

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView

{

return2;

}




출처 : http://blog.naver.com/PostList.nhn?blogId=philipousys¤tPage=11
Posted by 오늘마감

댓글을 달아 주세요

아이폰어플개발정보2010. 9. 11. 09:25
mapView위에 컨트롤을 올리는 간단한 방법

간단하다. 그냥 mapView아래에 두면된다.
쏘스상에서 신경안써도된다.

self.isPlaying=NO;

upCount=0;

downCount=0;

backwardCount=0;

forwardCount=0;

    // register for keyboard notifications

//[super viewDidLoad];

//self.frontView = [[UIView alloc]init];

//[self.view addSubview:self.frontView];

//mapView=[[MKMapView alloc]initWithFrame:CGRectMake(0, 0, 320, 320)];

mapView.showsUserLocation=TRUE;

mapView.mapType=MKMapTypeStandard;

mapView.delegate=self;

MKCoordinateRegion region;

MKCoordinateSpan span;

span.latitudeDelta=0.012;

span.longitudeDelta=0.012;

locationManager=[[CLLocationManageralloc] init];

locationManager.delegate=self;

locationManager.desiredAccuracy=kCLLocationAccuracyNearestTenMeters;

[locationManagerstartUpdatingLocation];   //Activate this line for having GPS tracking working

CLLocationCoordinate2D location2; //= mapView.userLocation.coordinate;

location2.latitude=45.43717;

location2.longitude=12.32688;

//location2.latitude=self.startLatitude;

//location2.longitude=self.startLongitude;

//self.label_curLon.text=[NSNumber  numberWithDouble:[self startLatitude]];

//self.label_curLat.text=[NSNumber numberWithDouble:[self startLatitude]];

//self.label_curLon.text=[[NSString alloc] initWithFormat:@"%d", [self startLatitude]];

//self.label_curLat.text=[[NSString alloc] initWithFormat:@"%d", [self startLongitude]];

region.span=span;

region.center=location2;

[mapViewsetRegion:region animated:NO];

//[mapView regionThatFits:region];

[self.frontViewinsertSubview:mapViewatIndex:0];

CLLocationCoordinate2D c;

NSString *latitude =  @"45.43700";

NSString *longitude = @"12.32516";

c.latitude = [latitude doubleValue];

c.longitude = [longitude doubleValue];

GPSAnnotation *annotation = [[GPSAnnotationalloc] initWithCoordinate:c];

annotation.currentPoint = [NSNumber numberWithInt:1];

annotation.mTitle=@"Point number 1";

[mapView addAnnotation:annotation];

[annotation release];

self.trace=[[NSMutableArrayalloc]init];

}

보다시피 viewDid, viewWillAppear에서 addSubView할 필요없다.


Posted by 오늘마감

댓글을 달아 주세요

아이폰어플개발정보2010. 9. 11. 09:14
아이폰 os4에서 앱 종료할때 refresh하는 방법
유저가 알아서 한다. 
종료버튼 만드는건 불필요
단지 foreground로 자신의 app이 떳을때 아래함수 있용 refresh를 적절하게 하면된다.
- (void)applicationDidEnterBackground:(UIApplication *)application { } - (void)applicationWillEnterForeground:(UIApplication *)application { }
iPhone20
 
Join Date: Sep 2009
Posts: 110
 How to close an app in OS 4.0

Hello,

Wondering how to close an app in OS 4.0. 
It saves the state of an app and resumes it from where you left off. Cool feature!!
But, At some point to fetch the current data i want to completely close the application and start it over again. Any idea?

Thanks
  
 06-28-2010, 10:17 AM   #2 (permalink)
Emphasizing Fundamentals
 
 
Join Date: Jul 2009
Location: Loveland, OH
Age: 35
Posts: 2,801

No you don't. You want to use the new methods corresponding to multitasking.
__________________
My Company: BriTer Ideas LLC
My Services: Code review, consulting, development. PM for details.
My Apps: SlickShopperSports Minute (Or So)

Ways to thank me: Buy my app. Leave a PayPal donation.

Things I've Written That You Should Read:
Definitive Guide To Properties | iPhone Development Resources, Tips, and Tricks | UITableView Series(Last update: 2/24)
  
 06-28-2010, 10:37 AM   #3 (permalink)
iPhone20
 
Join Date: Sep 2009
Posts: 110

Quote:
Originally Posted by BrianSlick 
No you don't. You want to use the new methods corresponding to multitasking.
I thought there should be a way, as it would utilize resources and battery.
I think from task dock you can close the app though i never tried it on a device.
  
 06-28-2010, 11:11 AM   #4 (permalink)
Emphasizing Fundamentals
 
 
Join Date: Jul 2009
Location: Loveland, OH
Age: 35
Posts: 2,801

Starting and stopping the app should be the user's decision, not yours.

Go watch the WWDC videos related to multitasking. It is a simple matter to reload your data when the app will come to the foreground.
__________________
My Company: BriTer Ideas LLC
My Services: Code review, consulting, development. PM for details.
My Apps: SlickShopperSports Minute (Or So)

Ways to thank me: Buy my app. Leave a PayPal donation.

Things I've Written That You Should Read:
Definitive Guide To Properties | iPhone Development Resources, Tips, and Tricks | UITableView Series(Last update: 2/24)
  
 06-28-2010, 11:26 AM   #5 (permalink)
Registered Member
 
Join Date: Nov 2009
Posts: 315

You can prevent your application from running the background at all by setting UIApplicationExitsOnSuspend to YES in the app's Info.plist file, but you should think very carefully before doing this. This ensures that your app is always terminated when the user closes it, but this is probably not what your users will expect or want.

A much better approach would be to rethink the way you load data in your app so that you can refresh it whenever the app resumes being active, instead of needing to completely terminate and restart it.
  
 06-28-2010, 11:48 AM   #6 (permalink)
iPhone20
 
Join Date: Sep 2009
Posts: 110

Thanks. I found that we can get the application status by using methods

Code:
- (void)applicationDidEnterBackground:(UIApplication *)application { } - (void)applicationWillEnterForeground:(UIApplication *)application { }
Now, i can easily refresh the data.

Thank you.


출처 : http://blog.naver.com/PostList.nhn?blogId=philipousys¤tPage=2
Posted by 오늘마감

댓글을 달아 주세요

아이폰어플개발정보2010. 9. 11. 09:12
아이폰어플 개발, 폰트 설정하는 방법

아이폰 SDK의 UIKit에는 문자열의 출력을 위해 NSString에 추가된 메소드들을 제공합니다. 이를 이용해서 UIView의 drawRect에서 직접 문자열을 출력하는 간단한 방법을 알아 보겠습니다. UIKit에 추가된 NSString의 메소드들에 대한 자세한 설명은 iPhone DevCenter의 NSString UIKit Additions Reference 문서에서 확인하실 수 있습니다.

1. 폰트 설정

폰트는 UIFont를 사용하여 설정할 수 있습니다. iPhone과 터치에서 사용가능한 폰트는 아래의 소스를 이용하여 확인할 수 있습니다.

NSArray* familyArray = [UIFont familyNames];
for (NSString *familyName in familyArray) {
    NSLog(@"- %@", familyName);   
    NSArray *fontArray = [UIFont fontNamesForFamilyName:familyName];
        
    for (NSString *fontName in fontArray) {
        NSLog(@"%@", fontName);
    }   
}

위 소스를 실행하면 아래와 같이 폰트들의 목록이 출력됩니다. 전체목록은 아래의 '모든 폰트 보기'를 클릭하시면 확인하실 수 있습니다.
- Georgia
Georgia-Bold
Georgia
Georgia-BoldItalic
Georgia-Italic

닫기

- Courier
Courier
Courier-BoldOblique
Courier-Oblique
Courier-Bold

- AppleGothic
AppleGothic

- Arial
ArialMT
Arial-BoldMT
Arial-BoldItalicMT
Arial-ItalicMT

- STHeiti TC
STHeitiTC-Light
STHeitiTC-Medium

- Hiragino Kaku Gothic ProN
HiraKakuProN-W6
HiraKakuProN-W3

- Courier New
CourierNewPS-BoldMT
CourierNewPS-ItalicMT
CourierNewPS-BoldItalicMT
CourierNewPSMT

- Zapfino
Zapfino

- Arial Unicode MS
ArialUnicodeMS

- STHeiti SC
STHeitiSC-Medium
STHeitiSC-Light

- American Typewriter
AmericanTypewriter
AmericanTypewriter-Bold

- Helvetica
Helvetica-Oblique
Helvetica-BoldOblique
Helvetica
Helvetica-Bold

- Marker Felt
MarkerFelt-Thin

- Helvetica Neue
HelveticaNeue
HelveticaNeue-Bold

- DB LCD Temp
DBLCDTempBlack

- Verdana
Verdana-Bold
Verdana-BoldItalic
Verdana
Verdana-Italic

- Times New Roman
TimesNewRomanPSMT
TimesNewRomanPS-BoldMT
TimesNewRomanPS-BoldItalicMT
TimesNewRomanPS-ItalicMT

- Georgia
Georgia-Bold
Georgia
Georgia-BoldItalic
Georgia-Italic

- STHeiti J
STHeitiJ-Medium
STHeitiJ-Light

- Arial Rounded MT Bold
ArialRoundedMTBold

- Trebuchet MS
TrebuchetMS-Italic
TrebuchetMS
Trebuchet-BoldItalic
TrebuchetMS-Bold

- STHeiti K
STHeitiK-Medium
STHeitiK-Light

닫기


폰트명을 보면 볼드는 -bold와 이텔릭은 -Italic과 같이 되어 있어 각각의 특징을 알 수 있습니다. 폰트는 일반적으로 UIFont의 아래와 같은 메소드를 사용하여 생성합니다.
+ (UIFont *)fontWithName:(NSString *)fontName size:(CGFloat)fontSize

fontName에는 폰트명을 fontSize에는 크기를 설정하여 UIFont 오브젝트를 생성합니다. 아래는 위의 메소드를 이용하여 19 사이즈의 'Verdana-Bold' 폰트를 생성하는 예입니다.
UIFont *generalFont = [UIFont fontWithName:@"Verdana-Bold" size:19];

한글은 다른 폰트로 설정을 해도 영향을 받지 않는 것 같고 'AppleGothic'만 사용할 수 있는 것 같습니다. 
 

2. 컬러 설정

컬러는 UIColor의 'colorWith...' 류의 생성 메소드로 직접 생성할 수 있지만 아래와 같이 미리 지장된 색상을 간편하게 이용할 수도 있습니다.
UIColor *generalColor = [UIColor darkGrayColor];

UIColor에서 지정되어 있는 색상은 아래와 같습니다.
black, darkGray, lightGray, white, gray, red, green, blue, cyan, yellow, magenta, orange, 
purple, brown

색상설정은 set을 이용하여 간편하게 적용할 수 있습니다. 
[generalColor set]


3. drawAtPoint

지정된 위치에 문자열을 출력하는 간단한 메소드입니다. 반환값은 실제 문자를 출력한 크기입니다.
- (CGSize)drawAtPoint:(CGPoint)point withFont:(UIFont *)font

point에 출력될 위치를 font에 사용될 폰트를 지정합니다.  다소 복잡하지만 아래의 메소드도 많이 사용됩니다.
- (CGSize)drawAtPoint:(CGPoint)point 
forWidth:(CGFloat)width 
withFont:(UIFont *)font 
lineBreakMode:(UILineBreakMode)lineBreakMode

forWith는 문자열이 출력될 너비를 구합니다. fotWidth를 넘어 가는 문자들은 출력되지 않으며, lineBreakMode에 설정된 값에 따라 잘리는 옵션을 선택할 수 있습니다. 옵션은 아래와 같습니다. lineBreakMode의 옵션은 아래와 같습니다.

  • UILineBreakModeWordWrap - 단어 단위
  • UILineBreakModeCharacterWrap - 문자 단위
  • UILineBreakModeClip - 영역
  • UILineBreakModeHeadTruncation - 앞에 '...' 표시
  • UILineBreakModeTailTruncation - 뒤에 '...' 표시
  • UILineBreakModeMiddleTruncation - 중간에 '...' 표시

각 옵션의 결과는 아래의 샘플에서 확인하실 수 있습니다.


4. drawInRect

지정된 영역에 문자를 출력하는 메소드 입니다. 가로정렬이 가능하고 긴 문자열의 경우에는 여러줄에 걸쳐 출력을 할 수 있습니다.
- (CGSize)drawInRect:(CGRect)rect 
withFont:(UIFont *)font 
lineBreakMode:(UILineBreakMode)lineBreakMode 
alignment:(UITextAlignment)alignment

drawAtPoint와 동일하며 alignment의 옵션은 아래와 같습니다.
  • UITextAlignmentLeft - 좌측 정렬
  • UITextAlignmentCenter - 중앙 정렬
  • UITextAlignmentRight - 우측정렬

5. 출력전 크기 구하기 

출력전에 미리 출력될 문자열의 크기를 알아 낼 수 있는 'sizeWith...'류의 메소드들을 제공합니다. 출력시 사용하는 font와 width, lineBreakMode과 동일하게 설정하고 호출하면 출력될 텍스트의 실제 크기를 반환합니다.
- (CGSize)sizeWithFont:(UIFont *)font 
forWidth:(CGFloat)width 
lineBreakMode:(UILineBreakMode)lineBreakMode

drawInRect로 긴 문자열을 여러줄에 출력할 시에는 아래의 메소드를 호출해여 크기를 구해 와야 합니다.
- (CGSize)sizeWithFont:(UIFont *)font 
constrainedToSize:(CGSize)size 
lineBreakMode:(UILineBreakMode)lineBreakMode


6. 샘플

위의 메소드들을 이용해서 아래와 같이 간단한 예제를 만들어 보겠습니다. drawAtPoint의 breakMode별로 출력하고, 마지막에는 drawInRect를 이용하여 여러행에 걸쳐 출력하도록 하였습니다.
UIView 서브클래스의 drawRect에 아래와 같이 소스를 입력합니다.
- (void)drawRect:(CGRect)rect {
// 시작 x 좌표 
#define START_X        10

    /* 텍스트 설정 (from wikipedia) */
    NSString *title = @"Tiger"; 
    NSString *memo = @"The tiger (Panthera tigris) is a member of the Felidae family;" \
                      "the largest of the four big cats";

    /* 폰트 설정 */
    UIFont *titleFont = [UIFont fontWithName:@"Arial-BoldItalicMT" size:40];
    UIFont *memoFont = [UIFont fontWithName:@"ArialMT" size:16];

    /* 칼라 설정 */
    UIColor *blackColor = [UIColor blackColor];
    UIColor *blueColor = [UIColor blueColor];
    UIColor *redColor = [UIColor redColor];
    UIColor *userColor = [UIColor colorWithRed:0.2 green:0.4 blue:0.2 alpha:0.8]; 

    CGFloat yPosition = 10;
    CGFloat viewWidth = [self bounds].size.width;
    CGSize textSize;

    /* 타이틀 출력 */ 
    [blueColor set];
    textSize = [title drawInRect:CGRectMake(0, yPosition, viewWidth, 30)
                        withFont:titleFont 
                   lineBreakMode:UILineBreakModeWordWrap 
                       alignment:UITextAlignmentCenter];
    yPosition = (textSize.height + 20);
        
    int mode = 0;    
    NSArray* breakModeArray = [NSArray arrayWithObjects:@"WordWrap",
                               @"CharacterWrap",
                               @"Clip",
                               @"HeadTruncation",
                               @"TailTruncation",
                               @"MiddleTruncation",
                               nil];

    /* breakMode 설정별로 텍스트 출력 */
    [blackColor set];

    for (NSString *modeName in breakModeArray) {
        /* 현재 breakMode 출력 */
        [redColor set];
        textSize = [modeName drawAtPoint:CGPointMake(START_X, yPosition) 
                                forWidth:viewWidth 
                                withFont:memoFont 
                           lineBreakMode:UILineBreakModeWordWrap];
        yPosition += textSize.height;
        
        /* 텍스트 출력 */
        [blackColor set];
        textSize = [memo drawAtPoint:CGPointMake(START_X, yPosition) 
                            forWidth:viewWidth-80 
                            withFont:memoFont 
                       lineBreakMode:mode];
        yPosition += (textSize.height + 8);
        
        mode++;
    }

    /* drawInRect 타이틀 출력 */
    [redColor set];
    textSize = [@"* drawInRect" drawAtPoint:CGPointMake(START_X, yPosition) 
                                   forWidth:viewWidth 
                                   withFont:memoFont 
                              lineBreakMode:UILineBreakModeWordWrap];
    yPosition += textSize.height;

    /* memo를 drawInRect로 출력 */
    [userColor set];
    textSize = [memo drawInRect:CGRectMake(START_X, yPosition, viewWidth-80, 100) 
                       withFont:memoFont 
                  lineBreakMode:UILineBreakModeWordWrap];
}



출처 : http://blog.naver.com/PostList.nhn?blogId=hana_815¤tPage=31
Posted by 오늘마감

댓글을 달아 주세요

아이폰42010. 9. 9. 17:24
[아이폰] 아이폰4 수신률 저하 막는 방법

아이폰4가 출시되고 수신률 가지고 말이 많죠? 캘럭시S는 그걸 이용해 방어하는 것 같고 ㅋ

(그래도 갤럭시S의 설명서 보면 올바른 파지법이 나오더라는..;;)

여튼 아이폰4를 손으로 콱 움켜쥐면 전화 수신률이 떨어진다 해서, 스티브 잡스가. 그렇게 안잡으면

된다라고 말을 했다더라 라는 의역? 이야기도 돌고, 그래도 산다는 사람도 많고 여튼 나올때 마다

이래저래 탈이 많은 아이폰 입니다. ㅎㅎ

그래서 그런지 오늘은 아이폰4의 수신률 저하 방법이라는 이미지가 돌아다니더군요

바로..아래.

아이폰4에 전화수화기를 붙여버렸다는..(사용법이 상상 되시죠?)

역시 사람의 아이디어는 끝이 없나 봅니다. ㅋ



출처 : http://blog.naver.com/PostView.nhn?blogId=vador&logNo=80110338790
Posted by 오늘마감

댓글을 달아 주세요

XCODE2010. 9. 6. 00:28
아이폰 어플 개발의 필수인 XCode에서 디버깅하는 방법

디버깅


Friday Section 은 원래 비공개 강의라서 동영상 강의가 없다. 단 2009년 버젼에서는 pdf가 제공됨으로 그걸 토대로 실습해 본다.


1.XCode 인터페이스 살펴보기 - 팁, 트릭(trick), 유용한 세팅
2.문서들 - 어떻게 찾나
3.좋은 디버깅 방법 - NSLog 외의 방법 살펴보기
4.디버깅 실습


1. XCode 인터페이스 살펴보기


- 연습문제를 다운로드 한다 -

맥 초보인 나로써는 다운받은 zip파일이 어디있나 한참 헤메이다가
Macintosh HD > 사용자 > XXX(유저명) > 다운로드 에 있다는 것을 발견. ㅡㅡ;
XCode 프로젝트로 옮기고 싶은데 이번엔 프로젝트 폴더가 어딨는지 몰라서 방황하다가
Macintosh HD > 사용자 > XXX(유저명) > 도큐먼트 에 있다는 것을 발견하고
힘들게 마우스로 끓어담겨 옮겼다. ㅡㅡ;;;

그래서 결국 최종 폴더는
Macintosh HD > 사용자 > XXX(유저명) > 도큐먼트 > Section-1-Exercises

■ XCode Walkthrough
•Splitter-working 프로젝트를 연다.


•프로젝트가 정상적으로 실행되는지 Build-and-Go를 해 본다. => 시뮬레이터가 기동되면서 Split 화면이 나오면 OK.


■ Splitter 데모에서 확인 해 볼 수 있는 기능들
•splitter가 어떻게 작동하는지 보여준다.
•추천하는 세팅:
    XCode->Preferences->Text Editing->Show line numbers (라인 번호 표시)

    XCode->Preferences->Text Editing->Show page guide (페이지 가이드 표시)

   


    XCode->Preferences->Debugging->On Start:->Show Console (콘솔 표시)
    XCode->Preferences->Debugging->On Start:->Auto Clear Debug Console (자동으로 디버깅 콘솔 클리어하기)

   


•심볼 셀렉터를 보여준다.


•툴바 유저정의

참고문헌 - Xcode Workspace Guide

2.문서들 - 어떻게 찾나


■ 어떻게 찾나
• 개발에 필요한 문서들은 Xcode안에 포함되어 있다
• 찾기 위한 두가지 방법
    Browse
    Search


■ 문서 검색 데모
•Browsing
    Help->Documentation
    Doc Sets->Apple iPhone OS 2.2.1->Subscribe
    “iPhone Reference Library” 페이지로 이동한다.
    왼쪽 트리메뉴를 이용하여 필요한 문서를 찾아내려간다.
    초보자에게 아주 유용한 문서들:
        “Getting Started”
        “Guides”
        “Sample Code”


•Search
    Browsing은 새로운 개념을 공부하고자 할때 유용하며, 검색은 코딩중에 문서를 보고 싶을때 유용하다.
    splitter-working 프로젝트로 돌아가서 Controller.m을 살펴보자.
    NSString위에서 ctrl+클릭(원버튼 마우스) 혹은 오른쪽 클릭을 하면 메뉴가 뜬다.

        -> Find Selected Text In API Reference 를 선택하면 리퍼런스가 열린다.

    

    결과 필터링: 툴바의 All Doc Sets 대신 Apple iPhone OS 3.1 Library 를 선택한다.

 

    결과 필터링: 툴바의 참조 API 언어 옵션에서 C 와 Obj C 만 남겨두고 나머지 언어는 체크를 없앤다.


    리퍼런스를 둘러보며 자바 API 리퍼런스와 비교해 본다.
    ctrl-F for capital
    splitter-working 프로젝트로 돌아와서 resignFirstResponder가 무엇을 하는 기능인지 알아보라.


3.좋은 디버깅 방법


■ 두가지 디버깅 방법


•그렇게 멋지지 않은 디버깅 방법: NSLog
    몇몇 상황에서는 유용할 수도 있다... 아마도.
    변수들을 직접 조사하는것 보다 훨씬 불편하다.


•멋진 방법: 디버거(Debugger)
    버그 수정을 위한 가장 좋은 방법
    브레이크 포인트를 설정 한 후, 코드를 한줄씩 실행하며 변수들을 조사한다.

4.디버깅 실습

■ NSLog
    Controller.m 을 연다.
    NSLog를 이용하여 textField.text 값을 찍는다.
    실행한다 (Build and go)
    콘솔에서 로그를 확인 한다.


    => 문제없이 값을 확인 할 수 있지만 쓸데없는 코드를 적어줘야 한다.


■ Debugger
    다음 코드 부분에 브레이크 포인트를 설정한다. NSString *string = textField.text;
    실행한다. (Build and go)
    브레이크 포인터 이후는 한줄 씩 실행(Step over) 한다.
    변수위에 마우스를 올려놓으면 값이 팝업으로 뜨게 된다.
    디버그 윈도우를 이용하여 값을 알아볼수 있다.

■ 혼자 실습해보기
•Warmup-working 프로젝트를 실행하여 무엇을 하는지 알아보라.
•Splitter-working 프로젝트를 실행하여 무엇을 하는지 알아보라.
•6가지 연습문제를 아래의 방법으로 풀어보라:
    1) 프로젝트에서 Run 또는 Go 대신 Debug 로 실행한다.
    2) 어떤 에러가 뜨는지 확인한다.
    3) 어디서 에러가 나는지 찾아본다.
    4) 에러를 수정한다.
    5) 왜 에러가 났는지 이해한다.


■ 6가지 연습문제에 대한 힌트
•Warmup-exercise1
    매우 간단하게 에러를 찾아내서 수정 할 수 있을 것이다.
•Warmup-exercise2
    힌트 1: 디버거 윈도우(debugger window)를 살펴보라.
    힌트 2: 마지막으로 출력된 메세지를 살펴보라.
•Warmup-exercise3
    힌트 1: 디버거 윈도우(debugger window)를 살펴보라.
    힌트 2: API를 찾아보라.
•Splitter-exercise1
    힌트: XCode 내에서는 문제를 수정 할 수 없을 것이다.
•Splitter-exercise2
    힌트: 디버거 윈도우(debugger window)를 살펴보라.
•Splitter-exercise3
    힌트 1: 에러 메세지는 도움이 안된다.
    힌트 2: 마지막 강의에서 나온 프로퍼티와 메모리 관리에 대해 생각해보라.


■ Mac OS X 주요 단축키
•Mac OS X 초보자를 위한 팁:
    -x/c/v: cut/copy/paste
        ※ => 명령키
    -Space bar: spotlight
        spotlight를 통해 어프리케이션 실행, 계산, 파일 검색이 가능하다.
    w: 현재 윈도우를 닫는다.
    q: 현재 어플리케이션을 닫는다.
    ~: 다른 윈도우로 이동한다. Windows의 Alt+Tab과 동일한 기능
    -Delete: 파일 삭제 (휴지통으로 이동)


■ XCode 주요 단축키
•XCode 초보자를 위한 팁:
    Esc: 자동 완성
        클래스나 메소드, 변수등을 입력할때 사용 가능하다.
        시험삼아 “[NSString “ 를 입력한후 Esc를 누르면 NSString에서 사용 가능한 메소드 일람이 표시된다.
    Enter: Build and Go
    /: 커멘트화 또는 비 커멘트화 시킨다.
    }: 오른쪽으로 들여쓰기 (Indent right)
    {: 왼쪽으로 들여쓰기 (Indent left)
    ↑: 헤더/소스 파일간을 이동한다.
        = 옵션키




출처 : http://blog.naver.com/PostView.nhn?blogId=katchup00&logNo=10079461916
Posted by 오늘마감

댓글을 달아 주세요

아이폰 개발할때, 유저 정의하는 클래스 생성하는 방법

1. 유저 정의 클래스 생성하기
2. 오브젝트의 생명주기
3. Autorelease
4. Objective-C 속성(Properties)

1. 유저 정의 클래스 생성하기

클래스 디자인 하기

클래스 명을 정하고 슈퍼클래스를 정한다. 필요한 속성과 액션을 정의한다.


메소드(Methods), 셀렉터(Selectors), 메세지(Messages)의 차이와 복습

메소드는 오브젝트의 액션을 정의한 것이다.
- (NSString *)name
{
// 구현
}
- (void)setName:(NSString *)name
{
// 구현
}

셀렉터는 메소드를 참조하기 위한 이름이다. 콜론을 포함하지만 실제 파라메터나 타입은 포함하지 않는다.
SEL mySelector = @selector(name);
SEL anotherSelector = @selector(setName:);
SEL lastSelector = @selector(doStuff:withThing:andThing:);


메세지는 오브젝트의 셀렉터를 실행시키기 위한 방법이다. 필요에 따라 파라메터도 같이 적는다.
NSString *name = [myPerson name];
[myPerson setName:@“New Name”];


클래스 정의
(Public 헤더와 Private implementation)

.h 가 헤더이고 .m 이 소스 파일 이란것은 지금까지 해온 것이기 때문에 구지 다시 설명하지 않아도 될 것이다.

여기서 다시 한번 짚고 넘어 갈 부분은 자기 클래스의 메소드를 호출할때는 self를 사용하고,

슈퍼 클래스의 메소드를 호출할 때는 super를 사용한다는 것이다. self는 자바와 비교하면 자바의 this와 같은 개념이다.


<예>
[self doSomething]
[super doSomething]

2. 오브젝트의 생명주기(Object Lifecycle)

오브젝트의 생성에는 allocinit의 두 단계를 거친다. new는 alloc/init을 대신할수 있지만 별로 쓰이지 않는다.
왜냐하면 실 프로젝트에서는 init 대신 initWith라는 초기값을 가지는 (유저정의)초기화 메소드를 사용하는 경우가 더 많기 때문이다.

#import "Person.h"

@implementation Person
- (id)init {
    // allow superclass to initialize its state first
    if (self = [super init]) {
    age = 0;
name = @“Bob”;
// do other initialization...
}
return self;
}
@end

여기에서 나오는 [super init]은 꼭 불러줘야 하는 필수 사항이며 그 값을 다시 self에 넣는 것은
혹시 슈퍼 클래스에서 다른 인스턴스를 돌려주는 특수 케이스가 있을수 있기 때문이다.
즉, 그냥 필요한 소스라고 생각하고 이 방식을 따라 주면 된다.


여러가지 초기화 메소드를 구현하고 싶을때 우리는 아래와 같은 방법을 쓸 수 있다.

- (id)init;
- (id)initWithName:(NSString *)name;
- (id)initWithName:(NSString *)name age:(int)age;


더 구체적인 값을 가진 초기화 메소드를 다시 불러 주는 방법이다.
이는 위의 self = [super init]과 같은 코드를 반복적으로 적어줘야 하는 불편함을 줄여 준다.

- (id)init {
return [self initWithName:@“No Name”]; //initWithName을 호출
}
- (id)initWithName:(NSString *)name {
return [self initWithName:name age:0]; //initWithName:age:를 호출
}


■ 메모리 관리

 생성  파괴
 C malloc free
Objective-c alloc dealloc


생성과 파괴는 같은 횟수 일어나야 한다.
하지만 Objective-c에서는 직접 dealloc을 부르지는 않는다.


참조 횟수(Reference Counting)

모든 오브젝트는 취득 횟수(Retain Count)를 가지고 있다.
    - NSObject에 정의 되어 있음
    - 취득 횟수(Retain Count) > 0 일 경우, 오브젝트는 유효하며 살아있다.
+alloc 이나 -copy는 오브젝트를 생성하며 취득 횟수(Retain Count) == 1로 만든다.
-retain 은 취득 횟수(Retain Count)를 1 증가시킨다.
-release 는 취득 횟수(Retain Count)를 1 감소시킨다.
취득 횟수(Retain Count)가 0이 될 때 오브젝트는 파괴된다.
    - dealloc 이 자동 실행된다.
    - 한번 dealloc 되면 다시 참조는 불가능 해진다.


Balanced Calls (동일한 횟수의 생성/파괴)

Person *person = nil;

person = [[Person alloc] init]; //오브젝트 생성

[person setName:@“Alan Cannistraro”];
[person setAge:29];
[person setWishfulThinking:YES];

[person castBallot];

// person 오브젝트의 사용이 끝나면 release한다.
[person release]; // person이 파괴될 것이다.


참조 횟수의 증감(Reference counting in action)
Person *person = [[Person alloc] init]; //+alloc에 의해 1이 된다.
[person retain]; //-retain에 의해 2가 된다.
[person release]; //-release에 의해 1이 된다.
[person release]; //-release에 의해 0이 된다. -deallocl 이 자동호출 된다.


참조 횟수가 0이 되어 dealloc된 person오브젝트를 만약 여기에서 다시 호출한다면 프로그램 이상으로 종료 될 것이다.
[person doSomething]; // Crash!


고로 이를 방지하기 위해, release 된 후 person = nil; 이라는 문장을 삽입 한다면 비록 참조되더라도 프로그램이 죽지는 않는다.
앞에서 설명했듯이 Objective-c에서는 nil오브젝트의 메소드를 호출해도 에러가 돌아오지 않기 때문이다.


Person *person = [[Person alloc] init];
// ...
[person release]; // Object is deallocated
person = nil;
[person doSomething]; // No effect (에러가 나지 않는다)


-dealloc 메소드 구현하기
#import "Person.h"
@implementation Person
- (void)dealloc {
// 필요한 cleanup을 적는다.
// ...
// 마지막에 슈퍼클래스의 dealloc을 불러준다.
[super dealloc];
}
@end


정리하면,

    오브젝트는 참조 횟수 1로 시작된다.
-retain과 -release로 참조 횟수가 증감한다.
참조횟수가 0이 되면 오브젝트는 자동으로 파괴된다.
절대 dealloc을 직접 호출해서는 안된다.
-[super dealloc]은 예외.
alloc, copy, retain, release 만 이용해라.

오브젝트의 소유권

Person이라는 오브젝트가 name이라는 속성을 가진다고 해보자.
@interface Person : NSObject
{
NSString *name; // Person class “owns” the name
}
@end


.m 파일에서 setter를 만들때,

1.retain을 사용
- (void)setName:(NSString *)newName {
if (name != newName) {
[name release];
name = [newName retain];
// retain을 사용한다면 name의 참조횟수는 1 증가하게 된다.
}

}

2.copy를 사용

- (void)setName:(NSString *)newName {
if (name != newName) {
[name release];
name = [newName copy];
// 혹은 copy를 사용한다면 name의 참조횟수는 1이 되며, 소유권이 생긴다.
}

}


retain대신 copy를 사용하는 이유는, 만약 수정 가능한 스트링 타입(NSMutableString)을 retain으로 넘겨 받는다면
밖에서 누군가가 이 값을 수정하였을때 파라메터로 넘겨받은 값도 영향을 받기 때문이다.
이를 방지하기 위해 영향을 받고 싶지 않을 경우에는 copy를 쓰도록 한다.


인스턴스 변수의 해방(release)

유저 정의 클래스 에서는 dealloc을 정의하여 필요한 cleanup을 적어준다.

#import "Person.h"
@implementation Person
- (void)dealloc {
    // 필요한 cleanup을 적어준다.
[name release];

// 슈퍼 클래스의 dealloc을 불러준다. 필수!!!
[super dealloc];
}


3. Autorelease

케이스 1
- (NSString *)fullName {
NSString *result;
result = [[NSString alloc] initWithFormat:@“%@ %@”, firstName, lastName];
    return result;
}
Wrong: result is leaked!

생성한 오브젝트를 릴리스 해주는 코드가 없어 잘못된 코드이다.


케이스 2
- (NSString *)fullName {
    NSString *result;
result = [[NSString alloc] initWithFormat:@“%@ %@”, firstName, lastName];
[result release];
return result;
}
Wrong: result를 너무 빨리 릴리스 했기때문에 잘못된 코드이다.


케이스 3
- (NSString *)fullName {
    NSString *result;
result = [[NSString alloc] initWithFormat:@“%@ %@”, firstName, lastName];
[result autorelease];
return result;
}

Just right: autorelease를 사용하면 result는 릴리스 되지만 바로 릴리스 되는것이 아니라 사용이 끝나면 릴리스 된다.


오브젝트의 자동릴리스(Autoreleasing Objects)

autorelease를 사용하면 즉시는 아니지만 필요한 시간이 경과된 후 release 명령이 오브젝트로 보내진다.
오브젝트를 일정시간 유지하고 싶을 때 retain/release를 충족하기 위하여 autorelease를 이용한다.
메모리 관리가 매우 효과적이다.
가장 유용하게 사용되는 부분은, 메소드내에서 새로 생성한 오브젝트를 돌려줄때 이다.


메소드 명과 자동릴리스(Method Names & Autorelease)
alloc이나 copy를 이용하여 오브젝트를 생성 하였을 경우, 생성한 사람은 이를 반드시 릴리스 해주어야 한다.

NSMutableString *string = [[NSMutableString alloc] init];
// -release 또는 -autorelease를 반드시 불러줄 것!
[string autorelease];


그 외 메소드들은 autorelease 오브젝트를 돌려줄 것이다.
NSMutableString *string = [NSMutableString string];
// 여기서는 alloc/copy를 사용하지 않고 오브젝트를 생성하였기 때문에

// autorelease 오브젝트가 생성 되므로 아무것도 안해도 된다.


유저 정의 클래스를 만들 경우에도 이 룰을 따라,

메소드내에서 오브젝트를 생성하였을 경우엔 autorelease 오브젝트를 돌려주도록 한다.


Autorelease의 작동 원리

오브젝트는 현재 자동릴리스 풀(current autorelease pool)에 저장된다.
자동릴리스 풀(autorelease pool)은 오브젝트가 릴리스 될수있도록 스케쥴링 한다.
    - 풀(pool) 자체가 릴리스 될 때, 풀은 모든 소유 오브젝트에게 -release 명령을 보낸다.
UIKit은 자동으로 이벤트 관련 풀을 포함(Wrap)하고 있다.


<어플리케이션의 시작~종료>
App 시작 ---> App 초기화 ---> main nib 로딩 ---> 이벤트 발생 대기 상태 ---> 이벤트 처리 ---> App 종료


여기의 이벤트 발생 대기 ~ 이벤트 처리 사이에서 발생한 이벤트는 자동으로 autorelease 모드로 풀에 들어가게 된다.

 <- 원본 pdf에서 발최


Autorelease 오브젝트를 릴리스 되지 않게 유지하는 방법

앞에서 다룬 룰에 의하면 많은 메소드 들은 Autorelease 오브젝트를 돌려주게 된다.
이 오브젝트들은 풀에 저장되어 있다가 시간이 경과하면 릴리스 되는데, 이를 릴리스 되지 않게 유지하고 싶다면
릴리스 되기 전에 -retain을 해주면 된다.


name = [NSMutableString string];
// 여기서 name을 retain하여 유효하게 유지 하게 된다.
[name retain];
// ...
// 사용이 끝나면 마지막에 release 해주도록 한다. (또는 클래스의 -dealloc에서 릴리스 할 수도 있다.)
[name release];


Garbage Collection

Autorelease는 Garbage Collection이 아니다.
iPhone OS의 Objective-c는 Garbage Collection을 지원하지 않는다. => 메모리 관리를 해야 한다는 뜻.


4.Property

클래스의 프로퍼티 선언은 @property와 @synthesize를 이용하여 간략화 할 수 있다는 것을 이전 문법 공부에서도 알아봤다.
추가로 몇가지 나열하자면 property와 인스턴스 변수의 이름은 다르게 설정 할 수 있다.


@interface Person : NSObject {
    int numberOfYearsOld;
}
@property int age;
@end

@implementation Person

//numberOfYearsOld라는 인스턴스 변수의 Getter/Setter를 age이라는 이름으로 정의.
@synthesize age = numberOfYearsOld;
@end

실제로 Property 가 사용 되고 있는 곳

새로운 API들은 @property를 사용한다.
기존 API들은 getter/setter를 사용한다.
기본 API 보다는 주로 UIKit API에 빈번히 사용되고 있다.
어느쪽을 사용해도 의미는 똑같다.
    @property는 적어야 하는 코드의 양을 줄여주지만, 때로는 코드 내용이 명확하지 않게 느껴질수도 있다.


■ .(Dot) 문법과 self

@interface Person : NSObject
{
NSString *name;
}
@property (copy) NSString *name;
@end

위와 같이 Person 오브젝트에 name 이라는 인스턴스 변수가 있다고 가정 할 때,
우리는 self.name과 같이 .(dot) 문법을 사용할 수 있다.
하지만 여기서 self.name은 name을 직접 호출 하는 것이 아니라 name의 setter/getter 메소드를 통해 접근 하게 된다.


그래서 만약 setter 메소드를 만들때 아래와 같은 실수를 하게 된다면 무한 루프에 빠지게 된다.

@implementation Person
- (void)setAge:(int)newAge {
    self.age = newAge; //이 코드는 [self setAge:newAge]를 호출하게 됨으로 자기자신을 계속 부르는 무한 루프가 된다.
}
@end


■ 읽어야 할 문서들

• Objective-C 2.0 Programming Language
    “Defining a Class”
    “Declared Properties”
• Memory Management Programming Guide for Cocoa


이해를 돕기 위해 위 문서를 읽고 넘어가면 도움이 될 것이다.



출처 : http://blog.naver.com/PostView.nhn?blogId=katchup00&logNo=10078813140
Posted by 오늘마감

댓글을 달아 주세요

아이폰 어플 개발, 모델, 뷰, 컨트롤러의 생성과 연동하는 방법



모델, 뷰, 컨트롤러의 생성과 연동


1. HelloPoly라는 이름의 iPhone OS application의 “Window-Based Application” 을 생성한다.

2. 유저인터페이스를 배치한다.

3. 컨트롤러를 생성하고 UI element와 연동시킨다.

4. PolygonShape를 import 한후 컨트롤러와 연동시킨다.

5. 유저의 화면 조작에 의해 실행되는 action 메소드를 구현한다.

6. polygon 오브젝트를 초기화 시키는 awakeFromNib를 구현한다.

7. 화면 조작에 의한 결과를 값의 증감, 다각형의 형태에 반영시키도록 한다.
    • 증가 버튼을 누르면 그 결과에 따라 다각형이 변하도록 만든다.

8. 면(number of sides)의 값이 최소 또는 최대값에 다다르면 유저인터페이스의 요소들을 활성화 또는 비활성화 시키도록 한다.
    • 면(number of sides)의 값이 최소에 다다르면 감소 버튼을 비활성화 시킨다.
    • 면(number of sides)의 값이 최대에 다다르면 증가 버튼을 비활성화 시킨다.


<추가 Task>

• 화면에 다각형의 내각과 라디안을 표시하는 텍스트라벨을 추가한다.
• 사용할 수 있는 다각형의 최대, 최소 값 정보를 표시하는 텍스트라벨을 추가한다.
• 다각형 이름을 표시할 수 있는 텍스트라벨을 추가한다.


■ 튜토리얼 원문: HelloPoly Walkthrough

<개요>

코코아 터치 어플리케이션을 만들기 위한 스텝 바이 스텝 튜토리얼로, 과제B를 완성시키기 위한 힌트이다.

결국 만들고자 하는것이 아래 이미지와 같다는것을 염두에 두고 진행한다.
이 컨트롤러 오브젝트에 유저인터페이스 요소들과 연동되는 인스턴스 변수를 선언해야 한다.


새로운 Cocoa Touch 프로젝트를 생성한다:
1. 메뉴의 File > New Project… 를 선택.
2. iPhone OS Application을 선택한 후, Window-Based Application 템플렛을 선택한다.
3. 프로젝트 명을 ‘HelloPoly’로 지정한다.


Active SDK 설정하기

편의를 위해서 여기서는 iPhone Simulator를 사용하도록 한다.
iPhone 어플리케이션을 개발할때 개발자는 어떤 플랫폼을 대상으로 개발할 것인지 Xcode에서 설정해주어야 하는데
이 Active SDK를 변경하기 위해서는 메뉴의 Project > Set Active SDK에서 ‘Simulator - iPhone OS 2.0’를 선택한다.

이와 관련하여 편리한 ‘Overview’ 라는 툴바 팝업이 있다.
이것은 Active SDK 와 Build Configuration(주로 debug또는 release)을 동시에 설정하도록 해준다.
메뉴의 View > Customize Toolbar... 를 선택한후 툴바에 이 팝업을 추가하면
iPhone 어플리케이션을 개발하면서 SDK를 전환할때 편리하게 쓸수 있다.


중간점검: 빌드(Build) 와 테스트
이 프로젝트는 이미 Cocoa Touch application의 골격(skeleton)을 사용하여 만들어졌다.
툴바의 “Build and Go”를 눌러 어플리케이션이 시뮬레이터로 기동되는지 확인해보자.
여기서 사용하고 있는 템플렛은 가장 기본이 되는 공백뷰(empty view)만 있는 템플렛으로 나머지는 직접 추가해야 한다.
처음부터 컨트롤을 배치해주는 다른 템플렛들도 있는데 이것은 필요에 따라 다른 과제에서 사용해보도록 한다.


Interface Builder 사용하기
위에서 확인해본 공백뷰(empty view)는 MainWindow.xib 파일에 정의되어 있다.
xib(“interface file” 또는 “nib file” 이라고 불리운다) 파일은 인터페이스 빌더에서 설정/연결된 오브젝트 정보를 포함한다.
Xcode 프로젝트 템플렛은 일반적으로 실행시 “MainWindow.xib”라는 파일을 부르도록 설정되어 있으며
이 인터페이스 파일은 어플리케이션의 메인위도우나 다른 유저 인터페이스를 포함한다.
디자인 화면에서 xib 파일을 저장하면 오브젝트의 상태들이 이 파일에 저장된다.
런타임 환경에서는 xib파일이 로딩되어 저장되어 있던 오브젝트의 상태들이 다시 실제 오브젝트에 반영된다.
MainWindow.xib를 더블클릭하면 인터페이스 빌더가 기동될 것이다.
(인터페이스 빌더는 /Developer/Applications 에 있다.)


Tip: 인터페이스 빌더의 메뉴에서 (편의를 위해) 인터페이스 빌더 외의 다른 툴들은 숨기도록 설정 할수 있다.


인터페이스 빌더를 이용하여 아래 4가지 작업을 한다:

<순서>
1. 유저 인터페이스를 배치하고 설정한다.
2. 컨트롤러 클래스를 정의하고 인스턴스화 한다.
3. 유저 인터페이스와 컨트롤러를 연결한다.
4. 새로운 컨트롤러 클래스를 위해 소스 파일을 생성한다.

1. 유저 인터페이스를 배치하고 설정한다. +-----+-----+-----+-----+-----+

아래와 같은 유저 인터페이스를 만든다:


Library 윈도우는 윈도우에 드래그하여 배치할 수 있는 많은 오브젝트를 제공한다.
여기에는 미디어 리소스(이미지, 사운드등)에 억세스할수 있는 오브젝트도 있다.


1. Cocoa Touch Plugin아래 있는 오브젝트를 선택한다.
2. 두개의 push 버튼을 윈도우에 추가한다.
3. 두개의 텍스트 라벨을 윈도우에 추가한다.
하나는 왼쪽에 배치하여 “Number of sides”라고 표시하고 나머지 하나는 오른쪽에 배치하여 값을 표시한다.


Attributes Inspector:

메뉴의 Tools > Attributes Inspector 를 선택하면 석택한 아이템의 속성값을 표시할 수 있다.


라벨의 타이틀을 편집하려면 Attributes Inspector에서 Text값을 편집하던가 라벨을 더블클릭하여 직접 바꿀수 있다.

1. Attributes Inspector가 화면에 없다면 Tools > Attributes Inspector 을 선택하여 표시하도록 한다.
2. 화면에 배치한 텍스트 라벨을 선택한다.
3. 왼쪽 라벨에 “Number of sides:” 라고 표시한다.
4. 오른쪽 라벨은 “5”라고 표시한다 (여기서 사용할 디폴트 값)
5. 버튼의 표시 텍스트(title)를 바꾸기 위해 버튼을 더블클릭한다.
6. 왼쪽 버튼은 “Decrease”로 표시한다.
7. 오른쪽 버튼은 “Increase”로 표시한다.

2. 컨트롤러 클래스를 정의하고 인스턴스화 한다. +-----+-----+-----+-----+-----+

■ 컨트롤러 클래스를 정의해보자

컨트롤러 클래스는 화면의 두 버튼과 값을 표시할 텍스트 라벨의 참조를 위한 인스턴스 변수를 가진다.
이 참조는 outlet(콘센트) 이라고도 한다. 또한 버튼에 대한 액션 메소드도 만들어야 한다.


1. 라이브러리의 Cocoa Touch Plugin 아래에 있는 Controllers 그룹을 선택한다.
2. Object 아이템을 선택한다. 이 아이콘은 유저가 정의한 유저정의 오브젝트를 의미한다.


3. 오브젝트 아이콘을 인터페이스 도큐먼트 윈도우로 드래그한다.
4. 도큐먼트 윈도우의 Object 아이템을 선택한다.
5. 메뉴의 Tools > Identity Inspector 를 이용하여 인스펙터 윈도우를 표시한다.
6. Class 필드에 Controller 라고 입력한다. 도큐먼트 윈도우의 이름이 업데이트 된것을 확인한다.


또한 클래스에 outlet(콘센트)이나 액션을 추가하기 위해서는 Identity Inspector 를 이용한다.

outlet(콘센트)을 유저정의 클래스에 추가하는 방법은:
1. 컨트롤러 오브젝트를 선택한 상태로
2. Class Outlets 섹션에 아래와 같은 outlet과 type을 정의한다.

Outlet Type
numberOfSidesLabel UILabel
decreaseButton UIButton
increaseButton UIButton

3. Class Actions 섹션에는 두가지 액션을 추가한다. 처음 액션을 ‘increase’ 로 세팅하고 두번째를 ‘decrease‘로 세팅한다.


인스펙터는 다음과 같아질 것이다:

3. 유저 인터페이스와 컨트롤러를 연결한다. +-----+-----+-----+-----+-----+

컨트롤러 클래스의 정의가 끝났음으로 인터페이스 파일내에 인스턴스가 존재한다.
이제 유저 인터페이스와 컨트롤러의 연결을 설정해보자.


Outlet(콘센트)과 연결하기


우선 outlet과 연결해보자. outlet 은 오브젝트간의 참조라고 할수 있다.


컨트롤러에서 텍스트 라벨로의 연결을 설정하기 위해서는:
1. 도큐먼트 윈도우 안의 컨트롤러를 선택한다.
2. 메뉴의 Tools > Connections Inspector 을 이용하여 적절한 인스펙터를 표시한다.
Connections Inspector(연결 인스펙터)에는 모든 사용가능한 outlet과 액션이 선택되어져 있을 것이다.

3. outlet과 action들 옆에는 동그란 모양의 “connection circle” 이 있는데 이것을 ‘numberOfSidesLabel’ outlet 옆의
텍스트 라벨에 끌어온다. 여기서는 타입이 맞는 outlet과 object만 연결가능하다.(여기서는 UILabel)

4. 연결하고자 하는 곳의 끌어왔을때 선택가능한 부분이 반전될것인데 그때 마우스 버튼을 놓으면 된다.

5. 인스펙터는 연결이 확립되었을때 아래와같이 표현된다. 나머지 outlet에 대해서도 같은 작업을 반복한다.


런타임 환경에서 컨트롤러 오브젝트는 이 컨트롤에 대한 참조를 가지게 될 것이며 메세지를 전달(호출/실행)할수 있게 된다.


변경을 저장한다.


■ 버튼의 타켓과 액션을 설정한다


모든 컨트롤은 오브젝트에 대한 참조를 가질수 있는데 이것을 타켓이라고 부른다.
그리고 타켓에서 불리는 메소드를 액션이라고 부른다.
어플리케이션이 실행되면서 특정 이벤트가 발생할때 컨트롤은 타켓의 액션을 실행한다.
이 어플리케이션에서는 버튼을 컨트롤러에 연결시키고 버튼이 클릭되었을때 증가/감소 메소드가 실행되도록 해보자.


컨트롤의 연결을 확립시키는 방법은 바로 위에서 outlet을 설정한 방법과 매우 비슷하다.


1. Increase 버튼을 선택한다.
2. Connections Inspector 가 없다면 메뉴의 Tools > Connections Inspector 를 실행시켜 보이게 한다.
3. 인스펙터에는 컨트롤을 지원하는 이벤트 리스트가 보이는데 해당 동그라미를 클릭하여 드래그 할 수 있다.
여기서는 “Touch Up Inside”(컨트롤의 안쪽을 터치했다 떼었을때) 이벤트를 사용한다.
Touch Up Inside이벤트 오른쪽의 동그라미를 끌어다가 컨트롤 오브젝트에 연결한다. 여기까지가 타켓을 설정하는 방법이다.


4. 위에서 끌어다가 오브젝트에 연결시키기 위해 마우스 버튼에서 손을 떼면(release) 타겟에서 실행할 수 있는
액션 메소드가 팝업으로 표시된다. 여기서는 두가지 액션 메소드가 보일 것이다. increase 메소드를 선택한다.


이 부분이 액션을 설정하는 부분이다.
5. Decrease 버튼에 대한 타켓과 액션도 같은 방법으로 설정한다.


변경을 저장한다.


4. 새로운 컨트롤러 클래스를 위해 소스 파일을 생성한다. +-----+-----+-----+-----+-----+

Interface Builder안에 컨트롤러 클래스를 정의했지만 실제로 생성하는 Objective-c소스 코드를 적지 않았기때문에
이 단계에서 컴파일&실행을 하려고 하면 에러가 날 것이다.
왜냐하면 nib파일이 로딩 되었을때 컨트롤러 오브젝트가 생성 되어야 하는데 코드가 존재 하지 않기 때문이다.
시험삼아 실행해 보면 아래와 같은 에러를 볼 수 있을 것이다.
“Unknown class Controller in Interface Builder file.“


컨트롤러 클래스를 위한 소스를 적어주기 위해서는:
1. document window에서 Controller 오브젝트를 선택한다.
2. 메뉴의 File > Write Class Files... 를 선택한다.
3. Save 파넬이 나타날 것이다. 여기서 헤어파일도 같이 생성된다. 디폴트 세팅으로 저장한다.
4. 새로 만들 파일을 프로젝트에 추가할 것인지 묻는 다이얼로그가 나온다.
다이어로그에는 프로젝트에 정의된 모든 타겟이 나오는데 여기서는 HelloPoly밖에 존재 하지 않음으로 하나만 나온다.
HelloPoly를 선택하고 Add 버튼을 누른다.

Xcode로 전환되며 새로 만들어진 파일을 편집할 수 있게 된다.

nib파일의 모든 변경을 저장한다.

여기까지가 인터페이스 정의이다.

컨트롤러 클래스 살펴보기

Xcode로 돌아간다.
Controller.h 와 Controller.m가 프로젝트에 추가된 것을 확인 할 수 있다.

헤더 파일을 더블클릭하여 살펴보자.

Controller.h 파일은 다음과 같을 것이다:
#import
#import
@interface Controller : /* Specify a superclass (eg: NSObject or NSView) */
{
IBOutlet UIButton *decreaseButton;
IBOutlet UIButton *increaseButton;
IBOutlet UILabel *numberOfSidesLabel;
}
- (IBAction)decrease;
- (IBAction)increase;
@end


Objective-C는 C, C++, Java를 경험한 사람에게도 좀 특이하게 느껴질수 있다.
이전 강의를 통해 이것이 유저정의 클래스라는것을 알수 있지만 인터페이스 빌더로 부터 만들었기때문에
여기서는 아직 어떤 클래스를 계승받았는지 확정되어있지 않다.
슈퍼 클래스로서 NSObject를 지정하자.
@interface Controller : NSObject {


여기서 또한 우리가 지정한 outlet도 볼수 있는데 이는 인스턴스 변수로서 지정되어 있다. (UIButton * - 버튼에 대한 포인터)
런타임 실행시에 nib 파일이 로딩될 때 이 인스턴스 변수들은 우리가 인터페이스 빌더에서 설정한 연결에 따라 필요한 값을 갖게 된다.
즉, 오브젝트에게 메세지를 전달 할 수 있다는 뜻이다.

그러면 IBOutlet 키워드는 무슨 뜻일까.
IBOutlet 는 단순히 Interface Builder에게 주는 힌트이다.
이 인스턴스 변수들이 IB의 Connections Inspector에 표시 되어야 한다는 뜻이다.
이것은 컴파일 시에는 아무 의미 없는 키워드이다. (#defined를 살펴보면 아무것도 정의되어 있지 않다.)

여기에 increase 와 decrease 메소드도 정의되어 있는데 이것 또한 IBOutlet과 비슷한 IBAction 키워드가 사용된다.
이것은 이 메소드가 IB에서 target-action 연결을 설정할때 action메소드로서 표시되어야 한다는 뜻이다.
void의 동의어이다. Xcode에서 IBOutlet이나 IBAction을 더블클릭해보면 정의를 볼 수 있다.


다음은 Controller.m 을 열어보자:


Tip: 헤더파일과 implementation 파일사이를 점프할때는 오른쪽위의 아래와 같은 버튼(Go To Counterparts)을
누르면 번갈아가며 이동할 수 있다.
또한 메뉴의 Xcode > Preferences… > General > Open counterparts 를 이용하여 각기 다른 에이터 창이 아닌
하나의 에디터 창에서 번갈아가며 표시되도록 설정할 수 있다.


#import "Controller.h"
@implementation Controller
- (IBAction)decrease {
}
- (IBAction)increase {
}
@end


.m 파일에는  increase/decrease 액션 메소드에 대한 stub가 포함되어 있다.
인터페이스 빌더에서 버튼의 타겟으로 컨트롤러 오브젝트를 설정하였고 액션으로 이 메소드들이 설정되었다.
버튼이 클릭되었을때는 컨트롤러 오브젝트의 메소드가 실행 될 것이다.


중간점검: 로그, 빌드와 테스트

increase/decrease 메소드를 구현하기 전에 중간점검을 해보자.
각 메소드에 간단한 로깅을 적어 실행해본다.
NSLog(@“I’m in the increase method”);


버튼을 누르고 제대로 찍히는지 Run > Console에서 확인해 보자.

만약 여기서 제대로 동작하지 않는다면 인터페이스빌더의 target/action설정을 확인해 보도록 하라. (제일 틀리기 쉬운곳)


MVC모델의 M 구현하기

여기까지 우리는 MVC모델의 V와 C를 구현해 왔다. V는 인터페이스 빌더에서 만든 유저 인터페이스 였으며
C는 nib 파일에 정의된 컨트롤러 오브젝트이다.
컨트롤러는 outlet과 target/action을 통하여 뷰와 연결되어 졌다.
하지만 polygon은 어디에 위치해야 할까?
이것이 우리의 Model 부분이다. (M)

저번 과제에서 만든 Polygon 클래스를 사용한다.


Polygon 클래스를 Xcode 프로젝트에 추가한다:

1. Xcode의 메뉴에서 Project > Add to Project...를 선택한다.
2. Open 판넬에서 PolygonShape.h와 .m를 찾아 Shift키로 함께 선택한후 Add를 누른다.
3. 다음 창에서는 “Copy items into destination group’s folder (if needed)”를 체크하여 선택한 소스를 현재 프로젝트로 카피한다.


만약 체크하지 않는다면 외부 소스를 참조하기때문에 프로젝트를 이동하였을때 에러날 가능성이 있다.

여기서 polygon 오브젝트는 모델로 사용되기 때문에 다각형의 실제 정보를 담고 있다.
위에서 만든 컨트롤러는 유저 인터페이스를 업데이트 하기 위해 이 정보에 억세스 할수 있어야 하여
그러기 위하여 우리는 컨트롤러와 모델 사이의 연결을 확립시켜줘야 한다. 이부분이 다음 Task이다.


컨트롤러와 모델 사이의 연결 만들기

이 작업은 위에서 한 작업과 비슷하기 때문에 간단하게 순서만 나열해 보기로 한다.

1. Controller 클래스에 PolygonShape 타입의 인스턴스 변수를 선언한다.
(Controller.h 파일에 PolygonShape.h를 import해야 한다.)
인터페이스 빌더의 connections inspector에 나타나게 하기 위해서는 다른 인스턴스 변수들처럼 IBOutlet 키워드를 사용하여야 한다.

주의: IB를 기동하기 전에 Controller.h를 저장하지 않으면 connections inspector에 나타나지 않는다.

2. 새로운 유저정의 Object를 도큐먼트 윈도우에 추가한다. 클래스 명은 PolygonShape라고 준다.
(힌트: 이 과정은 Controller 클래스를 만든 방법과 동일하다.)

3. IB의 connections inspector 를 이용하여 PolygonShape 인스턴스와 Controller 인스턴스를 연결한다.


(힌트: connections inspector에 polygon outlet이 나타나있지 않는다면 Controller.h를 저장했는지 다시한번 확인해보라.)

4. nib파일을 저장한다.

중간점검: 빌드하고 실행하기

많은 작업을 해 왔기 때문에 여기서 이상이 없나 실행해본다.
이제 초기상태 설정과 increase/decrease 메소드를 구현하는 과정만 남았다.


초기상태 설정하기

초기상태를 설정하기 위해서는 polygon (다각형)의 최대값, 최소값, number of sides를 정하여 한다.
nib에서 자동 생성된 Controller와 Polygon 인스턴스에 값을 지정하기 위해서는 언제가 가장 좋은 시기인가.
우리는 두 오브젝트가 초기화 되고 Controller와 polygon의 연결이 성립된 타이밍을 알아야 하는데,
Cocoa Touch에서는 이 타이밍에 awakeFromNib라는 메소드가 불리도록 준비되어 있다.
nib의 모든 설정이 로딩되고 연결이 확립되면 각 오브젝트들의 awakeFromNib이라는 메소드가 호출된다.
유저정의 클래스에서 이 메소드를 구현하고 싶다면 여기에 원하는 작업을 아무거나 적어주면 된다.
이번 과제에서는 polygon 오브젝트의 최대/최소/number of sides를 적어줄 것이다.

awakeFromNib 메소드는 다음과 같이 적어주면 된다.

- (void)awakeFromNib {
// 여기에 polygon(다각형)을 정의한다.
}


최소/최대 값을 각가 3/12로 설정한다.
numberOfSides 를 설정하기 위해서는 UI의 text 라벨 값을 가져와야 한다.
awakeFromNib이 불리울때는 이미 모든 UI 요소들이 outlet으로 세팅 되어 있기 때문에 아래와 같은 소스로 불러올수 있다.
numberOfSidesLabel.text.integerValue


중간점검: Build and Run

중간 확인을 위해 awakeFromNib 메소드에서 polygon 오브젝트를 로그출력하여 number of sides값을 확인한다.
NSLog (@”My polygon: %@”, polygon);

Error: Cocoa/Cocoa.h No such file or directory. 라는 에러가 난다.

이유는 다른 프로젝트에서 카피해온 PolygonShape.h 에서 Cocoa.h를 import하고 있기 때문에.

저번 과제에서 잘 움직였는데 왜 여기서는?? 이라고 생각하며 검색해보니...

아이폰 어플리케이션에서는 cocoa.h를 import하지 않는다고 나온다.

cocoa.h의 import문을 빼고 컴파일하니 잘 된다. 이유는 나중에 나오겠지..


Action 메소드 구현

마지막 스텝은 increase/decrease 메소드를 구현하는 부분이다.
각 액션 메소드는 아래와 같은 방법으로 구현되어야 한다:

1. polygon의 number of sides를 가져온다.
2. number를 증가/감소 시킨다.
3. polygon에 증감시킨 새로운 number를 설정한다.
4. 새로운 상태를 유저 인터페이스에 적용한다.

4의 유저 인터페이스에 적용시키는 과정은 증/감 모두 같은 순서가 필요하다.
1. number of sides가 최소값에 다달았느냐 아니냐에 따라 decrease버튼을 비활성화 또는 활성화 시킨다.
2. number of sides가 최대값에 다달았느냐 아니냐에 따라 increase버튼을 비활성화 또는 활성화 시킨다.
3. number of sides의 현재 값을 text 라벨에 세팅한다.


이 부분은 여러 메소드에서 불리울수 있어야 하므로 아래와 같은 공통 메소드로 정의한다.

- (void)updateInterface {
// set interface state here
}


UI를 업데이트 하기 위한 힌트
• UIButton 을 활성화/비활성화 시키기 위해서는 “enabled” 속성을 사용하면 된다.
예: 버튼의 비 활성화
someButton.enabled = NO;

•“text” 속성을 이용하여 UILabel 값을 변경할 수 있다.
예: text 라벨에 숫자로 표시되는 문자값 표시하기.
someLabel.text = [NSString stringWithFormat:@”%d”, someNumber];

• UI의 초기상태를 설정하기 위하여 awakeFromNib에서도 같은 메소드를 사용하면 된다.


Build and Test
제대로 다 설정이 되었다면 시뮬레이터로 실행했을때 버튼을 눌러도 최소 3까지만 내려가고 최대 12까지만 올라갈 것이다.


Building for an iPhone or iPod touch
시뮬레이터에서 문제없이 돌아간다면 이제 실제 iPhone이나 iPod touch를 이용해본다.
개발자 프로그램에 등록되어 있다면(유료) Active SDK를 Device로 변경함으로써 간단히 인스톨/실행이 가능해진다.


디자인 리뷰

자, 우리는 MVC모델로 깔끔하게 디자인된 "진짜" iPhone 어플리케이션을 완성했다.
이 어플리케이션의 아키텍쳐와 지금까지 나온 용어들이 여기에 어떻게 들어맞는지 보기 위해 아래 다이어로그를 살펴본다.


완성된 Controller.m 소스

#import "Controller.h"

@implementation Controller

- (IBAction)decrease {

    NSLog(@"decrease method");

polygonObject.numberOfSides -= 1;

[selfupdateInterface];

}

- (IBAction)increase {

    NSLog(@"increase method");

    polygonObject.numberOfSides += 1;

[selfupdateInterface];

}

-(void)awakeFromNib {

polygonObject = [[PolygonShapealloc] initWithNumberOfSides:numberOfSidesLabel.text.integerValue minimumNumberOfSides:3maximumNumberOfSides:12];

NSLog(@"My polygon is: %@", polygonObject);

}

-(void) updateInterface {

if ([polygonObjectnumberOfSides] == [polygonObjectminimumNumberOfSides]) {

decreaseButton.enabled = NO;

} else {

decreaseButton.enabled = YES;

}

if ([polygonObjectnumberOfSides] == [polygonObjectmaximumNumberOfSides]) {

increaseButton.enabled = NO;

} else {

increaseButton.enabled = YES;

}

numberOfSidesLabel.text = [NSStringstringWithFormat:@"%d",[polygonObject numberOfSides]];

}

@end




출처 : http://blog.naver.com/PostView.nhn?blogId=katchup00&logNo=10076311904
Posted by 오늘마감

댓글을 달아 주세요