3. 발표자 소개
• 창원대학교 정보통신공학과 교수
• ivis lab, mobile-x 지도교수
• 2002년 BREW 플랫폼에서의 콘텐츠 개발
• 2004년 이후 WIPI 플랫폼, Windows Mobile
플랫폼에서의 콘텐츠 개발
• 2009년 이후 아이폰위주의 어플 개발
10. iOS 관련 교육경력
• 대학원 - Objective-C, iPhone Programming
• 학부 - 3개 과정 교육
• 특강
• KAIST, 부산대학교 아이폰 앱 개발 특강
• 동명대학교 게임공학과 아이폰 앱 개발
• 경남로봇진흥원 아이폰 개발자과정
• ETRI 전문가 초청세미나, ...
11. 교육
• 창원대학교 정보통신공학과 교과목 운
영
• 모든 수강생은 팀으로 앱을 개발하고
앱스토어에 올릴것, 사용자 평가와 판
매는 학점과 관계가 있음
• 2명의 앱 전문 디자이너와 공동작업
14. 아이폰 개발자되기
• 어떤 관문을 지나야 할까?
• 맥 OS X - 윈도우와의 철학 차이를 이
해 해야한다.
• 개발도구의 이해 - X Code라는 개발도
구의 기능과 특성을 이해해야 한다
• IB, Performance Tool, iOS Simulator의
이해
15. 아이폰 개발자되기
• 관문
• 개발언어 : Objective C라는 다소 생소
한 프로그래밍 언어를 개발언어로 사
용한다
• API의 이해 : Cocoa Touch API가 가지는
객체 지향성의 이해가 필요함
• 애플 앱스토어라는 마지막 관문이 존
재함
16. 지나치기 쉬운점
• 아이폰 앱 개발 교육 현황
• 지나치게 API 위주로 교육한다
• 기능을 익히는데 주력한다
• 애플의 운영체제와 개발언어를 대하는
철학을 이해하는 것이 먼저이다.
17. 왜 Objective C인가?
• C는 하드웨어를 직접제어하기 원하는
시스템 SW 개발자등을 위한 최선의 선
택이 된다
• C++는 객체지향 언어임에도 불구하고 C
에 구속적인 특성이 많다.
• C++는 비객체지향적 특성이 너무 많다
18. C++
Bjarne Stroustrup
http://imakeit.ibbun.com/blog/58 C++개발자
와의 인터뷰를 한번 보시길.. ^.^
19. Window Phone 7
• MS의 차기 모바일 OS로 사용
• Silverlight, XNA에 기반함
• C++을 사용하지 못함
• C# 만을 사용하여 개발함
20. Android
• 개발언어로 Java를 사용함
• 이제 모바일 플랫폼에서 C++의 입지는
점차 약해지고 있다
• 성능보다는 앱개발을 편리하게 하기
위한 선택
21. C++ vs Objective-C
• C++은 매우 불완전한 객체지향언어이다
• 특히 배우기가 너무 어렵다.
• friend function, 다중상속, 순수가상함수
의 문법적인 불완전성
25. Objective-C
• Smalltalk에 영향을 많이 받은 객체지향언
어(객체지향성이 강하다)
• C 언어의 superset이다
• 모든 객체는 동적이다
• 프로그램 실행중에 메모리를 할당받고
(alloc) 해지(release)된다.
• 메모리관리를 사용자가 해야한다
26. 또 다른 특징
• C++보다 문법적으로 단순하다
• 다중상속을 허용하지 않는다
• 모든 메소드는 public이다
• 클래스도 객체이다.(C++에서는 객체를
생성하는 설계도가 클래스님)
• 추가된 키워드는 @로 시작한다
27. 2.0에서 추가된 기능
• 가비지 콜렉터를 지원
• 모바일 프레임워크인 Cocoa Touch에서
는 지원하지 않음
• @property 지원
• 멤버 변수의 접근자를 자동으로 생성
• Fast enumeration 기능으로 집합적인 객
체내부의 원소를 하나하나 접근
28. 함수 vs 메소드
• 함수
• C의 함수는 Objective-C에서도 지원한
다
• 메소드
• 객체가 보내는 신호
• +,- 접두어로 정적메소드, 동적메소드
를구분한다
29. 함수 vs 메소드
• C++에서는 두개의 문법적 차이점이 크지 않다
• Objective-C에서 함수와 메소드는 매우 큰 차이
가 있다
• 함수 : 호출문에 의해서 호출되어 작업을 수
행하는 수행단위
• 메소드 : 클래스데이터 타입에 의존적인 함
수, 멤버함수라고도 하는데, 반드시 객체나 클
래스가 호출한다
32. @class와 @interface
• 클래스 선언은 Objective-C에서는
@interface라는 키워드로 한다.
• @class는 전치선언을 위한 키워드로 사
용된다.
• 전치선언(forward declaration)이란 다음
에 나타날 클래스가 어딘가에 정의되
어 있음을 표시하는 기능이다
56. CalculatorBrain.m 이것은 구현 파일이다.
public이나 private 구현부가 이
파일에 오게 된다 Model
#import “CalculatorBrain.h”
@implementation CalculatorBrain
@end
57. CalculatorBrain.m
Model
자기 자신의 헤더 파일을 가져와야 한다.
#import “CalculatorBrain.h”
@implementation CalculatorBrain
@end
58. CalculatorBrain.m
Model
#import “CalculatorBrain.h”
@implementation CalculatorBrain
구현부에서는 슈퍼 클래스를 지정하지 않
는다는 점에 유의하자.
@end
59. CalculatorBrain.m
Model
#import “CalculatorBrain.h”
@implementation CalculatorBrain 이번에는 세미콜론이 없다.
-(void) setOperand: (double) anOperand
{
<구현 코드는 여기에 오게 된다>
}
@end
66. 메소드 구문
- (NSArray *)shipsAtPoint:(CGPoint)bombLocation withDamage:(BOOL)damaged;
메소드 이름의 첫부분 메소드 이름의 두번째 부분
여기서 shipsAtPoint: withDamage: 가 메소드의 전체이름
- Objective-C는 메소드 이름이 두 부분, 세 부분,.. 이
될 수 있다.
- 두 번째 부분, 세 번째 부분을 각각 태그라고 하기도
한다
- 이상한가요?
68. 메소드 구문
- (NSArray *)shipsAtPoint:(CGPoint)bombLocation withDamage:(BOOL)damaged;
괄호 안에 첫번째 인자의 종류 괄호 안에 두번째 인자의 종류.
이 부분은 C의 구조체임. 이것 하나는 BOOL (부울 값)임.
69. 메소드 구문
- (NSArray *)shipsAtPoint:(CGPoint)bombLocation withDamage:(BOOL)damaged;
첫번째 파라미터 이름. 두번째 파라미터 이름
메소드 구현부에서 지역 변수처럼 사용할
수 있다.
70. 메소드 구문
- (NSArray *)shipsAtPoint:(CGPoint)bombLocation withDamage:(BOOL)damaged;
* 라인이 인자가 많거나 (또는 인수 이름이 길거나) 할경
우 라인을 바꾸면 :(콜론)으로 정렬됨 정렬선으로 XCode 에디터가
- (void)splitViewController:(UISplitViewController*)svc 자동정렬시킴
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)popoverController;
* 서술적인 메소드 이름으로 인해 메소드가 길어지지만
가독성이 높아지고 에러를 줄이는데 도움이 된다.
* 위의 메소드는 “분할 뷰 컨트롤러 svc가
aViewController를 숨기는데, 바 버튼으로 숨기며, 이
때 팝오버 컨트롤러를 사용한다”고 이해할 수 있음.
71. 메소드 구문
- (NSArray *)shipsAtPoint:(CGPoint)bombLocation withDamage:(BOOL)damaged;
IBAction은 사용하는 (void와 같음) 행동을 인터페이스 빌더에 알려주는 역할을 한다.
- (IBAction)digitPressed:(UIButton *)sender;
- (IBAction)digitPressed:(id)sender;
- (IBAction)digitPressed:sender; // (id)sender 버전과 동일함.
- (IBAction)digitPressed;
73. 인스턴스 메소드
• 대시(-)로 시작 보통사용하는
- (IBAction)digitPressed:(UIButton *)sender;
• 보통의 객체가 사용하는 “일반적인” 메소드임.
• 인스턴스 변수를 지역변수인것처럼 액세스 할 수 있다.
• 내부의 super와 self에게 메시지를 보낼수 있다.
• 예시
BOOL destroyed = [ship dropBomb:bombType at:dropPoint from:height];
74. 클래스 메소드
• +로 시작. 메모리 할당, 단일체 객체, 유틸리티에 사용
+ (id)alloc; // 리시버의 클래스의 개체에 대한 공간을 만든다. (항상 init과 쌍으로)
+ (id)motherShip; // 공유된 motherShip 인스턴스의 단일 객체만을 반환.
+ (int)turretsOnShipOfSize:(int)shipSize; // 정보유틸리티 메소드
• 인스턴스 변수의 내부는 액세스 할 수 없음.
• 호출 문법 (인스턴스 메소드와 약간 다름)
CalculatorBrain *brain = [[CalculatorBrain alloc] init];
Ship *theMotherShip = [Ship motherShip];
Ship *newShip = [Ship shipWithTurrentCount:5];
int turretsOnMediumSizedShip = [Ship turretsOnShipOfSize:4];
75. 리테인 카운터
• 모든 객체는 동적으로 할당된다
• 포인터를 이용하여 접근한다
• 자바와 C++, 그리고 Objective-C
76. 자바
• 객체의 메모리를 동적으로 만들어서 가비지
수집기가 소거시킨다
• Scanner scan = new Scanner(System.in);
• scan의 소거는 프로그래머의 몫이 아니다
• 가비지 수집비용
• 사용하지 않는 메모리의 소거를 프로그램
에게 위임한다?? 고비용, 저효율.
78. C++
• new를 통해 메모리를 할당 받으면, delete
를 통해 메모리를 해지시켜야한다.
• 다른 곳에서 이를 참조하고 있을경우 이
를 delete시키면?
• CRASH
• 이 메모리가 몇번 참조되고 있는지 알 수
없을까
• 알 수 없다???
79. Objective-C
• alloc을 통해 할당 받은 메모리는 release
를 통해 해지시켜야한다.
• 메모리관리는 효율적이지만, 가비지
수집은 프로그래머의 몫이다
• 이 메모리가 몇번 참조되고 있는지 알 수
없을까
• 알 수 있다!!!
80. 리테인 카운터
• 객체가 참조될 때마다 객체의 retain 메소
드를 호출하여 이 값을 증가시킨다.
• 참조가 해지되면 release를 통해 retain 값
을 감소시킨다.
81. 리테인 카운터
• 어떻게 작동하는가?
– 모든 객체가 준수해야할 매우 단순한 규칙들이 있다.
• 당신은 포인터를 유지하려는 객체에 대한 소유권을 갖는
다.
– 주어진 객체에 대한 다수의 소유자(공용)를 허용한다.
• 객체의 사용이 완료되면, 당신이 그 소유권을 포기해야한
다
• 아무도 객체에 대해 소유권을 주장안하면, 소거
(deallocate)된다.
82. 객체 소유권
• 언제 소유권을 가지는가?
– new, alloc, copy 메시지를 어떤 객체에 보내는 즉시
– 이들의 가장 일반적인 조합은 alloc 다음에 init되는
조합
– NSObject의 retain 메시지를 통해 리테인 카운터를
증가시킬것.
83. 임시 소유권
• 그럼 어떤식으로 "임시 소유권" 작업이 이루어지는가?
당신은 "옵션"을 가진 상태에서 객체를 이전해 주고 싶다면, 그것의 소유권을 위한
객체를 전송할적에 autorelease 메시지를 포함한 상태로 보내서 소유권을 해지시켜
야한다. 여러분의 객체 소유권은 미래의 시간에 (그러나 현재 이벤트가 완료되기 이
전에는 해지되지 않는한 해지되니 않음) "종료"된다.
• 예제
- (Money *)showMeTheMoney:(double)amount {
Money *theMoney = [[Money alloc] init];
}
우리는 지금 메서드 alloc을 사용하여
theMoney를 사용하고 있다.
우리는 이 객체를 release시킬 책임이 있다.
84. 임시 소유권
• 그럼 어떤식으로 "임시 소유권" 작업이 이루어지는가?
당신은 "옵션"을 가진 상태에서 객체를 이전해 주고 싶다면, 그것의 소유권을 위한
객체를 전송할적에 autorelease 메시지를 포함한 상태로 보내서 소유권을 해지시켜
야한다. 여러분의 객체 소유권은 미래의 시간에 (그러나 현재 이벤트가 완료되기 이
전에는 해지되지 않는한 해지되니 않음) "종료"된다.
• 예제
- (Money *)showMeTheMoney:(double)amount {
Money *theMoney = [[Money alloc] init];
return theMoney;
}
안타깝게도, 우리는 이 객체를 이미 반환했기 때문에,
우리는 지역적으로 선언된 객체를 release시킬 수 없다!
85. 임시 소유권
• 그럼 어떤식으로 "임시 소유권" 작업이 이루어지는가?
당신은 "옵션"을 가진 상태에서 객체를 이전해 주고 싶다면, 그것의 소유권을 위한
객체를 전송할적에 autorelease 메시지를 포함한 상태로 보내서 소유권을 해지시켜
야한다. 여러분의 객체 소유권은 미래의 시간에 (그러나 현재 이벤트가 완료되기 이
전에는 해지되지 않는한 해지되니 않음) "종료"된다.
• 예제
- (Money *)showMeTheMoney:(double)amount {
Money *theMoney = [[Money alloc] init];
[theMoney release];
return theMoney;
}
이러면 안된다 : 지역적으로 선언된 객체
를 만들자마자 release시키면 외부에서
쓸 수가 없다.
86. 임시 소유권
• 그럼 어떤식으로 "임시 소유권" 작업이 이루어지는가?
당신은 "옵션"을 가진 상태에서 객체를 이전해 주고 싶다면, 그것의 소유권을 위한
객체를 전송할적에 autorelease 메시지를 포함한 상태로 보내서 소유권을 해지시켜
야한다. 여러분의 객체 소유권은 미래의 시간에 (그러나 현재 이벤트가 완료되기 이
전에는 해지되지 않는한 해지되니 않음) "종료"된다.
• 예제
- (Money *)showMeTheMoney:(double)amount {
Money *theMoney = [[Money alloc] init];
[theMoney autorelease];
return theMoney;
}
해결 방법 : 이 메소드를 호출한 외부에서
theMoney가 retain되고 나면 release된
다.
87. 임시 소유권
• Autorelease Pool : 해지될 객체들이 임시
로 보관되는 곳
• 지역적으로 이 풀을 만들어서 관리하
면 효율적인 메모리 관리를 달성할 수
있다
88. 세터와 게터
• 세터(Setter)
• 설정자, 치환자라고도 한다
• 클래스 속성값을 설정하는 메소드
• 게터(getter)
• 클래스 속성값을 가져오는 메소드
89. 왜 필요한가
• 외부에서 하가된 방법으로 멤버의 값을
바꾸거나 읽어오기 위해 필요하다
• 멤버의 수가 증가하면 세터,게터의 수
도 증가하게 된다
91. 세터와 게터
• 자바의 예와 같이 엄청난 분량의 세터와
게터 함수를 개발자가 만드는 코딩을 대
체할 수는 없을까?
• 있다.
• @property를 이용하여 자동으로 setter,
getter를 만들자
92. 프로퍼티
• @property 키워드
• set/get 메소드를 개발자가 만드는 것이 아니라,
@property 지시문을 통해 컴파일러가 자동 생성한다
@interface MyObject : NSObject
{
@private
int eye;
}
// getter 메소드로 속성값과 이름이 같은 메소드를 사용할 수 있다
- (int)eye;
- (void)setEye:(int)anInt; // setter 메소드로 매개변수를 속성값으로 set
@end
93. 프로퍼티
• @property 키워드
• set/get 메소드를 개발자가 만드는 것이 아니라,
@property 지시문을 통해 컴파일러가 자동 생성한다
@interface MyObject : NSObject
{
@private
int eye;
}
@property int eye; // 앞의 명령과 동일함
@end
94. 프로퍼티
• @property int eye;는 다음과 같은 메소드를 생성한다
• @synthesize eye; 명령에 의하여 실제로 setter/getter를 생성
@implementation MyObject
- (int)eye {
return eye;
}
- (void)setEye:(int)anInt {
eye = anInt;
}
@end
95. 프로퍼티
• 컴파일러는 @synthesize 를 사용하여 setter/getter를 자동 구현함.
헤더파일 (.h):
@interface MyObject : NSObject
{
@private
int eye;
}
@property int eye;
@end
해당실행 파일(.m):
@implementation MyObject
@synthesize eye; // 아래의 코드를 자동생성하는 역할
@end
96. 프로퍼티
• 컴파일러는 @synthesize 를 사용하여 setter/getter를 자동 구현함.
헤더파일 (.h):
@interface MyObject : NSObject
{
@private
int eye;
}
@property int eye;
@end
해당실행 파일(.m):
@implementation MyObject
@synthesize eye; // 아래의 코드를 자동생성하는 역할
- (int)eye {
return eye;
}
- (void)setEye:(int)anInt {
eye = anInt;
}
@end
100. @property
• 반환자(getter) 메소드는 대개 인스턴스 변수를 직접 반환
• UILabel의 Text 속성을 생각해보자
display.text = [display.text stringByAppendingString:digit];
이것은 계속해서 display (UILabel)에 의해 소유된다.
우리는 그것을 계속 소유하지 않기 때문에 retain하지 않는다.
우리는 단지 다른 NSString을 stringByAppendingString로 부터
얻기 위해서만 사용할 것이다.
101. @property
• 예제(retain 옵션)
@property (retain) NSString *name;
@synthesize will create a setter equivalent to this ...
- (void)setName:(NSString *)aString
{
[name release];
name = [aString retain]; @synthesize는 (만일 존재한다면 nil이 될 수
} 있는) 이전 객체를 새로운 객체에 retain 할당
시키기 이전에 release시킨다는 점을 주목
102. 돌아가는 방식
obj.name = @”dongupak”; 명령문은
[obj setName:@”dongupak”]; 명령을 호출하고 설정
자가 호출된다
...
obj.name = @”new dongupak”;은
기존의 객체를 해지하고
[@”dongupak” release];
새 객체를 retain시킨 후 name이 참조하도록 함
name = [aString retain];
103. @property
• 예제(copy 옵션)
@property (copy) NSString *name;
@synthesize will create a setter equivalent to this ...
- (void)setName:(NSString *)aString
{
[name release]; copy 이전에 release시킴
name = [aString copy];
}
104. @property
• 예제(assign 옵션)
@property (assign) NSString *name;
@synthesize will create a setter equivalent to this ...
- (void)setName:(NSString *)aString
{
name = aString; 우리가 retain이나 copy를 하지 않았으므로
} 여기서는 release 되지 않음
105. 메모리 검사
• XCode를 이용하여 Objective-C 프로그램
을 짤적에는 메모리 누수검사가 매우 중
요하다
• Performance Tool을 잘 활용해야하는 이
유가 여기에 있다
109. 기타(id형)
• id 형
• NSObject *와 같은며 NSObject로 부터 상속받은 객체를 참조할
수 있는 매우 유용한 타입
• id* 와 같이 사용하면 이중 참조가 된다. 주의가 필요함
• NSObject에서 상속받은 모든 객체는 아래 메소드를 가지고 있다.
• isKindOfClass : 개체가 클래스의 한 종류인지 여부를 반환한다
(상속 포함).
• isMemberOfClass : 개체가 클래스(상속이 아닌)의 멤버인지 여
부를 반환한다.
• respondsToSelector : 객체가 특정 메소드에 응답하는지 여부를
반환한다
110. SEL
• 메소드 테스트 방법은 선택자(selector) SEL이다.
특별한 @selector() 지시자는 메소드의 이름을 선택자에 넣는다.
if ([obj respondsToSelector:@selector(shoot)]) {
[obj shoot];
}
• SEL은 선택자를 위한 특별한 Objective-C “타입”이다.
SEL shootSelector = @selector(shoot);
SEL moveToSelector = @selector(moveTo:);
타겟/액션 사용의 예 : [button addTarget:self action:@selector(digitPressed:)]
• 당신이 SEL을 갖고 있다면, 당신은 객체에게 수행을 요청할 수 있다.
NSObject에 있는 메소드 performSelector나 performSelector: withObject 사용
[obj performSelector:shootSelector];
[obj performSelector:moveToSelector withObject:coordinate];
111. nil도 객체이다
• 아무것도 가리키지 않는 개체의 포인터의 값
id obj = nil;
NSString *hello = nil;
• 원시타입은 “제로”처럼 간주할 수 있다
• NSObject는 제로로 모든 인스턴스 변수로 설정한다.
• 개체에 대한 포인터는 nil 인스턴스 변수로 설정
• Nil에게 메시지를 보내는것도 가능하다.
• 메소드는 값을 반환하는 경우, 그것은 제로를 반환
한다.
int i = [obj methodWhichReturnsAnInt]; // obj가 nil이면 제로가 될 것이다.
112. 프로토콜
• 다중상속이 허용되지 않는 상황에서 객
체가 필요로하는 메소드를 사용하기 위
한 방법
• < .. > 내부에 프로토콜 이름을 적는다
• Java의 interface와 매우 유사한 개념이다
113. 정리
• Objective-C는 객체지향성이 매우 강하다
• Objective-C는 기존의 개발자들이 많이 사
용해온 C/C++/Java/C#과 매우 다른 특징
이 많다
• 그러나 배우기 어려운 까다로운 언어는
분명히 아니다
• 새로운 철학을 먼저 이해해야만 한다.
114. 정리
• 기존의 개념으로 접근하기 보다는 마음
을 비우고 객체라 하는 일을 어떨해 효율
적으로하면 되는가를 생각하자.
• 까다로운 메모리 관리는 개발의 효율
성을 위한 것이다.
• 메모리 관리의 중요성은 아무리 강조
해도 지나치지 않다.
115. 조언
• 개발자들을 위한 새로운 삶이 열리게되
었다.
• 앱스토어, 맥 앱스토어, 윈도우 마켓플
레이스, 안드로이드 마켓.. 그리고...
• 새로운 개념을 즐거운 마음으로 받아들
이자