오브젝티브-c 핸드북 : 사전처럼 바로 찾아 바로 쓰는

120

Post on 22-Jul-2016

264 views

Category:

Documents


0 download

DESCRIPTION

하야시 아키라 지음 | 김훈, 강병우 옮김 | 임베디드 & 모바일 시리즈 _ 024 | ISBN: 9788992939072 | 32,000원 | 2012년 08월 24일 발행 | 856쪽

TRANSCRIPT

Page 1: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는
Page 2: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는
Page 3: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

사전처럼 바로 찾아 바로 쓰는

오브젝티브-C 핸드북

Page 4: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

4 5

CHAPTER 01 Objective-C 기초

SECTION-001 Objective-C란? ............................................................................22

SECTION-002 개발 환경 ........................................................................................25

SECTION-003 코드 구현 방법 .............................................................................31

SECTION-004 디버그할 때 편리한 기능 .......................................................34

SECTION-005 프레임워크 ....................................................................................39

SECTION-006 인스턴스의 생성과 소멸 ........................................................41

SECTION-007 Objective-C 클래스...................................................................45

SECTION-008 C 언어 코드와의 조합 ..............................................................47

SECTION-009 C++ 클래스 ...................................................................................51

SECTION-010 네임스페이스 ...............................................................................56

CHAPTER 02 Objective-C의 문법

SECTION-011 리터럴 ...............................................................................................60

SECTION-012 변수 ....................................................................................................63

SECTION-013 연산자 ..............................................................................................64

SECTION-014 상수 ...................................................................................................68

SECTION-015 주석 ....................................................................................................72

• 차 례 •

Page 5: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

4 5

SECTION-016 조건분기 ........................................................................................75

SECTION-017 반복문(루프) ................................................................................78

SECTION-018 전처리 지시자(preprocessor directive) ........................81

SECTION-019 클래스 정의와 메서드 정의 ..................................................84

SECTION-020 프로토콜 정의 .............................................................................91

SECTION-021 카테고리 정의 ..............................................................................98

SECTION-022 프로퍼티 정의 .............................................................................102

SECTION-023 예외 처리 ........................................................................................112

SECTION-024 블록 구문 ........................................................................................117

CHAPTER 03 오브젝트의 기초

SECTION-025 ‘id’ 타입 ...........................................................................................122

SECTION-026 ‘불변’ 클래스와 ‘가변’ 클래스 ...........................................126

SECTION-027 NULL과 nil ......................................................................................131

SECTION-028 인스턴스 비교하기 ....................................................................134

SECTION-029 키 밸류 코딩(KVC)으로 프로퍼티 접근하기................137

SECTION-030 값의 변화를 감시하기(KVO).................................................145

Page 6: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

6 7

CHAPTER 04 문자열

SECTION-031 문자열 ...............................................................................................152

SECTION-032 문자열의 비교 · 검색 옵션 ....................................................156

SECTION-033 문자열 생성하기 .........................................................................157

SECTION-034 포맷을 지정해서 문자열 생성하기 ..................................159

SECTION-035 텍스트 인코딩을 지정해 문자열 생성하기 ................161

SECTION-036 로컬라이즈 문자열 읽어오기 ..............................................166

SECTION-037 파일에서 문자열 생성하기 ...................................................169

SECTION-038 문자열을 파일로 저장하기 ...................................................173

SECTION-039 문자열의 길이 취득하기 ........................................................176

SECTION-040 문자열에서 문자 취득하기 ..................................................177

SECTION-041 문자열에서 문자열의 일부분 취득하기 ........................180

SECTION-042 처음과 마지막의 공백 문자 삭제하기 ............................182

SECTION-043 문자의 종류 판정하기 .............................................................185

SECTION-044 문자열 연결하기 .........................................................................188

SECTION-045 문자열 삽입하기 .........................................................................191

SECTION-046 문자열 일부분 삭제하기 ........................................................193

SECTION-047 문자열 비교하기 .........................................................................195

SECTION-048 대문자·소문자 변환하기 ......................................................199

SECTION-049 문자열을 수치로 변환하기 ...................................................201

SECTION-050 문자열을 지정한 문자로 분할하기 ..................................203

SECTION-051 문자열 해석하기 .........................................................................205

SECTION-052 문자열 검색하기 .........................................................................208

SECTION-053 캐릭터 세트를 지정해서 검색하기 .................................212

SECTION-054 문자열 치환하기 ........................................................................215

Page 7: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

6 7

SECTION-055 경로 문자열에서 파일명·디렉터리명 취득하기 .....218

SECTION-056 홈 디렉터리 취득하기 .............................................................221

SECTION-057 경로 문자열 정규화하기 ........................................................223

SECTION-058 문자열을 URL 인코딩·URL 디코딩하기 .....................225

CHAPTER 05 컬렉션

SECTION-059 컬렉션 ...............................................................................................228

SECTION-060 배열 생성하기 .............................................................................231

SECTION-061 가변 배열 생성하기 ..................................................................234

SECTION-062 배열 복제하기 ..............................................................................237

SECTION-063 사전 생성하기 ..............................................................................239

SECTION-064 가변 사전 생성하기 .................................................................242

SECTION-065 사전 복제하기 .............................................................................245

SECTION-066 세트 생성하기 ..............................................................................247

SECTION-067 가변 세트 생성하기 ..................................................................250

SECTION-068 세트 복제하기 ..............................................................................252

SECTION-069 인덱스 세트 생성하기 ............................................................254

SECTION-070 가변 인덱스 세트 생성하기 ..................................................256

SECTION-071 컬렉션의 오브젝트 수 취득하기 .......................................258

SECTION-072 배열에서 오브젝트 취득하기 ..............................................260

SECTION-073 배열에서 여러 개의 오브젝트 취득하기 ......................262

SECTION-074 사전에서 오브젝트 취득하기 ..............................................264

SECTION-075 세트에서 오브젝트 취득하기 ............................................267

SECTION-076 배열이나 세트에서 순서대로 오브젝트 취득하기 ..........................................................................................269

Page 8: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

8 9

SECTION-077 고속열거를 사용해 배열이나 세트에서 순서대로 오브젝트 취득하기 ............................................273

SECTION-078 배열에서 역순으로 오브젝트 취득하기 ......................275

SECTION-079 고속열거를 사용해 배열에서 역순으로 오브젝트 취득하기 ....................................................................278

SECTION-080 인덱스 세트에서 값을 순서대로 취득하기 .................280

SECTION-081 인덱스 세트의 값을 역순으로 취득하기 ......................283

SECTION-082 배열에서 오브젝트 검색하기 ..............................................286

SECTION-083 배열에서 로직을 구현해 오브젝트 검색하기 ...........288

SECTION-084 배열이나 세트에 오브젝트가 포함돼 있는지 조사하기 ........................................................................................294

SECTION-085 인덱스 세트에 값이 포함돼 있는지 조사하기 ..........296

SECTION-086 C 언어의 함수를 사용해 배열 정렬하기 ......................299

SECTION-087 각 오브젝트의 메서드를 사용해 배열 정렬하기 ....303

SECTION-088 블록을 사용해 배열 정렬하기 ...........................................306

SECTION-089 정렬 기술 클래스를 사용해 배열 정렬하기 ................309

SECTION-090 배열의 마지막에 오브젝트 추가하기 ............................315

SECTION-091 배열에 오브젝트 삽입하기 ..................................................317

SECTION-092 배열 결합하기 ..............................................................................320

SECTION-093 배열에서 오브젝트 삭제하기 ..............................................322

SECTION-094 배열에서 오브젝트 치환하기 ..............................................331

SECTION-095 배열에서 오브젝트 교체하기 ..............................................335

SECTION-096 사전에 오브젝트 추가하기 ...................................................337

SECTION-097 사전에서 오브젝트 삭제하기 ..............................................339

SECTION-098 세트에 오브젝트 추가하기 ...................................................343

SECTION-099 세트에서 오브젝트 삭제하기 ..............................................346

SECTION-100 인덱스 세트에 값 추가하기 ..................................................351

Page 9: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

8 9

SECTION-101 인덱스 세트에서 값 삭제하기 ............................................354

SECTION-102 인덱스 세트의 값 시프트 하기 ...........................................358

CHAPTER 06 수치

SECTION-103 수치 ....................................................................................................360

SECTION-104 수치를 포함한 ‘NSNumber’ 클래스의 인스턴스 생성하기 ....................................................................364

SECTION-105 범위를 포함한 ‘NSValue’ 클래스의 인스턴스 생성하기 ..................................................................368

SECTION-106 ‘NSValue’ 클래스의 인스턴스에서 범위 취득하기 ........................................................................................369

SECTION-107 좌표를 포함한 ‘NSValue’ 클래스의 인스턴스 생성하기 ..................................................................370

SECTION-108 ‘NSValue’ 클래스의 인스턴스에서 좌표 취득하기 .............................................................................371

SECTION-109 사이즈를 포함한 ‘NSValue’ 클래스의 인스턴스 생성하기 ..................................................................373

SECTION-110 ‘NSValue’ 클래스의 인스턴스에서 사이즈 취득하기 .........................................................................374

SECTION-111 사각형을 포함한 ‘NSValue’ 클래스의 인스턴스 생성하기 ..................................................................376

SECTION-112 ‘NSValue’ 클래스의 인스턴스에서 사각형 취득하기 ........................................................................378

SECTION-113 임의의 구조체를 포함한 ‘NSValue’ 클래스의 인스턴스 생성하기 ............................................380

SECTION-114 ‘NSValue’ 클래스의 인스턴스에서 임의의 구조체 취득하기 ........................................................382

SECTION-115 아핀 변환을 사용해 좌표 변환하기 .................................384

Page 10: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

10 11

CHAPTER 07 데이터

SECTION-115 데이터 ..............................................................................................388

SECTION-117 데이터 생성하기 .........................................................................391

SECTION-118 가변 데이터 생성하기 .............................................................393

SECTION-119 외부 메모리 블록을 사용한 데이터 생성하기 ...........395

SECTION-120 데이터 복제하기 ........................................................................398

SECTION-121 파일을 읽어들여 데이터 생성하기 ..................................400

SECTION-122 데이터를 파일에 저장하기 ...................................................403

SECTION-123 데이터의 길이 취득하기 ........................................................406

SECTION-124 데이터의 길이 변경하기 .......................................................408

SECTION-125 데이터에서 바이트 열 포인터 취득하기 ......................410

SECTION-126 데이터에서 바이트 열을 메모리 블록으로 복사하기 ........................................................................................413

SECTION-127 데이터 비교하기 .........................................................................416

SECTION-128 데이터에 바이트 열 추가하기 ............................................418

SECTION-129 데이터에 데이터 추가하기 ..................................................420

SECTION-130 데이터의 일부분 치환하기 ...................................................423

SECTION-131 시스템의 엔디언 취득하기 ...................................................426

SECTION-132 정수의 엔디언 변환하기 ........................................................428

SECTION-133 부동소수점수의 엔디언 변환하기 ...................................431

CHAPTER 08 날짜와 시각

SECTION-134 일시(NSDate) 오브젝트 ..........................................................436

SECTION-135 현재 일시의 오브젝트 취득하기 ......................................438

SECTION-136 특정 일시의 오브젝트 취득하기 .......................................439

Page 11: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

10 11

SECTION-137 특정 일시로부터 계산한 일시 오브젝트 취득하기 ..........................................................................................441

SECTION-138 일시 오브젝트에서 정보 취득하기 ..................................444

SECTION-139 일시를 문자열로 변환하기 ..................................................448

SECTION-140 포맷을 지정해서 일시를 문자열화하기 ........................451

SECTION-141 두 일시 비교하기 ......................................................................454

SECTION-142 두 일시에서 최근 일시 취득하기 .....................................456

SECTION-143 두 일시의 차 계산하기 ...........................................................458

SECTION-144 타임존 목록 취득하기 ............................................................461

SECTION-145 로컬 타임존 취득하기 ............................................................463

SECTION-146 타임존 이름 또는 생략표기로 타임존 취득하기 ..........................................................................................464

SECTION-147 그리니치 표준시와의 시차를 지정해서 타임존 취득하기 .........................................................................466

SECTION-148 로케일 식별자의 목록 취득하기 ......................................467

SECTION-149 로케일 취득하기 ........................................................................469

CHAPTER 09 파일 시스템과 입출력

SECTION-150 파일 경로와 URL .........................................................................472

SECTION-151 샌드박스 ..........................................................................................475

SECTION-152 URL 오브젝트 생성하기 ........................................................477

SECTION-153 파일 경로로 URL 오브젝트 생성하기 ............................479

SECTION-154 상대경로로 URL 오브젝트 생성하기 ..............................481

SECTION-155 URL 오브젝트에서 정보 취득하기 ..................................484

SECTION-156 파일에 부분적으로 기록하기 ..............................................486

SECTION-157 파일 임의의 위치에 기록하기 ...........................................489

SECTION-158 파일 크기 변경하기 .................................................................492

Page 12: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

12 13

SECTION-159 파일을 부분적으로 읽어오기 ..............................................494

SECTION-160 파일 임의의 위치에서 읽어오기 ......................................496

SECTION-161 번들 취득하기 .............................................................................498

SECTION-162 번들의 디렉터리 경로 취득하기 ......................................500

SECTION-163 번들의 리소스 파일 취득하기 ...........................................502

SECTION-164 번들의 리소스 파일 목록 취득하기 .................................504

SECTION-165 파일이나 디렉터리의 존재 여부 조사하기 ................506

SECTION-166 파일인지 디렉터리인지 조사하기 ...................................507

SECTION-167 파일이나 디렉터리의 정보 취득하기 .............................509

SECTION-168 파일이나 디렉터리의 정보 설정하기 ............................512

SECTION-169 디렉터리의 파일이나 디렉터리 취득하기 ...................515

SECTION-170 디렉터리 계층의 파일이나 디렉터리를 순서대로 취득하기 ..................................................................517

SECTION-171 디렉터리 생성하기 ....................................................................519

SECTION-172 파일이나 디렉터리 이동하기 ..............................................521

SECTION-173 파일이나 디렉터리 복사하기 ..............................................524

SECTION-174 파일이나 디렉터리 삭제하기 ..............................................527

SECTION-175 임시 디렉터리 취득하기 .......................................................529

SECTION-176 프로퍼티 리스트 파일 .............................................................531

SECTION-177 프로퍼티 리스트 파일 생성하기 .......................................533

SECTION-178 프로퍼티 리스트의 데이터 생성하기 ............................536

SECTION-179 프로퍼티 리스트의 데이터 읽어오기 .............................538

SECTION-180 클래스의 인스턴스 아카이브 하기 .................................541

SECTION-181 아카이브된 데이터에서 인스턴스 생성하기 ............543

SECTION-182 독자적인 클래스의 인스턴스 아카이브하기 ............545

SECTION-183 아카이브된 데이터에서 독자적인 클래스의 인스턴스 생성하기 ....................................................................549

Page 13: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

12 13

CHAPTER 10 XML

SECTION-184 XML 지원 ........................................................................................554

SECTION-185 이벤트 구동 방식으로 XML 읽어오기 ............................555

SECTION-186 트리 구조 방식으로 XML 읽어오기 .................................560

SECTION-187 XML 텍스트 데이터 생성하기 .............................................562

SECTION-188 루트 엘리먼트 취득하기 ........................................................565

SECTION-189 자식 노드의 개수 취득하기 ..................................................567

SECTION-190 자식 노드 취득하기 ..................................................................569

SECTION-191 인덱스 번호를 지정해서 자식 노드 취득하기 ...........571

SECTION-192 이전 노드와 다음 노드 취득하기 ......................................573

SECTION-193 부모 노드 취득하기 .................................................................575

SECTION-194 노드의 종류 취득하기 .............................................................577

SECTION-195 엘리먼트의 이름 취득하기 ...................................................579

SECTION-196 엘리먼트의 속성 취득하기 ..................................................581

SECTION-197 이름을 지정해서 엘리먼트 속성 취득하기 .................583

SECTION-198 텍스트 노드의 텍스트 취득하기 ......................................585

SECTION-199 새 XML 트리 생성하기 ...........................................................587

SECTION-200 텍스트 인코딩 지정하기 ........................................................589

SECTION-201 엘리먼트 생성하기 ..................................................................591

SECTION-202 엘리먼트의 속성 설정하기 ..................................................594

SECTION-203 텍스트 노드 생성하기 .............................................................596

SECTION-204 XPath를 사용해 노드 취득하기 .........................................598

SECTION-205 XQuery의 쿼리 실행하기 ......................................................600

SECTION-206 XQuery의 쿼리에서 외부 변수 사용하기 .....................602

Page 14: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

14 15

CHAPTER 11 클래스와 셀렉터

SECTION-207 인스턴스의 클래스 취득하기 ..............................................606

SECTION-208 클래스명 취득하기 ....................................................................607

SECTION-209 클래스명으로 클래스 취득하기.........................................609

SECTION-210 특정 클래스의 인스턴스인지 확인하기 ......................611

SECTION-211 셀렉터의 문자열 표시 취득하기 .......................................614

SECTION-212 셀렉터의 문자열 표시에서 셀렉터 취득하기 ............615

SECTION-213 인스턴스와 셀렉터에서 메서드 호출하기 ...................616

SECTION-214 오브젝트에서 임의의 타입의 파라미터와 반환값을 가진 메서드 호출하기 .......................................618

SECTION-215 메서드를 지연해서 호출하기 ..............................................622

SECTION-216 인스턴스에 특정 메서드가 있는지 확인하기 ............625

SECTION-217 부모 클래스에 특정 메서드가 있는지

확인하기 ........................................................................................627

CHAPTER 12 스레드와 타이머와 통지

SECTION-218 스레드와 타이머 .........................................................................630

SECTION-219 런루프 실행 ..................................................................................633

SECTION-220 타이머를 경유해서 메서드 호출하기 ............................635

SECTION-221 타이머를 경유해서 임의의 타입의 파라미터를 취득하는 메서드 호출하기 ......................639

SECTION-222 타이머 삭제하기 .........................................................................642

SECTION-223 스레드 생성하기 ........................................................................645

SECTION-224 현재의 스레드 중단하기 .......................................................650

Page 15: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

14 15

SECTION-225 스레드 잠시 중단하기 ............................................................654

SECTION-226 임의의 메서드를 큐에 등록해 실행하기 .....................657

SECTION-227 블록을 큐에 등록해 실행하기 ...........................................661

SECTION-228 커스텀 오퍼레이션을 큐에 등록해 실행하기 ...........664

SECTION-229 큐에 등록된 오퍼레이션 취소하기 .................................667

SECTION-230 락을 사용해 베타제어하기 ..................................................670

SECTION-231 재귀락을 사용해 배타제어하기.........................................675

SECTION-232 상태변수포함 락을 사용해 배타제어하기 ...................679

SECTION-233 ‘@synchronized’ 구문을 사용해 배타제어하기 ...............................................................................683

SECTION-234 현재의 스레드가 메인스레드인지 판정하기 .............687

SECTION-235 메인스레드에 메서드 호출 의뢰하기 .............................689

SECTION-236 통지(Notification) ......................................................................692

SECTION-237 통지하기 ..........................................................................................694

SECTION-238 통지받기 ..........................................................................................696

SECTION-239 스레드의 중단 통지받기 ........................................................700

CHAPTER 13 사용자 디폴트

SECTION-240 사용자 디폴트 ..............................................................................704

SECTION-241 사용자 디폴트에 설정값 저장하기 ..................................707

SECTION-242 사용자 디폴트에서 설정값 삭제하기 .............................710

SECTION-243 사용자 디폴트에서 설정값 읽어오기 .............................712

SECTION-244 사용자 디폴트에서 모든 설정값 취득하기 .................714

SECTION-245 사용자 디폴트의 초기값 설정하기 .................................717

Page 16: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

16 17

CHAPTER 14 가비지 컬렉션

SECTION-246 가비지 컬렉션 .............................................................................720

SECTION-247 커멘드 라인 툴에서 가비지 컬렉션 사용하기 ...........724

SECTION-248 가비지 컬렉션의 소멸처리를 수동으로 기동하기 ..........................................................................................727

SECTION-249 포인터 배열 생성하기 ............................................................730

SECTION-250 포인터 배열에 오브젝트 추가하기 ..................................732

SECTION-251 포인터 배열에 오브젝트 삽입하기 ..................................734

SECTION-252 포인터 배열에서 오브젝트 삭제하기 .............................736

SECTION-253 포인터 배열에서 ‘NULL’ 삭제하기 ..................................738

SECTION-254 포인터 배열 내의 오브젝트 치환하기 ............................740

SECTION-255 포인터 배열에서 오브젝트 취득하기 ............................742

SECTION-256 포인터 배열에서 배열 생성하기 ......................................744

SECTION-257 포인터 배열에서 엘리먼트 수 취득하기 ......................747

SECTION-258 포인터 배열에서 순서대로 오브젝트

취득하기 ..........................................................................................749

SECTION-259 해시 테이블 생성하기 ............................................................751

SECTION-260 해시 테이블에 오브젝트 추가하기 .................................752

SECTION-261 해시 테이블에서 오브젝트 삭제하기 ............................755

SECTION-262 해시 테이블 결합하기 .............................................................757

SECTION-263 다른 해시 테이블에 포함된 오브젝트 삭제하기 ..........................................................................................759

SECTION-264 해시 테이블에서 엘리먼트 수 취득하기 .....................761

SECTION-265 해시 테이블에 오브젝트가 포함되어 있는지 확인하기 ........................................................................................763

SECTION-266 해시 테이블에서 오브젝트를 한 개씩 취득하기 ........................................................................................765

Page 17: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

16 17

SECTION-267 해시 테이블에서 오브젝트를 전부 취득하기 ...........767

SECTION-268 맵 테이블 생성하기 .................................................................769

SECTION-269 맵 테이블에 오브젝트 추가하기 ......................................772

SECTION-270 맵 테이블에서 오브젝트 삭제하기 ..................................774

SECTION-271 맵 테이블에서 엘리먼트 수 취득하기 ..........................776

SECTION-272 맵 테이블에서 오브젝트 취득하기 .................................778

SECTION-273 맵 테이블에서 순서대로 키 취득하기 ..........................780

SECTION-274 맵 테이블에서 순서대로 오브젝트 취득하기 ...........782

SECTION-275 맵 테이블에서 사전 생성하기 ...........................................784

APPENDIX 실제 애플리케이션 개발

SECTION-276 UIKit을 활용한 iPhone 애플리케이션 개발 ................788

SECTION-277 AppKit을 사용한 Mac OS X 애플리케이션의 개발 ....................................................................................................819

찾아보기...........................................................................................................................................................................846

Page 18: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

18 19

• 이 책에 대해 •

� 개발환경

이 책은 다음과 같은 개발환경을 기준으로 합니다.

• OS: Mac OS X 10.7

• Xcode : 4.4

• iPhone SDK : 5.1

특별한 기재가 없으면 동작환경은 다음과 같고 특정 버전이 필요할 때는 그때마다 기재

하겠습니다.

• Mac OS X : Mac OS X 10.3.0 ~ Mac OS X 10.8

• iPhone OS : iPhone OS 2.0 이상

필자의 동작확인 환경은 다음과 같습니다.

• Intel : Mac OS X 10.8 / Xcode : 4.2 / iPhone OS 5.1

� 표기방법

이 책의 표기 방법에 대한 주의할 점은 다음과 같습니다.

f메서드의 종류

메서드의 종류인 ‘+’는 ‘클래스 메서드’를 의미하고 ‘–‘는 ‘인스턴스 메서드’를 의미합니다.

f클래스의 표기방법

여러 클래스에서 자주 사용하는 몇 개의 클래스는 클래스명이 아닌 클래스의 목적에 근거

한 이름으로 표기하기도 합니다. 이러한 클래스로는 다음과 같은 클래스가 있으니 확인하

기 바랍니다.

Page 19: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

18 19

클래스명 표기방법

NSString 문자열

NSMutableString 가변 문자열

NSArray 배열

NSMutableArray 가변 배열

NSDictionary 사전

NSMutableDictionary 가변 사전

NSSet 세트

NSMutableSet 가변 세트

NSIndexSet 인덱스 세트

NSMutableIndexSet 가변 인덱스 세트

NSPointerArray 포인터 배열

NSHashTable 해시 테이블

NSMapTable 맵테이블

f메서드 정의

메서드 정의에는 각 항목에서 사용하고 있는 메서드의 프로토타입 선언을 기재하고 있습

니다. 메서드의 반환값이나 각 파라미터의 타입을 확인하기 바랍니다.

f예제코드에서의 기호

이 책에 있는 예제코드는 지면상 하나의 예제코드가 여러 페이지에 걸쳐 있을 수 있습니

다. 이럴 때에는 기호로 하나의 코드임을 표시했습니다.

� 예제 파일 내려받기

이 책의 예제 파일은 아래 위키북스 홈페이지에서 내려받을 수 있습니다.

• http://www.wikibook.co.kr

Page 20: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

20 21

� 예제코드 이용방법

예제파일은 장별로 분류돼 있고 각 장의 폴더 내에 항목번호별로 폴더가 분류되어 있습니

다. COLUMN의 예제는 ‘항목번호-COLUMN’ 으로 되어 있습니다. 예제가 여러 개라면

뒤에 연번을 붙여 구분하고 있습니다. 예제파일은 ZIP 형식으로 압축되어 있으니 압축을

풀어서 사용하기 바랍니다.

각 폴더에는 프로젝트파일과 소스파일이 저장되어 있습니다. 확장자가 ‘.xcodeproj’인

프로젝트파일을 더블클릭해서 Xcode로 열어 왼쪽 위의 ‘Run(▶)’ 버튼을 클릭하면 프로그

램이 실행됩니다. 실행결과는 Xcode 중간 하단의 ‘콘솔’ 윈도에 출력됩니다.

Page 21: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

20 21

CHAPTER01Objective-C 기초

Page 22: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

22 23

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

SECTION-001 VER. 1.0 2.0

Objective-C란?

� Objective-C의 개요

Objective-C는 C 언어를 확장해 객체지향 언어에 필요한 기능을 추가한 객체지향 언어입니

다. Objective-C의 역사는 바야흐로 1983년까지 거슬러 올라갑니다. NeXTSTEP에 채용된

이후 지금은 Mac OS X이나 아이폰의 네이티브 애플리케이션을 개발하는 표준 언어로 사용

하고 있습니다.

f C 언어 기반의 언어

C 언어에 기반을 두고 있으므로 대부분은 C 언어로 작성한 코드를 그대로 사용할 수 있습니

다. 또한 C 언어로 작성한 함수를 직접 Objective-C의 코드에서 호출할 수도 있으므로 C 언

어에서 사용할 수 있는 라이브러리와 시스템 API를 Objective-C의 코드에서도 직접 이용할

수 있습니다.

f C++와도 함께 쓸 수 있음

Objective-C에서 한 발 나아가 C++ 코드를 호출할 수 있는 Objective-C++도 있습니다.

Objective-C++에는 몇 가지 예외가 있긴 하지만 C++ 코드를 거의 그대로 사용할 수 있습니

다. 또한 Objective-C++ 코드에서 C++ 클래스를 사용할 수도 있습니다.

f메서드의 파라미터에 라벨을 붙일 수 있음

메서드의 파라미터에 라벨을 붙일 수 있습니다. 이 기능 덕분에 나중에 봐도 프로그램 코드

를 마치 일반 영문처럼 쉽게 파악할 수 있습니다. C 언어나 C++는 함수를 호출하는 부분에

파라미터만 나열하므로 그 파라미터만 보고는 파라미터의 의미를 파악하기가 어렵습니다.

그러나 Objective-C에서는 처음 보는 코드라도 파라미터의 라벨만 보면 무엇이 파라미터로

지정됐는지 쉽게 의미를 파악할 수 있습니다.

f nil로 메시지 송신

Objective-C에서는 클래스 인스턴스에서 발생한 NULL을 ‘nil’이라고 표시합니다. Objective-C

에서는 nil 인스턴스로 메시지를 송신(메서드를 호출)해도 충돌이 발생하지 않으며 아무 동

작도 하지 않습니다. 그러므로 nil 검사를 할 필요가 없고 코드가 단순합니다. 단순한 코드

Page 23: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

22 23

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 1 Objective-C란?

는 파악하기도 쉽고 수정하기도 편합니다. 다만 Objective-C++ 코드에서는 C++ 클래스의

NULL 인스턴스로 메서드를 호출하면 일반적인 C++와 마찬가지로 충돌이 발생하므로 주의

해야 합니다.

f스마트 포인터

Objective-C의 클래스 인스턴스는 스마트 포인터로 되어 있습니다. 스마트 포인터는 참조 카

운터를 갖고 있으며 인스턴스를 처음 생성했을 때의 참조 카운터는 ‘1’입니다. 참조 카운터가

‘0’이 되면 그 인스턴스는 소멸합니다. 여러 곳에서 한 개의 인스턴스를 공유할 때는 참조 카

운터를 증감시킴으로써 인스턴스를 사용하는 동안에 인스턴스가 소멸하지 않게 할 수 있습

니다.

f가비지 컬렉션

Objective-C 2.0부터는 스마트 포인터 방식의 메모리 관리 모델 외에도 가비지 컬렉션을 사

용할 수 있습니다.

이 책을 쓰는 시점에서 확인한 결과 OS X 10.5 이후 버전부터 가비지 컬렉션을 사용할 수

있습니다. 가비지 컬렉션에는 참조 카운터가 없습니다. 가비지 컬렉션을 사용하면 인스턴스

가 사용되는 동안에는 소멸되지 않고 더 이상 사용되지 않을 때 자동으로 소멸됩니다. 이러

한 인스턴스 소멸이나 인스턴스가 현재 사용 중인지 확인하는 동작은 운영체제에서 자동으

로 수행합니다.

f autorelease

스마트 포인터 방식의 Objective-C 클래스 인스턴스는 ‘autorelease’ 메서드를 호출함으로써

자동으로 소멸되게 할 수도 있습니다. 소멸되는 시점은 이벤트 처리가 시스템으로 반환될 때

입니다. 더 정확하게 설명하면 인스턴스가 등록된 ‘NSAutoreleasePool’ 클래스의 인스턴스

가 소멸될 때 참조 카운터가 1 줄어듭니다. 시스템은 이벤트 처리가 시스템에 반환될 때 소멸

되는 ‘NSAutoreleasePool’ 클래스의 인스턴스를 갖고 있습니다. 따라서 메서드의 반환값으

로 클래스의 인스턴스를 반환하더라도 호출하는 쪽에서 소멸처리를 빠트리지 않았나 신경

쓰지 않아도 됩니다. 호출하는 쪽은 소멸되면 안되는 상황일 때만 참조 카운터를 증가시켜

소멸되지 않게 하고 필요 없어지면 참조 카운터를 감소시킵니다. 이때 다른 곳에서도 유지되

지 않아 참조 카운터가 ‘0’이 되면 인스턴스는 자동으로 소멸됩니다.

Page 24: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

24 25

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 1 Objective-C란?

f동적 타입 설정

Objective-C의 인스턴스와 클래스는 클래스 자신과 클래스가 가진 메서드, 부모 클래스의 정

보 등을 알고 있습니다. 그러므로 실행될 때 전달된 인스턴스 클래스는 무엇인지 이 메서드

는 지원하는지 등의 타입에 관한 정보를 얻을 수 있습니다. 그뿐만 아니라 인스턴스의 클래

스가 무엇인지와 관계없이 특정 메서드를 지원한다면 그 메서드를 호출할 수도 있습니다. 이

특성 덕분에 매우 유연하게 설계할 수 있습니다.

f프로퍼티

Objective-C 2.0 이후 버전부터는 프로퍼티를 언어 요소로 지원합니다. 프로퍼티는 조건을

충족하면 필요한 접근자 메서드를 자동으로 생성할 수도 있습니다. 생성된 접근자 메서드는

배타제어 1

가 필요한지, 읽기 전용 프로퍼티인지 여부 등을 유연하게 설정할 수 있습니다. 또

한 프로퍼티는 C 언어의 구조체와 같이 ‘.’ (도트) 연산자로 읽고 쓰지만 내부에서는 접근자

메서드가 호출되어 C 언어의 구조체처럼 간편한 읽기 쓰기 방식으로 유연하게 접근 제어를

할 수 있습니다.

f톨 프리 브리지(Toll-Free bridge)

Mac OS X이나 아이폰용의 프로그램을 개발할 때 상황에 따라 Core Foundation을 사용해

야 할 때가 있습니다. Core Foundation에서는 Objective-C가 아닌 C 언어의 API를 사용해

‘CFStringRef ’ 등의 독자적인 오브젝트를 사용하지 않으면 안 됩니다.

이럴 때 힘을 발휘하는 것이 ‘톨 프리 브리지’ 구조입니다. 톨 프리 브리지는 Objective-C 클

래스와 Core Foundation의 오브젝트를 ‘형변환’ 하기만 하면 서로 이용할 수 있는 구조입니

다. 예를 들어 ‘NSString’ 클래스의 인스턴스는 ‘CFStringRef ’의 오브젝트로 사용할 수 있고

반대로 ‘CFStringRef ’의 오브젝트는 ‘NSString’ 클래스의 인스턴스로 사용할 수 있습니다.

1  ( 옮긴이 ) 처리 중인 리소스를 다른 곳에서 공유 ·처리하지 못하도록 제한하는 동작

Page 25: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

24 25

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-002 VER. 1.0 2.0

개발 환경

� 개발 환경의 종류

Objective-C에서의 개발은 입력한 프로그램 코드를 Objective-C를 지원하는 컴파일러로

컴파일하고 프로그램을 빌드해서 실행하는 순서로 진행됩니다. 따라서 Objective-C를 지원

하는 컴파일러가 필요합니다. Objective-C를 지원하는 컴파일러는 Mac OS X에서는 Xcode

를 설치하면서 함께 설치됩니다. Mac OS X 이외의 환경에서 Objective-C를 사용하고자 할

때는 GNUstep이 있습니다. GNUstep은 Windows와 같은 Mac OS X 이외의 시스템도 지원

하며 설치하고 나면 Objective-C를 지원하는 컴파일러와 함께 필요한 라이브러리도 설치됩

니다.

� Xcode에 대해

Xcode는 Mac OS X상의 표준 통합 개발 환경입니다. Xcode는 소스 코드를 입력할 때 쓰는

텍스트 편집기, 소스파일을 컴파일해서 프로그램을 빌드하는 컴파일러와 링커, 프로그램을

디버그하는 데 쓰는 디버거 등의 기능을 갖추고 있습니다. 정확하게는 Xcode 자체는 컴파일

러와 링커의 프론트엔드로 구성되며 내부에는 커멘드 라인 툴의 컴파일러와 링커가 동작하

는 형태입니다. iPhone용 네이티브 애플리케이션을 개발할 때도 Xcode를 사용합니다.

f Xcode 설치

Xcode는 Mac OS X의 설치 디스크에 포함돼 있습니다. 또 최신 버전은 애플사의 앱스토어

에서 내려받을 수 있습니다. 여기서는 이 책을 쓸 때의 최신 버전인 Xcode 4.4를 사용합니다.

다른 버전을 사용하면 파일명과 문자열이 일부 다를 수도 있습니다. 이때는 사용하는 환경을

고려해 이 책을 참조하기 바랍니다.

Xcode 설치는 앱스토어에서 Xcode로 검색한 뒤 설치 버튼만 누르면 간단하게 설치가 자동

으로 진행됩니다.

설치를 완료하면 ‘/Developer/Applications’ 폴더에 Xcode가 설치됩니다. 이 폴더에는 그

밖에 개발에 유용한 프로그램들이 설치됩니다. 또한 Xcode나 컴파일러가 사용하는 파일 등

도 ‘/Developer’ 폴더에 설치됩니다.

Page 26: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

26 27

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 2 개발 환경

� 앱스토어에서 Xcode 설치

f Xcode의 프로젝트와 타겟

Xcode에서는 빌드하는 대상마다 ‘타겟’을 작성합니다. ‘타겟’은 ‘프로젝트’에 등록되어 관리

됩니다. 일반적으로 한 개의 프로그램마다 ‘프로젝트’를 작성하고 그 프로그램을 빌드하는 데

필요한 프로그램과 라이브러리를 ‘타겟’으로 프로젝트에 추가할 수 있습니다. 다만 ‘타겟’ 추

가가 필요한 경우는 소스코드를 기반으로 프로그램과 라이브러리를 빌드할 때입니다. 이미

빌드가 끝난 라이브러리나 프레임워크와 링크만 할 때는 ‘타겟’을 추가할 필요가 없습니다.

프레임워크와 라이브러리를 빌드하는 주체가 되는 ‘프로젝트’에서는 테스트 프로그램 등을

‘타겟’으로 쉽게 추가할 수 있습니다. ‘프로젝트’에서는 이렇게 개발할 때 동시에 빌드하는 게

효율적이며 동시에 빌드해야만 하는 것을 모아서 관리할 수 있습니다.

f Xcode 프로젝트 생성

프로젝트를 생성하는 방법은 다음과 같습니다.

1. [File] 메뉴에서 [New] [New Project] 를 선택합니다.

2. [New Project] 다이얼로그 박스에서 프로젝트 템플릿을 선택합니다. 이 책에 실린

예제코드는 GUI가 없는 커맨드라인 툴로 실행되므로 [Mac OS X] 그룹 안에 있는

[Applicaton] 카테고리의 [Command Line Tool]을 선택합니다.

Page 27: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

26 27

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 2 개발 환경

3. [Product Name]과 [Company Identi�er]를 입력하고 [Type]은 [Foundation]을 선

택합니다. ([Use Automatic Reference Counting]은 Xcode 4.2부터 도입된 새로운 메

모리 관리 기능인 ‘Automatic Reference Counting’ 을 사용할지의 여부입니다).

4. [Next] 버튼을 클릭한 뒤 저장을 위한 다이얼로그에서 프로젝트를 저장할 장소를 선

택한 후 [Create] 버튼을 클릭합니다.

5. 저장하면 지정한 장소에 프로젝트명과 똑같은 이름의 폴더가 생성되고 그 폴더에 프

로젝트 파일(확장자 ‘.xcodeproj’ )과 기본형의 소스파일이 생성됩니다.

참고로 2번에서 선택한 템플릿 카테고리와 이름은 Xcode의 버전에 따라 달라집니다. 위에

표기된 부분은 Xcode 4.4일 때입니다. 또한 3에서 선택한 [Type]은 Xcode 3보다 하위 버전에

는 존재하지 않습니다

f프로젝트에 파일 추가

컴파일할 소스파일과 헤더 파일은 프로젝트에 추가해야 합니다. 새 파일을 생성해서 추가할

때는 [File] 메뉴의 [New] [New Project] 를 선택합니다. 기존의 소스 파일을 추가할 때는

[File] 메뉴의 [Add Files to “프로젝트명”]을 선택합니다.

f빌드와 실행

프로젝트에 등록한 소스파일의 컴파일 및 프로그램을 빌드할 때는 [Product] 메뉴의 [Build]

를 선택합니다. 에러가 발생하면 에러가 발생한 행의 왼쪽에 붉은 점이 표시되고 붉은 점을

클릭하면 행의 오른쪽에 이슈 내용이 표시됩니다. 메인화면 왼쪽의 [Issue navigator]를 보면

발생한 에러들이 이슈로 리스팅된 것을 볼 수 있습니다(에러가 없으면 표시되지 않습니다).

프로그램을 실행할 때는 메인화면 왼쪽 위의 [▶(Run)] 버튼을 클릭하거나, [Product] 메뉴

의 [Run] 을 선택합니다. 커맨드라인 프로그램은 실행결과가 메인화면 아래의 [Output] 윈

도우에 출력됩니다.

f디버거의 기본조작

‘브레이크 포인트’와 메인화면 하단의 ‘Debug area’에서 프로그램을 디버깅할 수 있습니다.

프로그램을 특정 줄에서 일시 정지시키려면 ‘브레이크 포인트’를 설정합니다. ‘브레이크 포인

트’를 설정하려면 Xcode에서 소스파일을 표시하고, ‘브레이크 포인트’를 설정할 줄의 왼쪽을

클릭해 ‘브레이크 포인트’ 아이콘이 표시되게 합니다. ‘브레이크 포인트’를 삭제하고 싶을 때

Page 28: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

28 29

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 2 개발 환경

는 표시된 ‘브레이크 포인트’ 아이콘을 아이콘이 표시되는 영역 밖으로 드롭하면 됩니다. 또

일시적으로 ‘브레이크 포인트’의 작동을 막고 싶을 때는 ‘브레이크 포인트’ 아이콘을 클릭해

서 색상이 연한 상태가 되게 합니다. 이 상태에서는 ‘브레이크 포인트’가 있는 줄이 실행되어

도 일시 정지되지 않습니다. 일시 정지한 프로그램의 소스를 한 줄씩 실행하거나, 변수값을

확인할 수 있습니다. 일시 정지한 프로그램의 소스는 ‘Debug area’의 [Step Over]를 실행하면

한 줄만 실행됩니다. [Step In]을 실행하면 실행하려고 하는 메서드의 내부로 들어가고 [Step

Out]을 실행하면 현재 실행 중인 메서드를 호출 한 코드로 이동합니다.

� 브레이크 포인트가 유효한 상태

� 브레이크 포인트가 무효인 상태

Page 29: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

28 29

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 2 개발 환경

� GNUstep

GNUstep은 Cocoa나 OpenStep과 소스차원의 호환성을 가진 개발환경입니다. 소스차원의

호환성이란 같은 소스파일이 Cocoa와 GNUstep 어느 쪽 환경에서도 대체로 수정하지 않고

컴파일할 수 있음을 의미합니다. GNUstep은 오픈소스로 제공되어 Windows나 Linux 등 다

양한 시스템에서 동작합니다. GNUstep에는 Objective-C로 개발할 때 필요한 컴파일러나 라

이브러리, 헤더 파일 등이 포함돼 있습니다. GNUstep은 GNUstep.org에서 내려받을 수 있

습니다. 사용할 때는 라이선스 조항을 잘 확인한 후 개발하려고 하는 프로그램에서 사용해도

문제가 없는지 검토하기 바랍니다.

f GNUStep 설치

Windows 버전의 설치 방법을 소개합니다. Windows 버전의 GNUStep은 컴파일러나 쉘 등

의 툴과 라이브러리 파일, 헤더 파일로 구성되어 있습니다. GNUstep.org에서 다음 4가지를

내려받아 순서대로 설치하기 바랍니다.

• GNUstep System

• GNUstep Core

• GNUstep Devel

• Cairo Backend

f홈 디렉터리

기본설정으로 설치하면 구동드라이브의 루트디렉터리에 ‘GNUStep’ 폴더가 생성됩니다.

‘GNUStep’ 폴더에 ‘home’ 폴더가 만들어지며 ‘home’ 안에 사용자별 ‘홈 디렉터리’가 생성

됩니다. ‘홈 디렉터리’는 처음 ‘쉘’을 구동했을 때 생성되고 ‘쉘’은 ‘스타트’ 메뉴에 생성된

‘GNUstep’ 내의 바로가기를 선택해서 구동합니다. 이 책의 예제코드를 실행할 때는 ‘홈 디렉

터리’에 폴더를 생성해서 그 안에 소스파일과 Make 파일을 만들기 바랍니다.

fMake 파일의 생성

GNUstep을 사용해서 빌드할 때는 소스파일과 같은 폴더에 Make 파일을 생성합니다. 텍스

트 편집기로 소스파일과 같은 폴더에 ‘GNUmake�le’이라는 이름의 파일(확장자는 필요 없

음)을 만들고 파일 내용은 다음과 같이 하기 바랍니다.

Page 30: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

30 31

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 2 개발 환경

f빌드

빌드는 [Shell]에서 실행합니다. 먼저 [스타트] 메뉴에 생성된 [GNUstep] 안의 [Shell]을 선택

해 쉘을 엽니다. 그다음 ‘cd’ 명령을 사용해 ‘GNUmake�le’을 작성한 폴더로 이동한 후 ‘make’

라고 입력합니다. make 명령을 실행하면 소스파일이 컴파일되어 프로그램이 빌드됩니다. 빌

드에 성공하면 ‘obj’ 폴더가 생성되며 ‘obj’ 폴더에 프로그램이 저장되므로 ‘쉘’에서 프로그램

명을 입력해 실행하기 바랍니다.

관련 항목 fff

• 코드 구현 방법 ····························································· p.31

include $(GNUSTEP_MAKEFILES)/common.make

TOOL_NAME = TestTool # 작성할 프로그램 이름

TestTool_OBJC_FILES = main.m # TOOL_NAME에 지정한 프로그램에서

# 사용할 소스파일 지정

# 여러 개를 지정할 때는 스페이스로

# 구분

include $(GNUSTEP_MAKEFILES)/tool.make

Page 31: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

30 31

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-003 VER. 1.0 2.0

코드 구현 방법

� 소스파일의 작성

코드 구현을 할 소스파일은 다른 프로그래밍 언어와 마찬가지로 텍스트 편집기나 Xcode 등

의 통합개발환경(IDE)으로 작성합니다. 익숙한 텍스트 편집기가 있다면 익숙한 텍스트 편집

기를 사용해도 되지만 통합개발환경에서 작성하는 방법을 추천합니다. Xcode 등의 통합개

발환경에서는 코드작성뿐만 아니라 빌드나 디버그도 할 수 있어 효율적으로 개발할 수 있습

니다.

� 확장자

Objective-C의 확장자는 ‘.m’입니다. Objective-C++에서는 ‘.mm’을 사용합니다. C 언어처럼

헤더 파일도 사용합니다. 헤더 파일의 확장자는 ‘.h’입니다.

� 텍스트 인코딩

사용할 수 있는 텍스트 인코딩은 컴파일러에 따라 결정됩니다. Mac OS X에서는 일반적으로

GCC가 사용되므로 임의의 텍스트 인코딩을 선택할 수 있습니다. Windows나 Linux 등 다른

플랫폼용 프로그램과 공유해서 사용 중인 소스파일이라면 그 플랫폼에 맞춰서 인코딩을 선

택할 수 있습니다. 또한 개인적인 경험에 따르면 Mac OS X에서는 UTF-8(BOM 없음)이 별

다른 문제가 없었으므로 UTF-8을 추천합니다. Windows 버전의 프로그램과 공유해서 사용

하는 소스파일 등에서 EUC-KR을 사용할 수도 있으나 매우 드물게 정확히 인식되지 않을 때

도 있었습니다.

f한국어

UTF-8이나 EUC-KR, KS_C_5601-1987 등 한국어를 지원하는 텍스트 인코딩을 사용하면

주석에 한국어를 사용할 수 있습니다. 하지만 문자열로서 직접 한국어를 전달하면 UTF-8 이

외의 인코딩에서는 문자가 깨져 보입니다.

프로그램에서 한국어를 사용하고 싶을 때는 로컬라이즈 문자열을 읽어오는 방식을 이용해

서 실행할 때 파일에서 직접 읽어들이는 방법을 사용하기 바랍니다.

Page 32: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

32 33

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 3 코드 구현 방법

프로그램 코드를 구현할 때 신경 써야 할 부분 중 하나는 ‘코드의 간결함’입니다. 간결한 코드는

나중에 읽어도 이해하기 쉽고 보기가 좋아서 유지보수가 간편합니다. 복잡한 처리를 구현할 때는

코드가 복잡해지기 쉬우니 신경 써서 깔끔하게 작성하도록 노력해야 합니다. 프로그래밍에 최적

화된 편집기는 자동 들여쓰기 기능은 물론이고 코드를 깔끔하게 해주는 기능이 많이 포함돼 있습

니다.

Objective-C 코드를 구현할 때 필자는 Xcode를 사용합니다. 예전에는 Xcode를 빌드와 디버그

에만 사용하고 코드를 구현할 때는 프로그래밍 전용 텍스트 편집기를 사용해 왔습니다.

하지만 지금은 Xcode의 ‘구문에 따른 들여쓰기 기능’ 이 매우 편리해서 Xcode만 사용합니다. 구

체적으로 설명하자면 다음과 같은 Objective-C의 메서드 구문에 따른 들여쓰기 기능을 알고 나

서는 Xcode로 갈아타게 되었습니다.

[anObject setParameter:param

withOwner:self];

이 코드는 단순히 ‘anObject’라는 인스턴스의 ‘setParameter:withOwner:’ 메서드를 호출하

는 코드입니다. 이때 Xcode로 코딩하면 두 번째 줄의 ‘:’를 입력했을 때 자동으로 첫 번째 줄의

setParameter 뒤의 ‘:’와 두 번째 줄 ‘withOwner’ 뒤의 ‘:’를 가지런히 들여쓰기 처리해줍니다. 코

드에서 Xcode가 메서드라고 인식하지 못했을 때나 ‘]’를 입력한 줄 밖에 들여쓰기가 처리되지 않

은 때에도, 줄 중간의 파라미터 라벨보다 앞에 탭을 입력하면 자동으로 ‘:’이 가지런히 들여쓰기

처리됩니다.

‘구문에 맞춘 들여쓰기 기능’을 적용하려면 다음과 같이 설정하면 됩니다.

1. [Xcode] 메뉴에서 [Preferences] 항목을 선택합니다.

2. [Preference] 윈도의 상단 카테고리에서 [Text Editing]을 선택하고 그 아래에 있는

[Indentation]을 선택합니다.

3. [Syntax-aware indenting]의 체크박스에 체크합니다.

4. [X]를 클릭해 윈도를 닫습니다.

COLUMN 깔끔한 코드 구현

Page 33: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

32 33

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 3 코드 구현 방법

‘On’ 으로 설정

관련 항목 fff

• 개발환경 ·································································· P.25

Page 34: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

34 35

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

SECTION-004 VER. 1.0 2.0

디버그할 때 편리한 기능

� 디버그할 때 편리한 기능

Xcode가 내부적으로 사용하는 GDB 디버거는 디버그할 때 편리한 기능을 갖추고 있으며

Foundation에도 편리한 로그 출력 함수가 있습니다. 이번 섹션에서는 디버그 효율을 크게 개

선하는 기능을 소개하겠습니다.

f GDB 기능 호출

Xcode의 ‘콘솔’ 윈도를 사용하면 GDB에 직접 명령어를 전달해서 실행할 수 있습니다. 그러

자면 먼저 ‘브레이크 포인트’나 일시 정지 버튼을 눌러 프로그램을 일단 정지시킵니다. 이 상

태에서 ‘Debug area’가 나타나게 하면 ‘Output’ 윈도우에 ‘(gdb)’라고 표시되고 그 밑의 줄부

터 직접 입력할 수 있습니다. 이 상태에서 명령을 입력하면 입력된 명령어가 GDB에 전달됩

니다.

fObjective-C의 인스턴스 문자열 출력하기

‘po’ 명령어를 사용하면 Objective-C 인스턴스의 문자열을 출력할 수 있습니다. 출력되는 문

자열은 ‘description’ 메서드의 반환값입니다. 예를 들어 ‘NSString’ 클래스의 인스턴스를 실

행하면 인스턴스가 가진 문자열이 출력됩니다. ‘NSArray’ 클래스의 인스턴스라면 배열에 들

어 있는 인스턴스 전체의 ‘description’의 반환값이 출력되므로 디버그 도중에 배열의 내용을

조사할 수 있습니다. 독자적으로 작성한 클래스에서도 ‘description’ 메서드를 구현하기만 하

면 지원되므로 필요에 따라 구현하면 디버그할 때 매우 편리합니다.

Page 35: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

34 35

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 4 디버그할 때 편리한 기능

f변수의 내용을 출력하기

‘int’ 등의 변수 내용을 출력할 때는 ‘print’ 명령을 사용합니다. 형변환도 사용할 수 있습니다.

이 함수는 나중에 소개할 메서드 호출과 함께 사용하면 편리합니다.

f GDB상에서 메서드 실행하기

디버그할 때 위력을 발휘하는 기능 가운데 하나가 ‘Output’ 윈도에서 디버그 중인 프로그램

의 Objective-C 메서드를 직접 호출하는 기능입니다. 메서드의 반환값이 Objective-C의 인스

턴스일 때는 ‘po’ 명령어와 함께 사용하고 Objective-C의 인스턴스가 아닐때는 ‘print’ 명령어

와 함께 사용합니다.

예를 들면 다음과 같은 코드를 봅시다.

- (NSArray *)doSomething:(int)value

{

NSArray *newArray = [self createSomething:value];

return newArray;

}

- (NSArray *)createSomething:(int)value

{

NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:0];

if (value > 0)

{

for (int i = 0; i < value; i++)

{

[newArray addObject:[NSNumber numberWithInt:i]];

}

}

else

{

for (int i = value; i < 0; i++)

{

[newArray addObject:[NSNumber numberWithInt:i]];

}

}

return newArray;

}

이 코드에서 ‘return’이 들어간 줄 (네 번째 줄)에서 일시 정지한다고 했을 때 이 상태에서 변

수 ‘value’에 ‘10’이란 값이 들어 있을 때 ‘newArray’의 내용을 알고 싶다면 다음과 같이 입력

합니다.

Page 36: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

36 37

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 4 디버그할 때 편리한 기능

po [self createSomething:10]

위 코드를 실행하면 ‘createSomething’ 메서드에 ‘10’을 전달해 그 결과가 ‘po’ 명령어에 의

해 ‘콘솔’ 윈도에 출력됩니다.

<NSCFArray 0x100111920>(

0,

1,

2,

3,

4,

5,

6,

7,

8,

9

)

다음으로 변수 ‘newArray’의 엘리먼트 개수를 알고 싶을 때는 다음과 같이 입력합니다.

print (int)[newArray count]

위 코드를 실행하면 ‘count’ 메서드가 실행되고 반환값이 ‘int’ 타입으로 형변환되어 ‘콘솔’

윈도에 출력됩니다.

$1 = 10

f특정 메서드에서 일시 정지

‘b’ 명령어를 사용하면 특정 함수나 메서드에서 일시 정지를 할 수 있습니다. 다음 예에서는

‘NSLog’ 함수에서 일시 정지하게 설정했습니다.

b NSLog

입력하고 나면 다음과 같이 출력되면서 브레이크 포인트가 설정됩니다.

Breakpoint 2 at 0x7fff847fb28f

출력된 ‘Breakpoint’ 뒤의 ‘2’는 ‘2번째 브레이크 포인트’라는 의미입니다. 다음 예에서는

‘drain’ 메서드에서 일시 정지하게 설정했습니다. ‘drain’ 메서드는 ‘NSAutoreleasePool’ 클래

스의 메서드입니다.

Page 37: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

36 37

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 4 디버그할 때 편리한 기능

b drain

입력하고 나면 다음과 같이 출력되면서 브레이크 포인트가 설정됩니다.

Breakpoint 3 at 0x7fff847ad267

fObjective-C에서 예외가 발생했을 때 일시 정지

‘콘솔’ 윈도우에 다음과 같이 입력하면 프로그램에서 예외가 발생했을 때 일시 정지하게 설정

할 수 있습니다.

b raise

GDB 버전에 따라서 ‘NSException’만으로 멈출지를 선택할 수 있는 표시가 나옵니다. 그러

한 경우는 ‘NSException’을 사용하기 바랍니다. Xcode 3.2.5와 함께 설치된 GDB에서는 선택

할 수 없으며 다음과 같이 출력됩니다. .

Breakpoint 4 at 0x7fff829ad863

f ‘브레이크 포인트’의 리스트 표시

설정된 ‘브레이크 포인트’는 ‘Breakpoint navigator’ 윈도에 목록으로 표시됩니다. ‘브레이크

포인트‘ 윈도에서 필요 없는 ‘브레이크 포인트’는 삭제할 수도 있으며 ‘b’ 명령어로 설정한 ‘브

레이크 포인트’도 이 윈도에서 삭제할 수 있습니다. [View] 메뉴에서 [Navigators] 항목의 하

위 메뉴인 [Show Breakpoint Navigator]를 선택하면 표시됩니다.

Page 38: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

38 39

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 4 디버그할 때 편리한 기능

GDB상에서 메서드를 실행하는 기능을 이용해 중간 파일을 출력하면 디버그할 때 작업 효율이 매

우 높아집니다. 예를 들면 ‘NSDictionary’ 클래스의 내용을 알고 싶을 때는 ‘po dict’를 이용하면

내용을 표시할 수 있지만, 내용이 복잡하거나 등록된 데이터의 수가 많을 때는 이 방법으로는 작

업 효율이 떨어집니다. 그래서 이럴 때는 메서드 실행 기능을 사용해 프로퍼티 리스트 파일로 작

성하고 ‘Property List Editor’나 텍스트 편집기로 살펴보는 편이 좋습니다. 예를 들면 GDB 콘솔에

다음과 같이 입력해 봅시다.

print (int)[dict writeToFile:@"/data.plist" atomically:YES]

위와 같이 입력하면 변수 ‘dict’가 ‘/data.plist’에 프로퍼티 리스트 파일로 작성됩니다. 디버그 중에

내용이 자주 바뀔 때에도 파일명을 바꿔가면서 작성한 뒤 ‘Property List Editor’나 텍스트 편집기

로 비교해보면 값의 변화를 신속하게 확인할 수 있어 작업 효율이 매우 높아집니다

COLUMN 중간 파일의 출력

Page 39: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

38 39

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-005 VER. 1.0 2.0

프레임워크

� 프레임워크

Mac OS X에서 프레임워크란 라이브러리의 오브젝트코드, 헤더파일, 프레임워크의 정보파

일과 그 밖에 필요한 리소스 파일을 한데 모아둔 폴더입니다. Mac OS X에서는 이런 폴더를

‘번들’이라고 부릅니다. 번들에는 정해진 규칙이 있어서 그 규칙에 따라 오브젝트 코드나 헤

더 파일이 있습니다. 또 번들 폴더에는 확장자가 있습니다. Mac OS X에서는 애플리케이션

도 하나의 번들이지만 Finder에서는 폴더가 아닌 하나의 파일로 표시됩니다. 이런 번들을 패

키지라고 부릅니다.

Obejctive-C에서 문자열이나 컬렉션 등의 클래스는 ‘Foundation’ 프레임워크에서 제공합

니다. 이 ‘Foundation’ 프레임워크와 그 밖의 Mac OS X 시스템 API를 제공하는 프레임워크

를 한데 모아 ‘Cocoa’라고 부릅니다. iPhone OS에서도 ‘Foundation’ 프레임워크가 제공되며

그 밖의 iPhone OS의 시스템 API를 제공하는 프레임워크를 한데 모아 ‘Cocoa Touch’라고

부릅니다.

‘Foundation’ 프레임워크 이외에 대표적인 프레임워크로는 ‘AppKit’ 프레임워크가 있습니

다. ‘AppKit’ 프레임워크는 메뉴바나 윈도우, 버튼 등의 컨트롤 같은 사용자인터페이스에 관

련된 기능을 제공합니다. 이미지에 대한 기능이나 처리도 ‘AppKit’ 프레임워크에서 제공합니

다. ‘Cocoa Touch’에서는 ‘AppKit’ 프레임워크가 제공되지 않고 대신에 ‘UIKit’ 프레임워크

가 제공됩니다.

번들 및 패키지의 확장자는 다음 표를 참조하기 바랍니다.

번들·패키지 확장자

애플리케이션 .app

프레임워크 .framework

플러그인 .plugin

커널 확장 .kext

범용 번들 .bundle

f프레임워크 설치 디렉터리

프레임워크는 ‘Frameworks’ 디렉터리에 설치됩니다. ‘Frameworks’ 디렉터리는 여러 곳에 존

재하며 프레임워크가 있는 곳에 따라 프레임워크를 사용하는 방법도 달라집니다.

Page 40: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

40 41

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 5 프레임워크

� ‘Frameworks’ 디렉터리의 위치와 이용 방법

디렉터리 경로 목적

/System/Library/Frameworks 시스템 전체에서 사용하는 프레임워크를 배치. 이 디렉터리는

OS에 있어서 중요한 프레임워크를 배치하는 곳이므로 사용자

애플리케이션의 프레임워크는 배치하지 않음

/Library/Frameworks 시스템 전체에서 사용할 프레임워크를 배치. 사용자 애플리케

이션에서 사용자 계정과 관계없이 사용할 프레임워크를 배치

~/Library/Frameworks 특정 사용자 전용 프레임워크를 배치. ‘~/’는 로그인 중인 사용

자의 홈디렉터리를 의미

*.app/Contents/Frameworks 특정 애플리케이션 전용 프레임워크를 배치

Page 41: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

40 41

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-006 VER. 1.0 2.0

인스턴스의 생성과 소멸

� 인스턴스 생성과 소멸

Objective-C에서 클래스 인스턴스를 생성할 때는 ‘alloc’ 메서드를 사용하고 생성한 인스턴스

는 ‘init’ 메서드로 초기화합니다. 각 클래스에서는 ‘init’ 메서드를 정의해서 초기화 로직을 수

행합니다. ‘init’ 메서드는 이니셜라이져라고도 부릅니다. 이니셜라이져는 클래스에 따라 파

라미터가 달라지거나 메서드명이 다르게 정의되기도 합니다. 그러나 항상 ‘init’으로 시작합

니다.

생성한 인스턴스를 소멸할 때는 ‘release’ 메서드를 사용합니다. ‘release’ 메서드가 호출되면

그 인스턴스의 참조 카운터가 1 감소하며 참조 카운터가 0이 되면 소멸됩니다. 인스턴스가

소멸할 때 ‘dealloc’ 메서드가 호출됩니다. 각 클래스는 ‘dealloc’ 메서드를 정의하고 인스턴스

소멸처리와 관련된 처리 로직을 구현합니다.

f이니셜라이져의 반환값

이니셜라이져의 반환값은 부모클래스 이니셜라이져의 반환값을 받습니다. 이 반환값은 인

스턴스 자기 자신입니다. 초기화에 실패할 때도 있는데 초기화에 실패하면 인스턴스는 소멸

되고 ‘nil’을 반환합니다.

- (id)init

{

self = [super init];

if (self) // 부모클래스의 초기화 처리에 실패하면 ‘nil’을 반환

{

// 이 클래스의 초기화 처리

}

return self;

}

f ‘dealloc’ 메서드에서 부모클래스 호출도 잊지 말 것

‘dealloc’ 메서드를 구현할 때는 부모클래스의 ‘dealloc’ 메서드를 호출하는 것을 잊지 않게 주

의해야 합니다. ‘dealloc’을 빠뜨리면 부모클래스가 소멸되지 않아 메모리 누수나 예상치 못

한 동작이 발생할 수 있습니다.

Page 42: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

42 43

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 6 인스턴스의 생성과 소멸

- (void)dealloc

{

// 이 클래스 소멸 처리

// ....

[super dealloc]; // 부모클래스의 소멸 처리를 호출

}

f ‘autorelease’ 메서드

인스턴스 소멸에는 ‘release’ 메서드에 의한 명시적인 소멸 외에도 ‘autorelease’ 메서드에 의

한 자동소멸도 있습니다. ‘release’ 메서드 대신 ‘autorelease’ 메서드를 호출하면 그 인스턴

스는 ‘NSAutoreleasePool’ 클래스의 인스턴스가 소멸될 때 함께 소멸됩니다. 좀 더 정확하

게 말하면 ‘release’ 메서드와 같은 시점에 참조 카운터를 1 줄입니다. 시스템도 이벤트를 돌

릴 때마다 NSAutoreleasePool 클래스의 인스턴스를 생성하므로 시스템에 처리가 돌아오면

‘NSAutoreleasePool’ 클래스의 인스턴스가 소멸됨과 동시에 ‘autorelease’ 메서드를 호출한

메서드가 소멸됩니다.

‘NSAutoreleasePool’ 클래스는 ‘autorelease’ 메서드를 호출한 인스턴스를 관리하는 클래스

입니다. ‘Autorelease’ 메서드를 호출하면 유효한 ‘NSAutoreleasePool’ 클래스의 인스턴스 가

운데 가장 마지막에 생성된 인스턴스에 등록됩니다.

NSAutoreleasePool *pool1 = [[NSAutoreleasePool alloc] init];

while (...)

{

NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];

// 이 인스턴스는 ‘pool2’에 등록됨

MyObject *obj = [[[MyObject alloc] init] autorelease];

// 이 ‘drain’ 메서드로 ‘obj’가 소멸됨

[pool2 drain];

}

// 이 인스턴스는 ‘pool1’에 등록됨.

MyObject *obj2 = [[[MyObject alloc] init] autorelease];

// 이 ‘drain’ 메서드로 ‘obj2’가 소멸됨

[pool1 drain];

‘drain’ 메서드는 ‘NSAutoreleasePool’ 클래스의 인스턴스를 소멸시키는 메서드입니다. 다

른 메서드와 마찬가지로 ‘release’ 메서드를 사용할 수도 있지만 가비지 컬렉션 환경과의 호

환성을 위해 ‘NSAutoreleasePool’ 클래스에서는 ‘drain’ 메서드를 사용합니다. 더 자세한 내

Page 43: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

42 43

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 6 인스턴스의 생성과 소멸

용은 《가비지 컬렉션의 소멸처리를 수동으로 기동하기》(p.727)를 참조하기 바랍니다. 또한

‘drain’ 메서드는 Mac OS 10.4 이후 버전 또는 iPhone OS에서만 사용할 수 있습니다. Mac

OS 10.4 이전 버전에서는 ‘release’ 메서드를 사용하기 바랍니다.

이 책에서는 기본적으로는 ‘drain’ 메서드를 사용해 기술합니다. Mac OS 10.4 이전 버전에

서는 ‘drain’ 메서드 대신 ‘release’ 메서드를 사용하기 바랍니다.

f ‘autorelease’ 메서드를 사용해야만 할 때

메서드의 반환값 등 ‘alloc’ 메서드를 호출한 메서드가 종료된 후에도 그 인스턴스가 존재한

다면 ‘autorelease’ 메서드를 호출해 인스턴스를 반환해야 합니다. 이렇게 해야 그 인스턴스를

받아들인 쪽에서 처리할 때 인스턴스를 해제할 의무가 사라집니다. 또한 호출하는 쪽의 처리

도 ‘alloc’ 메서드에 의한 명시적인 인스턴스 생성 이외의 방법으로 취득한 인스턴스는 자동

소멸 된다고 할 수 있습니다(다만 예외인 경우도 있습니다).

‘Foundation’ 프레임워크도 마찬가지로 ‘alloc’ 메서드에 의한 명시적인 인스턴스 생성이

아닌 방법으로 인스턴스를 생성했을 때는 ‘autorelease’ 메서드가 호출된 인스턴스를 반환합

니다.

f ‘copy’ 메서드와 ‘mutableCopy’ 메서드는 ‘autorelease’ 메서드가

호출되지 않는다

‘alloc’ 메서드 이외에 ‘copy’ 메서드와 ‘mutableCopy’ 메서드로 생성한 인스턴스는 ‘autorelease’

메서드가 호출되지 않으므로 주의해야 합니다. 이들 메서드에서 취득한 인스턴스는 ‘release’

메서드로 명시적으로 소멸하거나 ‘autorelease’ 메서드를 호출해야 합니다.

f인스턴스를 유지하고자 할 때는 ‘retain’ 메서드를 호출한다

메서드 호출로 취득한 인스턴스는 ‘autorelease’ 메서드가 호출되는 경우가 대부분입니다. 취

득한 인스턴스를 클래스 인스턴스변수나 전역변수에 대입해서 유지하려고 할 때는 반드시

‘retain’ 메서드로 참조 카운터를 증가시켜야 합니다. 이 작업을 잊어버리면 이벤트 루프 처리

가 시스템으로 되돌아왔을 때 소멸되서 나중에 그 저장된 인스턴스를 사용하려고 하면 이미

인스턴스가 소멸되어 에러가 발생합니다. 그리고 ‘retain’ 메서드로 참조 카운터를 늘린 인스

턴스가 필요 없어지면 ‘release’ 메서드로 참조 카운터를 줄여야 합니다. 이때 다른 곳에서 참

조되지 않고 참조 카운터가 ‘0’이 되면 소멸됩니다.

Page 44: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

44 45

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 6 인스턴스의 생성과 소멸

f가비지 컬렉션이 유효할 때

가비지 컬렉션이 유효할 때는 ‘release’ 메서드와 ‘autorelease’ 메서드는 아무 동작도 하지 않

습니다. 인스턴스의 소멸은 해당 인스턴스가 더는 사용되지 않을 때 시스템에서 자동으로 실

행하며 ‘dealloc’ 메서드도 호출되지 않습니다. 그 대신 ‘�nalize’ 메서드가 호출됩니다.

하지만 ‘�nalize’ 메서드는 ‘dealloc’ 메서드와는 달리 호출되는 시점이 가비지 컬렉션에 달

려있으므로 순서나 시점에 좌우되는 코드는 피하기 바랍니다. 또한 ‘�nalize’ 메서드에서의

처리는 스레드 세이프 1하게 구현해야 합니다. 따라서 될 수 있으면 ‘�nalize’ 메서드에 의존하

지 않게 설계하는 방법이 좋습니다.

관련 항목 fff

• 가비지 컬렉션 ····························································· p.720

• 가비지 컬렉션의 소멸처리를 수동으로 기동하기 ································ p.727

1  ( 옮긴이 ) Thread Safe : 여러 개의 스레드에 접근할 때 동작의 안정성을 보장하는 처리 방법

Page 45: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

44 45

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-007 VER. 1.0 2.0

Objective-C 클래스

� Objective-C 클래스의 특징

Objective-C의 클래스도 다른 객체지향 언어와 같은 특징이 있습니다. 클래스를 파생할 수

있으며 부모클래스와 자식클래스가 있습니다. 자식클래스는 부모클래스의 메서드를 재정의

할 수 있으며 자식클래스는 부모클래스의 메서드를 호출할 수도 있습니다. 그 밖에 다음과

같은 특징이 있습니다.

• 다중상속 불가

• 대부분의 클래스는 ‘NSObject’ 클래스를 상속

• 동적 타입 설정

• 메서드명과 인스턴스 변수명은 중복 가능

f다중상속 불가

C++와는 달리 Objective-C는 클래스가 다중상속되지 않습니다. 하지만 ‘프로토콜’이 존재하

므로 다중상속과 다른 형태로 인터페이스 정의를 할 수 있습니다. ‘프로토콜’은 특정 메서드

가 있다는 것을 정의합니다. 이는 클래스가 무엇인지 와는 관계없이 특정 메서드를 구현하면

된다는 개념에서 나왔습니다.

쉬운 예로 ‘AppKit’ 프레임워크의 ‘NSTableView’ 클래스와 ‘NSTableDataSource’ 프로토콜

의 관계를 들 수 있습니다. ‘NSTableView’ 클래스에는 표시할 정보를 제공하는 데이터소스에

해당하는 인스턴스가 필요합니다. 이 데이터소스는 ‘NSTableDataSource’ 프로토콜에 정의

된 메서드를 구현한 클래스라면 무엇이라도 상관없습니다. ‘NSTableView’가 정보를 표시하

는 데 필요한 것은 정보 그 자체와 그 정보를 얻기 위한 메서드뿐입니다. 즉 특정 클래스에서

파생된 클래스일 필요는 없습니다. ‘NSTableView’ 클래스는 데이터소스로 설정된 인스턴스

에 대해 ‘NSTableDataSource’ 프로토콜에서 정의한 정보를 가져오는 메서드를 호출하고 가

져온 정보를 표시합니다.

f대부분 클래스는 ‘NSObject’ 클래스를 상속

‘NSObject’ 클래스는 매우 중요한 기본 클래스입니다. Objective-C의 클래스는 대부분

‘NSObject’ 클래스를 상속합니다.

Page 46: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

46 47

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 7 Objective-C 클래스

‘NSObject’ 클래스는 인스턴스 생성에 사용하는 ‘alloc’ 메서드나 소멸에 사용하는 ‘release’

메서드, 참조 카운터를 늘리는 ‘retain’ 메서드, 자동소멸을 위한 ‘autorelease’ 메서드 등 매우

중요한 메서드를 포함하고 있습니다. 새로운 클래스를 생성할 때는 반드시 ‘NSObject’ 클래

스나 그 밖의 클래스의 서브클래스로 생성하기 바랍니다.

f메서드에 대한 주의점

Objective-C 클래스는 클래스 자체가 자신의 정보를 담고 있습니다. 메서드가 있는지 없는지

는 실행할 때 판단합니다. 따라서 C++에서는 메서드 이름이 잘못되어 있으면 빌드에 실패하

지만 Objective-C에서는 빌드는 성공합니다(단, 경고가 나옴). 하지만 클래스가 갖지 않은 메

서드를 호출하려고 하면 실행할 때 예외가 발생해 그 지점에서 처리가 중단됩니다. 그러므로

빌드할 때는 컴파일러가 출력하는 경고를 잘 살피기 바랍니다.

Page 47: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

46 47

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-008 VER. 1.0 2.0

C 언어 코드와의 조합

� C 언어 코드와 함께 사용하기

Objective-C는 C 언어를 확장한 언어이므로 C 언어의 코드를 그대로 사용할 수 있으며 함께

사용할 수도 있습니다.

f함수

C 언어 함수에서 Objective-C 메서드를 호출할 수 있으며 반대로 Objective-C 메서드에서 C

언어의 함수를 호출할 수도 있습니다. 이런 특징을 살려 C 언어용 라이브러리의 콜백 함수를

C 언어의 코드로 작성하고 그 안에 Objective-C 기능을 사용하거나 Objective-C 코드에서 외

부의 C 언어용 라이브러리를 호출할 수도 있습니다. 또한 C 언어의 코드를 다시 구현하지 않

아도 Objective-C 클래스로 감싸기만 하면 기존의 C 언어 코드를 쉽게 사용할 수 있습니다.

#import <Foundation/Foundation.h>

@interface MyObject : NSObject

{

}

- (void)doSomething:(NSString*)str;

@end

@implementation MyObject

- (void)doSomething:(NSString*)str

{

// Objective-C 메서드에서 C 언어 함수를 호출할 수 있음

printf("%s", [str UTF8String]);

}

@end

void doSomething(void)

{

// C 언어 함수에서 Objective-C 클래스의 인스턴스 생성할 수 있음

NSString* str = [NSString stringWithString:@"TEST"];

// C 언어 함수에서 Objective-C 클래스의 메서드를 호출할 수 있음

str = [str stringByAppendingString:@" STRING"];

// C 언어 함수를 호출할 수 있음

printf("%s\n", [str UTF8String]);

}

Page 48: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

48 49

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 8 C 언어 코드와의 조합

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

MyObject* myObject = [[MyObject alloc] init];

[myObject doSomething:@"Objective-C method\n"];

doSomething();

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

Objective-C method

TEST STRING

f구조체

C 언어의 구조체도 그대로 사용할 수 있으며 메서드의 파라미터나 클래스의 인스턴스 변수

등에도 사용할 수 있습니다. 또한 Objective-C 클래스를 선언할 때 구조체를 선언할 수도 있

습니다. 하지만 Objective-C에는 네임스페이스 기능이 없으므로 클래스에서 선언해도 전역

네임스페이스로 할당됩니다. 따라서 선언된 구조체는 그 선언이 속한 Objective-C 클래스에

구속되지 않고 자유롭게 다른 클래스나 함수에서 사용할 수 있습니다. 이 점은 C++와는 다

르므로 주의해야 합니다.

#import <Foundation/Foundation.h>

@interface MyObject : NSObject

{

// Objective-C의 클래스를 선언할 때 구조체를 선언할 수 있음

struct MyStruct {

int data0;

int data1;

} MyStruct;

// 구조체의 변수도 Objective-C 클래스의 선언에서 사용할 수 있음

struct MyStruct _data;

}

@end

@implementation MyObject

- (id)init

{

Page 49: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

48 49

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 8 C 언어 코드와의 조합

self = [super init];

if (self)

{

_data.data0 = 3;

_data.data1 = 2;

}

return self;

}

- (void)printData

{

NSLog(@"%d, %d", _data.data0, _data.data1);

}

- (void)printDataFromExternal:(struct MyStruct)externalData

{

NSLog(@"%d, %d", externalData.data0, externalData.data1);

}

@end

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

MyObject* myObject = [[[MyObject alloc] init] autorelease];

[myObject printData];

// Objective-C 클래스 선언에서 선언한 구조체는 전역으로 취급

struct MyStruct data = { 10, 20 };

[myObject printDataFromExternal:data];

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-14 22:50:05.547 CStruct[3941:a0f] 3, 2

2010-01-14 22:50:05.550 CStruct[3941:a0f] 10, 20

f타입 정의

타입을 정의할 때 쓰는 ‘typedef’ 명령도 그대로 사용할 수 있습니다. 구조체처럼 메서드의 파

라미터나 클래스 인스턴스 변수 등에도 사용할 수 있습니다.

Page 50: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

50 51

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 8 C 언어 코드와의 조합

#import <Foundation/Foundation.h>

// 정수타입을 정의

typedef unsigned long long SerialNumber;

// 구조체의 타입을 정의

typedef struct {

SerialNumber sn;

int data0;

int data1;

} MyStruct, *MyStructPtr;

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

MyStructPtr p = (MyStructPtr)malloc(sizeof(MyStruct));

p->sn = 10;

p->data0 = 20;

p->data1 = 30;

NSLog(@"sn=%llu, data0=%d, data1=%d",

newItem->sn, newItem->data0, newItem->data1);

free(newItem);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-14 23:24:08.424 Typedef[4277:a0f] sn=10, data0=20, data1=30

Page 51: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

50 51

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

SECTION-009 VER. 1.0 2.0

C++ 클래스

� Objective-C++에서 C++ 클래스 다루기

Objective-C++에서는 C++ 클래스를 사용할 수 있습니다. C++ 클래스의 멤버 변수나 메서

드 파라미터에 Objective-C의 인스턴스를 전달할 수도 있습니다. 반대로 Objective-C의 클래

스 인스턴스 변수나 메서드 파라미터에 C++ 클래스의 인스턴스나 인스턴스 포인터를 사용

할 수도 있습니다. C++ 클래스의 인스턴스는 인스턴스 포인터와 스택에 생성한 인스턴스가

있는데 가상함수나 생성자, 소멸자는 Objective-C++에서 지원하지 않으므로 Objective-C

인스턴스 변수로는 인스턴스 포인터를 두는 편이 무난합니다.

하지만 클래스 계층을 혼합하는 것은 불가합니다. C++ 클래스를 상속한 Objective-C 클래

스를 구현하거나 반대로 Objective-C 클래스를 상속한 C++ 클래스는 구현할 수 없습니다.

#import <Foundation/Foundation.h>

class MyClass {

public:

MyClass() {

_str = nil;

}

virtual ~MyClass() {

[_str release];

}

// Objective-C 클래스의 인스턴스를 C++ 메서드의 파라미터로 사용할 수 있음

void DoSomething(NSString *newStr) {

if (_str != newStr)

{

[_str release];

_str = [newStr copy];

}

NSLog(@"%@", _str);

}

private:

// Objective-C 클래스의 인스턴스를 멤버 변수로 사용할 수 있음

NSString *_str;

};

@interface MyObject : NSObject

{

Page 52: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

52 53

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 9 C++ 클래스

// C++ 클래스의 인스턴스 포인터를 Objective-C 클래스의

// 인스턴스 변수로 사용할 수 있음

MyClass *_data;

}

// Objective-C 메서드의 파라미터로 C++ 인스턴스 포인터를 사용할 수 있음

- (void)doSomething:(MyClass *)p;

@end

@implementation MyObject

- (void)doSomething:(MyClass *)p

{

_data = p;

if (_data)

{

_data->DoSomething(@"Call From Objective-C Method");

}

}

@end

int main(int argc, char **argv)

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *p = new MyClass();

MyObject *p2 = [[MyObject alloc] init];

[p2 doSomething:p];

[p2 release];

delete p;

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-14 23:29:26.560 CppClass[4373:a0f] Call From Objective-C Method

� 가상함수는 지원하지 않음

Objective-C++는 C++의 가상함수를 지원하지 않습니다. 따라서 Objective-C 클래스의 인

스턴스 변수로 virtual 멤버를 가진 C++ 클래스의 인스턴스를 둘 수는 없습니다. 하지만 완전

히 지원하지 않는 것은 아니므로 Objective-C 클래스의 인스턴스 변수로 C++ 클래스를 사용

하고 싶을 때는 ‘new’로 생성한 인스턴스 포인터를 갖게 하면 됩니다. 인스턴스 포인터는 가

상함수를 가진 클래스도 사용할 수 있으며 ‘->’ 연산자를 이용한 메서드 호출에서 가상함수도

호출할 수 있습니다. 이것은 인스턴수 변수뿐만 아니라 스택 변수나 메서드의 파라미터도 같

습니다.

Page 53: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

52 53

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 9 C++ 클래스

#import <Foundation/Foundation.h>

class MyClass {

public:

MyClass() { NSLog(@"MyClass::MyClass()"); }

virtual ~MyClass() { NSLog(@"MyClass::~MyClass"); }

};

class MyClass2 {

public:

MyClass2() { NSLog(@"MyClass2::MyClass2()"); }

~MyClass2() { NSLog(@"MyClass2::~MyClass2()"); }

};

@interface MyObject : NSObject

{

/*

MyClass _myClass; // 가상 함수를 갖고 있으므로

// 인스턴스 변수를 둘 수 없음

// (에러 발생)

*/

MyClass *_myClassPtr; // 문제 없음

MyClass2 *_myClass2Ptr; // 문제 없음

}

- (void)doSomething;

@end

@implementation MyObject

- (void)doSomething

{

//'new'가 생성자를 호출

_myClassPtr = new MyClass();

//'delete'가 소멸자를 호출

delete _myClassPtr;

//'new'가 생성자를 호출

_myClass2Ptr = new MyClass2();

//'delete'가 소멸자를 호출

delete _myClass2Ptr;

// 메서드에서 스택에 C++ 클래스를 두는 것도 가능

// 여기서 생성자를 호출

MyClass c1;

// 메서드를 벗어날 때 변수 'c1'의 소멸자가 호출됨

}

@end

int main(int argc, char **argv)

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyObject *myObject = [[MyObject alloc] init];

Page 54: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

54 55

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

S E C T I O N - 0 0 9 C++ 클래스

[myObject doSomething];

[myObject release];

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다. 날짜와 시각은 프로그램의 실행 일자입니다.

2010-01-14 23:52:49.820 CppClass2[4700:a0f] MyClass::MyClass()

2010-01-14 23:52:49.823 CppClass2[4700:a0f] MyClass::~MyClass

2010-01-14 23:52:49.823 CppClass2[4700:a0f] MyClass2::MyClass2()

2010-01-14 23:52:49.823 CppClass2[4700:a0f] MyClass2::~MyClass2()

2010-01-14 23:52:49.824 CppClass2[4700:a0f] MyClass::MyClass()

2010-01-14 23:52:49.824 CppClass2[4700:a0f] MyClass::~MyClass

Objective-C++에서는 C++ 생성자와 소멸자 모두 호출할 수 있습니다.

일반적으로 Objective-C 클래스 정의는 헤더 파일에 작성하지만 헤더 파일에서 정의한 클래스에

서 C++ 클래스의 인스턴스 포인터를 인스턴스 변수로 사용하면 그 헤더 파일은 Objective-C 파

일(확정자가 ‘.m’인 파일)에서는 인식하지 못하게 됩니다. 이는 Objective-C++는 C++ 클래스를

인식할 수 있으나 Objective-C는 C++ 클래스를 인식하지 못하기 때문입니다. 이때는 인스턴스

변수를 ‘void*’로 정의하면 됩니다.

예를 들면 ‘MyClass’라는 C++ 클래스를 ‘MyObject’라는 Objective-C 클래스의 인스턴스 변수

로 가지고 있을 때에는 다음과 같이 ‘void*’를 사용합니다.

@interface MyObject : NSObject

{

void *_myClassPtr; // 실제로는 ‘MyClass’ 클래스의 포인터

}

@end

클래스의 메서드를 포함한 Objective-C++ 파일(확장자가 ‘.mm’인 파일)에서는 다음과 같이 처

리합니다.

COLUMN Objective-C에서 사용되는 헤더 파일에서 C++ 클래스 다루기

Page 55: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

54 55

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 0 9 C++ 클래스

@implementation MyObject

- (id)init

{

self = [super init];

if (self)

{ // 형변환해서 대입

_myClassPtr = (void *)(new MyClass());

}

return self;

}

- (void)dealloc

{ // 형변환해서 파기

if (_myClassPtr)

delete ((MyClass *)_myClassPtr);

[super dealloc];

}

- (void)doSomething

{ // 형변환한 후 메서드 호출

if (_myClassPtr)

((MyClass *)_myClassPtr)->DoSomething();

}

@end

Page 56: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

56 57

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER

01

SECTION-010 VER. 1.0 2.0

네임스페이스

� Objective-C++에서 네임스페이스 다루기

Objective-C++는 C++ 클래스에서 네임스페이스를 사용할 수 있습니다. 더러 제한적인 부

분도 있지만 일반적으로 한 코드에서 네임스페이스가 있는 C++ 코드와 Objective-C 코드를

조합해서 사용할 수 있습니다. ‘using namespace’ 명령을 사용해 네임스페이스를 생략할 수

도 있습니다. 하지만 Objective-C 자체는 네임스페이스라는 개념이 없으므로 Objective-C의

클래스명이 충돌하면 해결할 방법이 없습니다. 따라서 클래스명을 변경하는 방법 말고는 해

결책이 없으므로 하나의 프로젝트에 또는 하나의 프로그램에서 공통으로 사용할 접두어를

정해서 클래스명 앞에 붙이는 식으로 클래스 이름이 중복되지 않게 해야 합니다. 예를 들면

Objective-C의 Foundation 프레임워크나 AppKit 프레임워크에서는 ‘NS’로 시작하는 클래

스명을 사용합니다.

#import <Foundation/Foundation.h>

// Objective-C 클래스 선언 이외에는 네임스페이스를 정의할 수 있음

namespace MyNamespace2 {

// C++ 클래스이므로 네임스페이스 안에서 선언할 수 있음

class MyClass {

public:

MyClass() {}

virtual ~MyClass() {}

void Do() { NSLog(@"MyClass::Do()"); }

};

}

int main (int argc, const char* argv[])

{

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

// 함수에서 네임스페이스 선언 내의 C++클래스를 사용할 수도 있음

MyNamespace2::MyClass *p = new MyNamespace2::MyClass();

p->Do();

delete p;

[pool drain];

return 0;

}

Page 57: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

56 57

01

02

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

기초

CH

AP

TER01

S E C T I O N - 0 1 0 네임스페이스

fObjective-C++에서 네임스페이스 제약 사항

Objective-C++에서 C++의 네임스페이스를 사용할 때는 다음과 같은 두 가지 제약 사항이

있습니다.

• Objective-C 클래스 선언 내에서는 네임스페이스를 선언할 수 없음

• 네임스페이스 내에서는 Objective-C 클래스를 선언할 수 없음

이 두 가지 제약 사항 때문에 다음과 같은 코드에서는 에러가 발생합니다.

@interface MyObject : NSObject

{

// Objective-C 클래스 선언 내에서는 네임스페이스를 선언할 수 없음 (에러 발생)

namespace MyNamespace

{

}

}

@end

namespace MyNamespace2

{

// Objective-C 클래스를 C++의 네임스페이스 내에서는 선언할 수 없음 (에러 발생)

@interface MyObject2 : NSObject

{

}

@end

}

Page 58: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는
Page 59: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

CHAPTER02Objective-C의 문법

Page 60: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

60

SECTION-011 VER. 1.0 2.0

리터럴

� Objective-C의 리터럴

리터럴이란 프로그램에서 직접 작성할 수 있는 문자나 문자열, 수치를 의미합니다. Objective-C

의 리터럴은 C 언어의 리터럴을 물려받았습니다.

f수치

수치는 10진수, 16진수, 8진수를 사용할 수 있습니다. 또한 정수뿐만 아니라 실수도 사용할

수 있습니다. 일반적으로 작성한 수치는 10진수로 취급하고 ‘0x’로 시작하면 16진수, ‘0’으로

시작하면 8진수로 취급합니다. 수치 뒤에 붙는 접미어에 따라 형태가 변하기도 합니다. 특히

‘long long’ 타입으로밖에 표현할 수 없는 큰 수치는 ‘ll’을 붙이지 않으면 수치가 반올림 되어

정확하게 동작하지 않을 수도 있으니 주의해야 합니다.

20 // 정수

-14 // ‘-’를 붙이면 음의 정수

10.4 // ‘.’을 붙이면 실수

-11.5 // ‘-’와 ‘.’을 모두 쓰면 음의 실수

20.345f // ‘f’를 붙이면 ‘float’ 타입으로 취급

403u // ‘u’를 붙이면 부호가 없는 것으로 취급

20005ul // ‘ul’을 붙이면 ‘unsigned long’ 타입으로 취급

205l // ‘l’을 붙이면 ‘long’ 타입으로 취급

12345ll // ‘ll’을 붙이면 ‘long long’ 타입으로 취급

20345ull // ‘ull’을 붙이면 ‘unsigned long long’ 타입으로 취급

0x1f // ‘0x’를 붙이면 16진수가 됨

0x1F // 16진수의 알파벳은 대문자ㆍ소문자 모두 사용할 수 있음

0214 // ‘0’으로 시작하면 8진수가 됨

f BOOL 타입

‘참’인지 ‘거짓’인지 표시합니다. 값은 ‘YES’ 또는 ‘NO’입니다. ‘YES’는 1과 같고 ‘NO’는 0과

같습니다.

f문자

문자는 ''(작은따옴표) 기호로 둘러싸서 표기합니다. 문자는 ‘char’ 타입으로 취급되며 접두

어로 ‘L’을 붙이면 ‘wchar_t’ 타입으로 취급됩니다. 이때 대문자와 소문자가 다른 값이 되니

주의해야 합니다. 또한 ‘숫자’와 ‘수치’는 다른 개념이므로 주의해야 합니다.

Page 61: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

61

S E C T I O N - 0 1 1 리터럴

// 대문자 ‘A’와 소문자 ‘a’는 다른 문자로 취급됨

'A'

'a'

// 수치 ‘1’과 문자 ‘1’은 다른 값임

'1'

// ‘wchar_t’ 타입으로 취급됨

L'A'

f문자열

문자열은 " "(큰따옴표) 기호로 둘러싸서 표기합니다. C 언어의 문자열과 마찬가지로

Objective-C의 문자열은 ‘NULL 종단 문자열’입니다.

NULL 종단 문자열이란 문자열의 마지막에 종단을 표시하는 문자로 ‘0’이 들어간 문자열입

니다. 문자열은 ‘char’ 타입의 변수가 연속해서 나열된 ‘char’ 타입의 배열과 같습니다. ‘문자’

와 마찬가지로 접두어로 ‘L’을 붙이면 ‘wchar_t’ 타입 변수가 연속으로 이어진 ‘wchar_t’ 타입

의 배열과 같아집니다. 여기서 ‘같다’라는 애매한 표현을 쓰는 이유는 실제로는 ‘char*’ 또는

‘wchar_t*’ 타입이 되기 때문입니다. 여기서 ‘*’은 ‘포인터’를 의미합니다.

추가로 Objective-C에서는 접두어로 ‘@’를 붙이면 ‘NSString’ 클래스의 인스턴스로 취급합

니다. 더 자세한 내용은 <문자열>(p.152)을 참조하기 바랍니다.

// ‘char*'로 취급함

"This is a NULL terminated string"

// ‘wchart_t*'로 취급함

L"This is a NULL terminated wide string"

// ‘NSString*'로 취급함

@"This is a NSString*."

Page 62: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

62

S E C T I O N - 0 1 1 리터럴

문자의 실체는 수치입니다. 각 문자의 값이 몇인지는 텍스트 인코딩(문자코드)에 따라 정의됩니

다. 대부분 텍스트 인코딩은 127 이하의 값은 ASCII 코드와 호환성을 갖고 있으므로 알파벳이나

숫자를 직접 소스코드에서 사용해도 문제가 발생하는 일은 거의 없습니다. 또한 수치이므로 덧셈

이나 뺄셈 등의 연산도 할 수 있습니다. ASCII 코드의 각 문자에서 ‘a’의 다음은 ‘b’가 되며 ‘z’까지

순서대로 이어져 있습니다. 따라서 ‘a’+2는 ‘c’입니다. 또한 대문자 알파벳과 소문자 알파벳에는

각 수치가 할당돼 있으므로 대문자와 소문자는 서로 다른 문자로 취급됩니다.

다음 코드는 문자를 로그에 출력하는 코드입니다.

for (int i = 0; i < 128; i++)

{

//출력할 수 있는 문자인지 조사

if (isprint(i))

{

//로그에 수치와 문자 형태로 출력

NSLog(@"0x%02X (%d) = '%c'", i, i, (char)i);

}

}

COLUMN 문자의 실체는 수치

관련 항목 fff

• 문자열 ···································································· p. 152

Page 63: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

63

SECTION-012 VER. 1.0 2.0

변수

� Objective-C의 변수

변수는 값을 넣어둘 수 있는 장소입니다. 변수 선언은 다음과 같이 ‘타입’을 먼저 지정하고 그

뒤에 ‘변수명’을 지정합니다. ‘=’ 연산자로 초기값을 지정할 수도 있습니다.

long l; // ‘long’ 타입의 변수 ‘l’ 선언

int i = 10; // ‘int’ 타입의 변수 ‘i’ 선언. 초기값은 ‘10’

f대입

변수에 값을 대입할 때는 ‘=’ 연산자를 사용합니다.

x = 10; // 변수 ‘x’에 ‘10’을 대입

x = y; // 변수 ‘x’에 변수 ‘y’의 수치를 대입

f유효범위

변수는 선언된 위치에 따라 사용할 수 있는 범위가 정해집니다. 사용할 수 있는 범위는 선언

된 영역 내입니다. 영역은 ‘{’로 시작해서 ‘}’로 끝나는 범위를 가리킵니다.

int x;

{

// 여기서는 변수 ‘y’가 아직 선언되지 않았으므로 사용할 수 없음

int y;

// 여기서는 변수 ‘x’와 변수 ‘y’ 모두 사용할 수 있음

}

// 여기서는 변수 ‘y’는 영역 밖에 있으므로 사용할 수 없음

// 변수 ‘x’는 사용할 수 있음

관련 항목 fff

• 연산자 ···································································· p.64

Page 64: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

64

SECTION-013 VER. 1.0 2.0

연산자

� Objective-C의 연산자

Objective-C에서 사용할 수 있는 연산자는 C 언어에서 사용할 수 있는 연산자와 같습니다.

연산자에는 우선순위가 정해져 있지만 소괄호 ‘(’와 ‘)’를 사용해 먼저 연산할 부분을 지정할

수 있습니다. 필자는 연산자가 처리되는 순서를 명확히 하기 위해 연산자의 우선순위와 관계

없이 괄호를 사용해 먼저 처리하고 싶은 부분을 명시합니다.

f산술 연산자

산술연산은 일반적인 산술연산 방식을 사용합니다. 일반적인 산술연산과 마찬가지로 곱셈

과 나눗셈이 덧셈과 뺄셈보다 우선순위가 높습니다.

연산자 설명

* 곱셈

/ 나눗셈

+ 덧셈

- 뺄셈

% 나머지 계산

i = (10 + 2 * 5) % 3; // ‘2*5’를 먼저 계산하고 ‘10’을 더한 후에 ‘3’으로 나눈 나머지 ‘2’가 변수 ‘i’에 대입됨

x = x * y; // ‘x * y’의 결과가 ‘x’에 대입됨

a = b + 10 * c; // ‘10 * c’가 먼저 계산되어

// 변수 ‘b’와 더한 결과가 변수 ‘a’에 대입됨

z = (x + 10) * 5; // ‘x + 10’이 먼저 계산되어,

// ‘5’와 곱한 결과가 변수 ‘z’에 대입됨

f증가, 감소 연산자

증가 연산자는 변수의 값을 1 증가시키며 감소 연산자는 1 감소시킵니다.

int i = 0;

i++; // ‘i = i + 1’과 같음

i--; // ‘i = i – 1’과 같음

Page 65: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

65

f비트 연산자

비트 연산자는 비트 단위로 연산합니다. 비트 단위의 연산은 값을 2진수로 바꾼 후 비트열 상

태로 계산합니다.

연산자 설명

| OR를 계산

& AND를 계산

~ NOT을 계산

^ XOR를 계산

>> 오른쪽으로 비트 시프트

<< 왼쪽으로 비트 시프트

unsigned char x = 5; // 2진수로 ‘00000101’unsigned char y = 3; // 2진수로 ‘00000011’unsigned char z;

z = x | y; // 2진수로 ‘00000111’z = x & y; // 2진수로 ‘00000001’z = ~x; // 2진수로 ‘11111010’z = x ^ y; // 2진수로 ‘00000110’z = x << 5; // 2진수로 ‘10100000’z = x >> 1; // 2진수로 ‘00000010’

f논리 연산자

논리 연산자는 연산자의 좌변과 우변을 비교해 결과를 ‘거짓’(0)과 ‘참’(1)으로 반환하는 연산

자로 조건분기에서 사용합니다.

연산자 설명

== 좌변값과 우변값이 같을 때 ‘참’

!= 좌변값과 우변값이 다를 때 ‘참’

< 좌변값이 우변값 미만일 때 ‘참’

> 좌변값이 우변값 초과일 때 ‘참’

<= 좌변값이 우변값 이하일 때 ‘참’

>= 좌변값이 우변값 이상일 때 ‘참‘

&& 좌변값과 우변값 양쪽 모두 ‘참’일 때 ‘참’

|| 좌변값과 우변값 중 어느 한 쪽이 ‘참’일 때 ‘참’

! 우변값이 ‘거짓’일 때 ‘참’, ‘참’일 때 ‘거짓’

Page 66: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

66

f삼항 연산자

삼항 연산자는 조건식이 성립할 때(‘참’일 때)의 값과 성립하지 않을 때(‘거짓’일 때)의 값을

지정하는 연산자입니다. 값에는 수식이나 함수 등을 지정할 수도 있으며 구문은 다음과 같

습니다.

(조건식) ? (‘참’일 때의 값) : (‘거짓’일 때의 값)

// 변수 ‘y’의 값이 0보다 클 때, 함수 ‘doSomething’의 반환값을 변수 ‘x’에 대입함

// 이외의 경우에는 ‘0’을 대입함

x = (y > 0) ? doSomething(y) : 0;

f축약형

연산자는 축약형으로 사용할 수도 있습니다. 예를 들어, ‘i = i + 2’는 ‘i += 2’라고 쓸 수도 있습

니다. 이와 같이 축약형으로 쓸 수 있는 연산자는 다음과 같습니다.

축약형 축약하기 전

a += b a = a + b

a -= b a = a - b

a *= b a = a * b

a /= b a = a / b

a %= b a = a % b

a &= b a = a & b

a |= b a = a | b

a <<= b a = a << b

a >>=b a = a >> b

f ‘sizeof’ 연산자

‘sizeof’ 연산자는 타입의 크기를 반환하는 연산자입니다. 예를 들어 ‘sizeof(short)’ 타입은 16

비트 변수이므로 2바이트가 되어 ‘2’를 반환합니다. ‘sizeof’ 연산자는 타입 또는 변수를 파라

미터로 사용합니다. 구조체를 파라미터로 사용하면 그 구조체에 필요한 크기를 반환합니다.

Page 67: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

67

삼항 연산자는 ‘if’문을 사용한 조건분기로 바꿔 쓸 수도 있습니다. 예를 들어 다음과 같은 코드가

있다고 합시다.

int a = (x < y) ? calc(x) : calc(y);

이 코드를 다음과 같이 바꿀 수도 있습니다.

int a;

if (x < y)

a = calc(x);

else

a = clac(y);

삼항 연산자로 기술할지 if 문을 사용한 조건분기로 기술할지는 개발자의 취향에 달렸지만 필자는

다음과 같을 때 삼항 연산자를 사용합니다.

• 변수를 정의했을 때 사용할 초기값 설정

• ‘return’ 문의 함수(메서드) 반환값

• 함수(메서드)의 파라미터로 기술할 때

하지만 위의 경우 중 하나를 만족하더라도 조건식이나 값(또는 식)이 복잡할 때는 삼항 연산자 대

신 ‘if’문으로 된 조건분기를 사용합니다.

// 변수를 정의했을 때 사용할 초기값 설정

int a = (x > 0) ? x : 0;

// ‘return’ 문의 함수 (메서드) 반환값

return ((x > 0) ? x : 0);

// 함수(메서드)의 파라미터로 기술할 때

[myObject calc:((x > 0) ? x : 0)];

COLUMN 삼항 연산자와 조건분기

관련 항목 fff

• 변수 ······································································ p.63

Page 68: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

68

SECTION-014 VER. 1.0 2.0

상수

� Objective-C의 상수

Objective-C에서는 상수로서 열거, 전처리 지시자(preprocessor directive), ‘const’ 수식자를

붙인 변수를 사용할 수 있습니다. 그 외에 Objective-C에서는 문자열 상수를 자주 사용하는

데 그때 ‘NSString’ 클래스를 사용합니다. 프로그램에 상수를 선언하지 않고 필요한 상황에

값을 기술할 수도 있지만 다음과 같은 이유로 그러한 방식은 추천하지 않습니다.

• 코드를 여기저기 작성하게 되면 코드를 변경할 때 모두 수정해 주지 않으면 안 된다.

• 상수의 의미가 불분명해진다. 상수에 알기 쉬운 이름을 붙여두면 나중에 봐도 그 값의

의미를 쉽게 파악할 수 있다.

• 문자열 상수(‘NSString’ 클래스)는 매번 문자열 리터럴을 기술하면 철자가 틀려도 컴파

일 에러가 발생하지 않으므로 잘못된 부분을 발견하기가 무척 어렵다.

따라서 될 수 있으면 상수는 직접 작성하지 않고 상수로 선언한 후 선언한 상수를 사용하는

방법을 추천합니다.

f열거

열거를 정의하려면 예약어인 ‘enum’을 사용합니다.

// ‘enum.h’ 파일

#import <Foundation/Foundation.h>

// 열거를 정의함

enum

{

// OneObjectType의 값을 2000으로 정의함

OneObjectType = 2000,

// TwoObjectType의 값을 3000으로 정의함

TwoObjectType = 3000,

// ThreeObjectType의 값을 3001로 정의함

ThreeObjectType

};

‘enum’은 ‘{}’(대괄호)로 둘러싼 유효범위 안에 ‘상수명=수치’ 형식으로 정의하고 여러 항

목을 열거할 때는 ‘,’(콤마)로 구분합니다. 값을 생략했을 때는 직전의 상수값에서 ‘1’을 더한

값이 사용됩니다. 첫 번째 상수의 값을 생략하면 첫 번째 값은 ‘0’이 됩니다. 정의한 값을 사용

하려면 다음 코드와 같이 값 대신에 상수명을 기술합니다.

Page 69: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

69

S E C T I O N - 0 1 4 상수

// ‘main.m’ 파일

#import <Foundation/Foundation.h>

#import "enum.h"

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// 열거를 사용할 때는 수치 대신에 열거할 상수명을 씀

NSLog(@"OneObjectType=%d", OneObjectType);

NSLog(@"TwoObjectType=%d", TwoObjectType);

NSLog(@"ThreeObjectType=%d", ThreeObjectType);

[pool drain];

return 0;

}

f전처리 지시자

C 언어와 마찬가지로 전처리 지시자인 ‘#de�ne’을 사용합니다. 컴파일러는 ‘#de�ne’에서 정

의한 상수를 값으로 바꿔 컴파일합니다. ‘#de�ne’을 이용해 수치뿐만 아니라 문자열도 정의

할 수 있습니다.

// ‘Define.h’ 파일

// ‘InitialValue’라는 이름으로 ‘10’을 정의함

#define InitialValue 10

// ‘InitialString’이라는 이름으로 “ABCDEF”를 정의함

#define InitialString "ABCDEF"

‘#de�ne’은 ‘상수명 값’ 형식으로 정의합니다. 값과 상수명은 스페이스나 탭으로 구분하며

하나의 ‘#de�ne’ 당 하나의 상수를 정의할 수 있습니다. 정의한 값을 사용하려면 다음 코드와

같이 값이나 문자열 대신 상수명을 기술합니다.

// ‘Define.m’ 파일

#import <Foundation/Foundation.h>

#import "Define.h"

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// 정의한 상수를 사용할 때는 값 대신에 상수명을 기술함

NSLog(@"InitialValue=%d", InitialValue);

NSLog(@"InitialString=%s", InitialString);

[pool drain];

return 0;

}

Page 70: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

70

S E C T I O N - 0 1 4 상수

f ‘const’ 수식자

변수의 타입 선언 앞에 ‘const’ 수식자를 붙입니다. ‘#de�ne’과 달리 ‘변경할 수 없는 변수’로

취급되며 ‘타입’ 정보를 가진 것이 특징입니다. 따라서 잘못 사용했을 때는 컴파일러가 컴파

일할 때 어느 정도 잘못된 부분을 검출할 수 있습니다.

// ‘Const.h’ 파일

// ‘InitialValue’라는 이름으로 ‘10’을 정의함

const int InitialValue = 10;

정의한 값을 사용하려면 다음 코드와 같이 상수명을 기술합니다.

// ‘Const.m’ 파일

#import <Foundation/Foundation.h>

#import "Const.h"

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// 정의한 상수를 사용하려면 값 대신에 상수명을 씀

NSLog(@"InitialValue=%d", InitialValue);

[pool drain];

return 0;

}

f ‘NSString’ 클래스

문자열 상수의 정의는 ‘NSString’ 클래스를 사용합니다. 그리고 헤더 파일에 직접 정의하면

읽어들인 소스파일마다 서로 다른 인스턴스가 돼버리므로 링크 에러가 발생합니다. 따라서

소스파일에 정의해야하며 헤더 파일은 ‘extern’ 수식자로 선언해 참조만 하도록 합니다.

// ‘StringConstant.m’ 파일

#import "StringContant.h"

// ‘MyIdentifier’라는 이름의 문자열 상수를 정의함

NSString *MyIdentifier = @"MyIdentifier";

// ‘StringConstant.h’ 파일

#import <Cocoa/Cocoa.h>

// ‘MyIdentifier’라는 이름의 상수를 참조함

extern NSString *MyIdentifier;

Page 71: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

71

S E C T I O N - 0 1 4 상수

// main.m 파일

#import <Foundation/Foundation.h>

#import "StringContant.h"

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// 정의한 상수를 사용할 때는 문자열 대신 상수명을 씀

NSLog(@"Constant=%@", MyIdentifier);

[pool drain];

return 0;

}

코드에서 상수와 변수를 구분하기 위해 상수 이름을 붙이는 몇 가지 방법 중 Mac OS X용 소프트

웨어를 개발할 때 자주 사용하는 3가지 명명규칙은 다음과 같습니다.

• 소문자 ‘k’로 시작하며 단어를 구분할 때 대문자를 사용 (예: ‘kMyIdentifier’ )

• 모두 대문자로 적고 단어를 구분할 때에 ‘_’를 사용 (예: ‘MY_IDENTIFIER’ )

• 앞에 프로젝트 단위의 접두어를 붙이고 단어를 구분할 때 대문자를 사용

(예: ‘NSOrderedSame’ )

이렇게 이름을 붙이는 방식을 ‘명명규칙’이라고 합니다.

Foundation 프레임워크에서는 앞에 프로젝트 단위의 접두어를 붙인 후 단어를 구분할 때 대문자

를 사용하는 방법을 씁니다. Carbon 프레임워크에서는 소문자 ‘k’로 시작해 단어를 구분할 때 대

문자를 사용하는 방법을 씁니다. 어떤 방법을 사용해도 상관없지만 개발프로젝트팀이나 회사에서

정한 표준 방식이 있다면 그 규칙에 따르면 됩니다.

COLUMN 상수의 명명규칙

관련 항목 fff

• 전처리 지시자 ····························································· p.81

• ‘불변’ 클래스와 ‘가변’ 클래스 ··············································· p.126

Page 72: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

72

SECTION-015 VER. 1.0 2.0

주석

� 주석의 기술방법

주석은 프로그램에 작성해도 컴파일러에서는 무시되는 부분입니다. Objective-C 코드는

다른 언어와 비교했을 때 나중에 봐도 의미 파악이 쉬운 편이기는 하지만 각 코드가 어떤 역

할을 하며 어떤 목적의 코드인지 등의 전제조건을 주석으로 남겨두면 유지보수가 간편해집

니다.

Objective-C에서 주석을 다는 방법에는 2종류가 있습니다.

• ‘//’ 라고 적은 부분부터 줄 끝까지가 주석이 됨(이 책에서는 이 방식의 주석을 사용)

• ‘/*’ 에서 ‘*/’ 까지가 주석이 됨

int a = 10; // 이 이후는 줄 끝까지 주석이므로 무시됨

int b = 20; /* 이 부분은 주석이므로 무시됨 */

/*이 줄은 주석이므로 무시됨

이런 식으로 주석을 달면 여러 줄에 걸쳐 표기할 수 있음

/*

프로그램 코드에서 특정한 규칙에 따라 주석을 작성하면 작성한 주석을 읽어들여 문서로 만들

어주는 프로그램이 있습니다. 이런 프로그램으로는 Xocde의 스크립트를 지원하는 Doxygen,

HeaderDoc 등이 있으며 이 책에서는 Doxygen의 사용법을 알아보겠습니다.

f Doxygen 설치

Doxygen 홈페이지(http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc)에서 디스

크 이미지 파일을 내려받은 후 설치합니다. 이 책에서는 Doxygen-1.8.1.1.dmg를 내려받았습니다.

f 코드에 주석 작성하기

자동문서화할 프로젝트를 생성한 후 Doxygen 형식에 맞춰 주석을 달아줍니다. 주석 스타일은

JavaDoc와 유사하므로 JavaDoc을 사용해 본 사용자라면 쉽게 적응할 수 있습니다. Doxygen의

주석 사용법은 Doxygen 홈페이지의 메뉴얼을 참고하기 바랍니다.

COLUMN Doxygen

Page 73: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

73

S E C T I O N - 0 1 5 주석

f Doxygen을 이용해 문서 만들기

� Doxygen

Doxygen을 실행한 후 각 항목을 입력합니다.

working directory : Doxygen이 작업할 공간을 지정

• Project

- Project name : 프로젝트명

- Project version : 프로젝트 버전

- Source code directory : 프로젝트 소스 코드 위치

- Destination directory : 최종 결과 파일의 저장 위치

• Mode

- extraction mode : 모드 설정

- programming language : 언어 설정

(이 책에서는 All Entities 모드, Optimize for C++ output을 선택했습니다)

• Output

- output format to generate : 결과 문서의 형식

각 항목을 알맞게 선택한 뒤 Step 2 아래의 Run 탭을 클릭합니다.

Page 74: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

74

S E C T I O N - 0 1 5 주석

f Doxygen으로 생성한 문서 확인하기

Project에서 지정한 경로에 생성된 index.html 파일을 열거나 Run 탭의 Show HTML output을

클릭하면 문서화된 웹 페이지를 확인할 수 있습니다.

� Doxygen으로 생성한 문서

Page 75: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

75

SECTION-016 VER. 1.0 2.0

조건분기

� 조건분기의 종류

조건분기는 프로그램 코드에서 매우 중요한 구문입니다. Objective-C에는 예약어 ‘if’와

‘switch’를 사용한 조건분기가 있습니다.

f ‘if’를 사용한 조건 분기

‘if’는 조건식이 ‘참’일 때만 실행되는 조건분기로 다음과 같이 구현합니다.

if (조건식1){ 조건식1이 ‘참’일 때 실행되는 코드

}else if (조건식2){ 조건식2가 ‘참’일 때 실행되는 코드

}else{ 조건식1과 조건식2가 모두 ‘거짓’일 때 실행되는 코드

}

‘else if’나 ‘else’를 생략할 수도 있으며 ‘else if’를 여러 번 사용할 수도 있습니다. 각 조건에서

실행되는 코드를 ‘{’와 ‘}’로 둘러싸서 표기하는데 이를 생략하면 한 단계만 실행됩니다.

다음 코드는 ‘if’문의 조건분기를 사용해 카운터 값이 짝수일 때는 대문자를 출력하고 홀수

일 때는 소문자로 알파벳을 출력하는 코드입니다.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]){ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// 대문자와 소문자를 교대로 바꾸면서 알파벳을 출력함

int i; for (i = 0; i < 26; i++) { // 짝수일 때는 대문자로 출력함

if ((i % 2) == 0) printf("%c", 'A' + i); else printf("%c", 'a' + i); } [pool drain]; return 0;}

Page 76: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

76

S E C T I O N - 0 1 6 조건분기

이 코드를 실행한 결과는 다음과 같습니다.

AbCdEfGhIjKlMnOpQrStUvWxYz

f ‘switch’를 사용한 조건분기

상수를 열거한 조건분기일 때 사용하며 조건식의 값에 따라 조건분기를 실행합니다.

switch (조건식)

{

case 값1:

조건식의 값이 1일 때 실행할 코드

break;

case 값2:

조건식의 값이 2일 때 실행할 코드

break;

default:

조건식의 값이 ‘case’에서 정의한 어떤 값과도 일치하지 않을 때 실행할 코드

break;

}

각 값은 ‘case’문에 기술하며 각 ‘case’문은 ‘break’문을 만날 때까지 실행됩니다. 따라서

‘break’문을 입력하지 않으면 그 아래의 ‘case’문도 실행되므로 주의해야 합니다. 이는 장

점이기도 하며 단점이기도 합니다. 의도적으로 ‘break’문을 넣지 않을 때도 있습니다. 또한

‘default’문에서의 ‘break’문은 필수사항은 아니지만 필자는 코드를 쉽게 파악하려고 입력하

고 있습니다.

다음 코드는 ‘switch’를 사용해 카운터의 값을 3으로 나눈 나머지에 따라 출력하는 문자열

을 바꾼 코드입니다.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])

{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

int i;

for (i = 0; i < 5; i++)

{

// 3으로 나눈 나머지에 따라 출력하는 문자열을 변경시킴

switch (i % 3)

{

Page 77: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

77

S E C T I O N - 0 1 6 조건분기

case 0: // 0 일 때

NSLog(@"Zero");

break;

case 1: // 1 일 때

NSLog(@"One");

break;

case 2: // 2 일 때

NSLog(@"Two");

break;

}

}

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-16 20:35:48.390 Switch[584:a0f] Zero

2010-01-16 20:35:48.393 Switch[584:a0f] One

2010-01-16 20:35:48.393 Switch[584:a0f] Two

2010-01-16 20:35:48.393 Switch[584:a0f] Zero

2010-01-16 20:35:48.394 Switch[584:a0f] One

Page 78: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

78

SECTION-017 VER. 1.0 2.0

반복문(루프)

� 반복문의 종류

Objective-C에는 4종류의 반복문이 있습니다. 어떤 반복문을 사용해도 처리방법과 결과는

같지만 서로 다른 특징이 있으므로 용도에 따라 구분해서 쓰면 알기 쉬운 코드를 작성할 수

있습니다.

f ‘for’를 사용한 반복문

‘for’를 사용한 반복문은 ‘초기화’, ‘반복할 조건식’, ‘반복해서 실행할 코드’의 세 가지를 한 번

에 지정할 수 있습니다. 필자는 반복횟수가 정해졌을 때는 ‘for’문을 사용하고 있습니다.

for (초기화; 조건식; 각 반복 후에 반복할 코드)

{

반복할 코드

}

예를 들어, 변수 ‘x’를 카운터로 10회 반복할 때는 다음과 같이 기술합니다.

for (x = 0; x < 10; x++)

{

반복할 코드

}

‘for’를 사용한 반복문에서 중간에 반복을 중단하고 싶을 때도 있습니다. 예를 들어 실행

중인 코드에서 에러가 발생할 때입니다. 이럴 때는 ‘break’문을 사용합니다. 다음 예는 함수

‘getStatus’의 반환값이 음수일 때 반복을 중단하는 코드입니다.

for (x = 0; x < 10; x++)

{

if (getStatus() < 0)

break;

...

}

Page 79: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

79

S E C T I O N - 0 1 7 반복문(루프)

f ‘while’을 사용한 반복문

‘while’을 사용한 반복문에서는 반복할 조건식만 지정합니다. 카운터 값이 불규칙적으로 변

할 때나 반복을 시작하기 전에 반복횟수를 정확히 알 수 없을 때 사용합니다.

while (조건식)

{

반복할 코드

}

예를 들어 다음 코드는 함수 ‘getStatus’의 반환값이 0 이상일 때 반복되는 코드입니다.

while (getStatus() >= 0)

{

반복할 코드

}

‘while’을 사용한 반복문도 ‘for’를 사용한 반복문과 마찬가지로 ‘break’문으로 중단할 수 있

습니다.

f ‘do’~‘while’을 사용한 반복문

‘while’을 사용한 반복문을 약간 변형한 형태로 ‘do’를 함께 쓰는 방식이 있습니다.

do

{

반복할 코드

} while (조건식);

‘while’만 사용한 반복문과 다른 점은 조건식을 판단하는 시점입니다. ‘while’만 사용한 반복

문에서는 조건식을 처음에 판단합니다. 따라서 코드가 한 번도 실행되지 않고 반복문을 빠져

나갈 수도 있습니다. 이에 반해 ‘do’를 사용한 반복문은 조건식을 마지막에 판단합니다. 따라

서 처음부터 조건식이 ‘거짓’이더라도 반복 코드가 적어도 1번은 실행됩니다. 어느 방식이 더

좋다고 단정 지을 수는 없습니다. 사용할 상황에 따라 알기 쉽고 적합한 방식을 사용하는 것

이 좋습니다.

f ‘for’~‘in’을 사용한 반복문

Objective-C 2.0부터 도입된 반복문으로 ‘고속열거’라고도 합니다. Objective-C 컬렉션 클래

스의 엘리먼트를 열거하는 데만 사용할 수 있습니다.

Page 80: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

80

S E C T I O N - 0 1 7 반복문(루프)

for (엘리먼트를받을변수 in 컬렉션클래스의인스턴스)

{

반복할 코드

}

자세한 사항은 <고속열거를 사용해 배열이나 세트에서 순서대로 오브젝트 취득하기>

(p.273)를 참조하기 바랍니다.

COLUMN 무한 반복

프로그램 코드에서 무한 반복을 사용하고 싶을 때도 있습니다. 무한 반복이라고는 해도 특정 조건

이 갖춰지면 반복문을 벗어나게 됩니다. 벗어날 조건이 없는 무한 반복이 발생하면 프로그램은 멈

춰 버립니다. 무한 반복에도 ‘for’문을 사용하는 방법과 ‘while’문을 사용하는 방법이 있습니다. 어

떤 방법을 사용할지는 사용자의 취향에 따라 선택하면 됩니다. 팀에서 결정한 규칙이 있다면 규칙

을 따르기 바랍니다.

for(;;) // 초기화, 조건식, 매번 실행할 코드 모두 지정하지 않음

{

반복할 코드

if (조건식)

break;

}

while (1) // 항상 ‘참’이 되게 1을 지정함

{

반복할 코드

if (조건식)

break;

}

관련 항목 fff

• 고속열거를 사용해 배열이나 세트에서 순서대로 오브젝트 취득하기 ··············· p.273

• 고속열거를 사용해 배열에서 역순으로 오브젝트 취득하기 ······················· p.278

• 포인터 배열에서 순서대로 오브젝트 취득하기 ·································· p.749

Page 81: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

81

SECTION-018 VER. 1.0 2.0

전처리 지시자

� Objective-C의 전처리 지시자

전처리 지시자(preprocessor directive)는 컴파일러가 소스 파일을 컴파일할 때 실행되는 명

령문입니다. 전처리 지시자는 프로그램이 실행될 때가 아니라 컴파일할 때에 실행된다는 점

이 중요합니다. 따라서 C 언어와 Objective-C 양쪽에서 참조되는 헤더 파일을 Objective-C일

때만 정의되도록 사용할 수도 있습니다. 또한 헤더 파일을 읽어들이는 작업도 전처리 지시자

에서 실행합니다.

f헤더 파일 읽어들이기

헤더 파일 읽어들이기는 C 언어와 마찬가지로 ‘#include’를 사용할 수도 있지만 Objective-C

에서는 ‘#import’를 사용합니다. ‘#include’와 ‘#import’의 차이점은 ‘#include’는 정해진 횟수

만큼만 읽어들이고 ‘#import’는 한 번만 읽어들인다는 점입니다. 따라서 ‘#import’로 읽어들

일 때는 C의 헤더 파일에서 사용하는 ‘인클루드 가드’(include guard)는 필요 없습니다.

#import <Foundation/Foundation.h>

f매크로 정의

상수의 정의나 컴파일할 때 치환되는 매크로를 정의하기 위한 전처리 지시자로는 ‘#de�ne’을

사용합니다. ‘#de�ne’으로 정의한 매크로를 정의되지 않은 상태로 되돌리려면 ‘#undef’를 사

용합니다.

#define MaxFileCount 10 // MaxFileCount를 10으로 정의함

#undef MaxFileCount // MaxFileCount의 정의를 삭제함

f전처리 지시자를 사용한 분기문

전처리 지시자에서 정의한 매크로를 사용해 분기를 실행할 수 있습니다.

Page 82: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

82

S E C T I O N - 0 1 8 전처리 지시자

#if 조건식1

조건식1이 ‘참’일 때의 코드

#elif 조건식2

조건식2가 ‘참’일 때의 코드

#else

조건식1과 조건식2 모두가 ‘거짓’일 때의 코드

#endif

‘#elif’와 ‘#else’는 필요 없으면 생략할 수도 있으며 ‘#elif’는 여러 번 사용할 수도 있습니다.

전처리 지시자의 조건식에는 프로그램 코드의 함수나 변수는 사용할 수 없습니다. 조건식도

전처리 지시자에서 정의한 매크로나 상수만 사용해야 합니다. 조건식에 ‘de�ned’를 사용하

면 매크로가 정의됐는지를 판단합니다.

#if defined(__OBJC__)

Objective-C의 경우(‘ __OBJC__’가 정의돼 있을 때)의 코드

#endif

f전처리 지시자의 축약형

전처리 지시자의 축약형은 다음 표를 참조하기 바랍니다.

축약형 축약되기 전

#ifdef A #if defined(A)

#ifndef A #if !defined(A)

Page 83: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

83

S E C T I O N - 0 1 8 전처리 지시자

매크로 중에는 컴파일러에서 정의하고 있는 것도 있습니다. 따라서 컴파일러가 코드를 변경해 주

는 처리도 할 수 있습니다. 자주 사용되는 매크로는 다음과 같습니다.

매크로 설명

__OBJC__ Objective-C 컴파일러일 때 정의됨

__cplusplus C++인 경우에 정의됨. Objective-C++에서도 정의됨

예를 들어 C 언어, C++, Objective-C에서 공통으로 읽어들이는 헤더 파일이 있다고 한다면 읽

어들이는 컴파일러에 따라 사용할 수 없는 정의를 읽어들이지 않게 하려면 다음과 같이 기술할 수

있습니다.

#ifdef __cplusplus

// C++ 전용 정의

class CppClass {

};

#endif

#ifdef __OBJC__

// Objective-C 전용 정의

extern NSString *MyTableIdentifier;

#endif

#ifdef __cplusplus

extern "C" {

#endif

/* C 언어, C++, Objective-C 모두 참조할 수 있는 정의*/

void doSomething();

#ifdef __cplusplus

}

#endif

COLUMN 컴파일러 정의가 끝난 매크로

관련 항목 fff

• 상수 ······································································ p.68

Page 84: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

84

SECTION-019 VER. 1.0 2.0

클래스 정의와 메서드 정의

� Objective-C의 클래스 정의

Objective-C의 클래스 정의는 ‘인터페이스 선언’과 ‘구현코드’로 구성됩니다. ‘인터페이스 선

언’은 일반적으로 헤더 파일에 기술하며 구현코드는 소스 파일에 기술합니다.

f인터페이스 선언

인터페이스 선언에서는 클래스명, 부모클래스, 인터페이스 변수의 정의, 메서드의 선언을 포

함할 수 있으며 ‘@interface’부터 ‘@end’ 사이에 기술합니다. 메서드는 여기서 선언하지 않더

라도 호출할 수 있지만 외부에서 항상 호출되는 메서드를 선언해 두면 호출한 쪽의 코드에서

오타가 났을 때 컴파일러가 경고를 표시하므로 금방 발견할 수 있습니다. 또한 클래스를 선

언할 때 부모클래스의 ‘인터페이스 선언’이 필요하므로 부모클래스의 헤더 파일을 읽어오게

됩니다.

#import "부모클래스의 인터페이스 선언이 들어간 헤더 파일"

@interface 클래스명 : 부모클래스명

{

인터페이스 변수의 정의

}메서드의 선언

@end

예를 들어 다음과 같이 선언합니다.

@interface MyController : NSObject

{

int _data0;

int _data1;

}

- (int)myFunction;

@end

이 예에서는 ‘MyController’라는 클래스를 ‘NSObject’ 클래스의 자식클래스로 생성하고 인

스턴스변수로 ‘_data0’과 ‘_data1’을 정의했습니다. 또 인스턴스 메서드로 ‘myFunction’을 선

언했습니다.

인스턴스 변수의 명칭 앞에 ‘_’가 붙어 있는데 이는 정해진 규칙은 아닙니다. 필자는 인스턴

스 변수와 로컬 변수를 구분하기 위해 인스턴스 변수 앞에 ‘_’를 붙입니다. ‘Foundation’ 프레

Page 85: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

85

S E C T I O N - 0 1 9 클래스 정의와 메서드 정의

임워크의 ‘NSURL’ 클래스 등에서도 마찬가지로 인스턴스 변수의 앞에 ‘_’를 붙이지만 다른

클래스에서는 붙이지 않을 때도 있습니다. 개발팀에서 자체적으로 통일된 규칙을 결정하면

됩니다.

f클래스의 구현코드

클래스의 구현코드에는 그 클래스의 인스턴스 메서드와 클래스 메서드를 구현합니다. 다음

과 같이 ‘@implementation’부터 ‘@end’ 사이에 기술합니다.

@implementation 클래스명

인스턴스 메서드와 클래스 메서드의 구현코드

@end

예를 들어 앞의 ‘인터페이스 선언’ 예제코드에서 선언한 인터페이스의 ‘구현코드’는 다음과

같습니다.

@implementation MyController

- (int)myFunction

{

return 0;

}

@end

f부모클래스의 필요성

부모클래스가 없는 클래스도 정의할 수는 있습니다. 하지만 Objective-C는 ‘NSObject’ 클래

스가 제공하는 기능의 많은 부분에 의존하므로 ‘NSObject’ 클래스로부터 상속받고 있음을

전제로 하고 있습니다. 따라서 특별히 부모클래스가 필요 없을 때는 ‘NSObject’ 클래스를 지

정하면 됩니다.

� Objective-C의 메서드 정의

Objective-C의 메서드는 반드시 클래스에 포함돼야 합니다. 클래스에 속하지 않을 때는 C 언

어의 함수로서 구현됩니다.

Page 86: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

86

S E C T I O N - 0 1 9 클래스 정의와 메서드 정의

f메서드 정의 구문

메서드 정의에는 다음과 같은 구문을 사용합니다.

// 파라미터가 없을 때

-(반환형) 메서드명;

// 파라미터가 하나일 때

-(반환형) 메서드명:(파라미터 1의 타입)파라미터1;

// 파라미터가 둘일 때

-(반환형) 메서드명:(파라미터1의 타입)파라미터1

파라미터2의 라벨:(파라미터2의 타입)파라미터2;

‘반환형’ 앞의 ‘–’ 기호는 인스턴스 메서드임을 의미하며, 클래스 메서드일 때는 ‘+’ 기호를

사용합니다. 파라미터가 3개 이상이라면 ‘파라미터의 라벨 : (파라미터의 타입) 파라미터’를

반복합니다. 다음 코드는 파라미터가 없을 때, 파라미터가 하나일 때, 파라미터가 둘일 때의

‘인터페이스 선언’과 ‘구현코드’의 예시입니다.

@interface MyController

{

}

- (void)methodWithoutParameter;

- (void)methodWithOneParameter:(int)param1;

- (void)methodWithOneParameter:(int)param1

twoParameter:(int)param2;

@end

@implementation MyController

- (void)methodWithoutParameter

{

}

- (void)methodWithOneParameter:(int)param1

{

}

- (void)methodWithOneParameter:(int)param1

twoParameter:(int)param2

{

}

@end

Page 87: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

87

S E C T I O N - 0 1 9 클래스 정의와 메서드 정의

f인스턴스 메서드와 클래스 메서드

메서드에는 ‘인스턴스 메서드’와 ‘클래스 메서드’ 두 종류가 있습니다. ‘인스턴스 메서드’는 인

스턴스와 연결된 메서드로 인스턴스화하지 않으면 사용할 수 없지만 인스턴스 변수를 사용

할 수 있습니다. ‘클래스 메서드’는 클래스와 연결된 메서드로 특정 인스턴스에 연결되어 있지

않으므로 인스턴스 변수를 사용할 수는 없지만 인스턴스화하지 않고 사용할 수 있습니다.

‘클래스 메서드’는 인스턴스화하지 않고 사용할 수 있는 특징이 있으므로 특정 인스턴스와

관계없는 유틸리티적인 처리를 구현할 때 사용하면 좋습니다. 반대로 특정 인스턴스를 통한

처리는 ‘인스턴스 메서드’로 구현할 것을 추천합니다.

f메서드 호출

메서드의 호출은 다음과 같이 구현합니다.

// 파라미터가 없을 때

[리시버 메서드명];

// 파라미터가 하나일 때

[리시버 메서드명:파라미터];

// 파라미터가 둘일 때

[리시버 메서드명:파라미터1

파라미터2의 라벨:파라미터2];

파라미터가 3개 이상일 때는 ‘파라미터의 라벨 : 파라미터’를 반복합니다. ‘리시버’는 메서드

호출을 받는 오브젝트를 지정합니다. ‘인스턴스 메서드’라면 인스턴스를 지정하고 ‘클래스 메

서드’라면 클래스명을 지정합니다. Objective-C는 메서드의 반환값으로 Objective-C 클래스

의 인스턴스를 반환할 때가 많아서 반환값을 그대로 ‘리시버’로 사용할 때도 있습니다.

[[리시버 메서드명] 메서드명];

다음 예제코드는 ‘NSString’ 클래스 메서드를 호출하는 코드입니다.

// ‘stringWithString’이라는 클래스 메서드를 호출

NSString *str = [NSString stringWithString:@"The String];

// ‘uppercaseString’이라는 인스턴스 메서드를 호출

NSString *str2 = [str uppercaseString];

// ‘substringWithRange’ 메서드의 반환값을 ‘리시버’로 하여

// ‘uppercaseString’ 메서드를 호출

NSString *str3 = [[str subStringWithRange:NSMakeRange(0, 3)]

uppercaseString];

Page 88: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

88

S E C T I O N - 0 1 9 클래스 정의와 메서드 정의

f메서드의 재정의

메서드는 상속받은 클래스에서 재작성할 수 있습니다. 이렇게 상속받은 클래스에서 메서드

를 재작성해서 독자적인 처리를 하는 것을 ‘메서드 재정의(오버라이드)’라고 합니다. 이 클래

스를 사용하는 쪽은 부모클래스의 메서드를 호출할지 상속받은 클래스에서 재정의한 메서

드를 호출할지를 구분하여 메서드를 호출합니다. 상속받은 클래스에서 메서드를 재정의했

다면 상속받은 클래스의 메서드를 호출합니다.

메서드를 재정의 하려면 재정의할 클래스와 같은 이름의 메서드를 정의해 구현합니다. 또

한 Objective-C에서는 인스턴스 메서드뿐만 아니라 클래스 메서드도 재정의할 수 있습니다.

#import <Foundation/Foundation.h>

@interface Parent : NSObject{}- (void)log;@end

@interface Sub : Parent{}@end

@implementation Parent

- (void)log{ NSLog(@"Parent");}

@end

@implementation Sub

- (void)log{ NSLog(@"Sub");}

@end

int main (int argc, const char *argv[]){ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; id p1 = [[[Parent alloc] init] autorelease]; id p2 = [[[Sub alloc] init] autorelease]; [p1 log]; // - [Parent log]가 호출됨

[p2 log]; // - [Sub log]가 호출됨

[pool drain]; return 0;}

Page 89: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

89

S E C T I O N - 0 1 9 클래스 정의와 메서드 정의

이 코드를 실행하면 콘솔 윈도우에 다음과 같이 출력되며 재정의 된 메서드가 호출됐음을

알 수 있습니다.

2009-09-23 18:35:48.179 MethodOverride[3576:a0f] Parent

2009-09-23 18:35:48.182 MethodOverride[3576:a0f] Sub

f메서드 자신의 오브젝트 메서드를 호출

메서드 자신의 오브젝트 메서드를 호출하려면 리시버로 ‘self’를 사용합니다.

[self method1];

메서드가 인스턴스 메서드라면 ‘self’는 인스턴스가 되며, 메서드가 클래스 메서드라면 ‘self’

는 클래스가 됩니다.

f상속해 준 클래스의 메서드 호출

재정의한 메서드에서 재정의하기 전에 상속해 준 클래스 메서드를 호출하려면 다음과 같이

합니다.

[super method1];

이렇게 ‘super’ 키워드를 사용하면 상속해 준 클래스의 ‘method1’ 메서드를 호출합니다. 만

일 상속 받은 클래스에서 ‘method1’ 메서드를 재정의하고 있어도 부모 클래스의 ‘method1’

이 호출됩니다.

Objective-C는 메서드가 존재하는지 여부를 실행할 때 판단합니다. 따라서 빌드할 때는 구현되지

않은 메서드를 호출하는 코딩을 해도 에러가 발생하지 않습니다.

하지만 구현되지 않은 메서드가 호출되는 시점에 Objective-C의 런타임은 예외를 발생시키고 콘

솔에는 다음과 같은 로그가 출력됩니다.

2009-09-23 18:41:11.439 MethodOverride[3612:a0f] -[Sub log2]: unrecognized selector sent

to instance 0x10010cb80

이 로그는 ‘Sub’ 클래스의 ‘log2’ 인스턴스 메서드를 호출하려고 했으나 ‘Sub’ 클래스에 ‘log2’ 메

서드가 구현되어 있지 않음을 나타냅니다. 이렇게 되면 코드는 예외를 발생시킨 코드 이후를 실행

하지 않고 그대로 예외 처리로 이동합니다.

COLUMN 구현되지 않은 메서드를 호출하면 예외가 발생한다

Page 90: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

90

S E C T I O N - 0 1 9 클래스 정의와 메서드 정의

관련 항목 fff

• 프로토콜 정의 ····························································· p.91

• 카테고리 정의 ····························································· p.98

• 프로퍼티 정의 ····························································· p.102

• 예외 처리 ································································· p.112

Page 91: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

91

SECTION-020 VER. 1.0 2.0

프로토콜 정의

� Objective-C의 프로토콜 정의

‘프로토콜 정의’는 메서드만을 정의하는 즉 인터페이스를 정의하는 기능입니다. 클래스와 다

른 점은 클래스는 하나의 틀이 되지만 프로토콜은 틀이 아닌 일련의 메서드를 선언한다는 점

입니다.

f정의 방법

프로토콜의 선언 방법은 다음과 같습니다.

@protocol 프로토콜명

메서드 정의

@end

다른 프로토콜을 따르는 프로토콜의 선언 방법은 다음과 같습니다.

@protocol 프로토콜명 <프로토콜 리스트>

메서드 정의

@end

프로토콜을 따르는 클래스의 선언 방법은 다음과 같습니다.

@interface 클래스명 : 부모클래스명 <프로토콜 리스트>

{

인스턴스 변수 정의

}메서드 정의

@end

프로토콜을 따르고 카테고리가 추가된 클래스의 선언 방법은 다음과 같습니다.

@interface 클래스명 (카테고리명) <프로토콜 리스트>

메서드 정의

@end

Page 92: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

92

S E C T I O N - 0 2 0 프로토콜 정의

프로토콜 리스트에는 여러 개의 프로토콜을 선언할 수 있으며 ‘,’(콤마)로 구분해 프로토

콜을 열거합니다. 특정 프로토콜을 지원하는 ‘id’ 타입의 변수를 정의하는 방법은 다음과 같

습니다.

id <프로토콜명> 변수명

f예문

다음 코드는 프로토콜을 사용한 예제입니다.

#import <Foundation/Foundation.h>

//프로토콜을 정의함

@protocol MyCallbackProtocol <NSObject>- (int)doCalc:(int)num;@end

// ‘MyClass1’ 클래스에서 ‘MyCallbackProtocol’ 프로토콜을 따른다고 선언

@interface MyClass1 : NSObject <MyCallbackProtocol>{}@end

// ‘MyClass2’ 클래스에서 ‘MyCallbackProtocol’ 프로토콜을 따른다고 선언

@interface MyClass2 : NSObject <MyCallbackProtocol>{}@end

// ‘MyClass1’ 클래스 구현

@implementation MyClass1- (int)doCalc:(int)num{ return (num * num);}@end

// ‘MyClass2’ 클래스 구현

@implementation MyClass2- (int)doCalc:(int)num{ return (num * num * num);}@end

// 메인 함수

int main (int argc, const char *argv[]){ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // ‘MyCallbackProtocol’ 프로토콜을 포함한 인스턴스 배열을 정의

id<MyCallbackProtocol> cbs[] = { [[[MyClass1 alloc] init] autorelease], [[[MyClass2 alloc] init] autorelease]

Page 93: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

93

S E C T I O N - 0 2 0 프로토콜 정의

};

// 배열의 각 엘리먼트에서 메서드를 호출

int i;

for (i = 0; i < 2; i++)

{

// 인스턴스의 클래스와 관계없이 ‘MyCallbackProtocol’을 구현하고 있다면

// ‘doCalc:’ 메서드를 갖고 있으므로 그것을 호출

int j = [cbs[i] doCalc:4];

NSLog(@"%d", j);

}

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같으며 각 클래스에서 구현한 ‘doCalc:’ 메서드가 호출됐

음을 알 수 있습니다.

2009-09-24 18:56:37.639 Protocol[606:a0f] 16

2009-09-24 18:56:37.641 Protocol[606:a0f] 64

이 코드는 프로토콜을 정의하고 이 프로토콜을 두 클래스로 구현한 예입니다. 이 코드에서

주목할 점은 ‘main’ 함수에서 ‘doCalc:’ 메서드를 호출하는 부분입니다. 여기서 사용한 첫 번

째 인스턴스는 ‘MyClass1’ 클래스의 인스턴스이며 두 번째 인스턴스는 ‘MyClass2’ 클래스의

인스턴스입니다. 프로토콜을 사용하지 않고 클래스에서 ‘doCalc:’ 메서드를 정의하면 모두

공통의 부모 클래스를 갖게 되며 그 부모 클래스가 ‘doCalc:’ 메서드를 가져야 합니다. 하지

만 프로토콜에서 ‘doCalc:’ 메서드를 선언하고 ‘doCalc:’메서드를 클래스 쪽에서 ‘구현한다’고

선언하면 ‘doCalc:’ 메서드를 가진 공통의 부모클래스로부터 상속받을 필요가 없고 메서드의

구현만으로 사용할 수 있게 됩니다.

하지만 실제로 Objective-C는 메서드가 있는지를 실행할 때 판단하므로 프로토콜을 정의

하지 않아도 사용할 수 있습니다. 그렇다면 프로토콜을 정의해서 얻는 장점으로는 오타 때문

에 메서드가 제대로 구현되지 않았을 때 컴파일 단계에서 이를 검출할 수 있다는 점과 프로

토콜을 포함한 인스턴스를 사용하는 코드에서 각 인스턴스에 대한 클래스를 선언할 필요가

없다는 점입니다. 클래스에 관계없이 특정 메서드만을 규정함으로써 클래스 계층에 제한받

지 않는 유연한 설계를 할 수 있습니다.

또한 이 코드는 ‘MyCallbackProtocol’ 프로토콜이 ‘NSObject’ 프로토콜을 구현한다고 선언

하고 있습니다. 그 이유는 ‘alloc’ 메서드 등이 ‘NSObject’ 프로토콜에 정의되어 있으므로 이

선언을 넣지 않으면 인스턴스 ‘id<MyCallbackProtocol>’가 ‘alloc’ 메서드를 호출할 때 컴파

일러로부터 경고의 대상이 되기 때문입니다.

Page 94: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

94

S E C T I O N - 0 2 0 프로토콜 정의

f프로토콜에 적합한지 여부 판단

특정 인스턴스가 프로토콜에서 정의한 메서드를 구현하고 있는지 알아보려면 다음 두 가지

방법을 사용합니다.

• ‘conformsToProtocol:’ 메서드를 사용

• 호출하려는 메서드를 가졌는지 하나씩 확인

필자의 경험으로는 두 번째 방법이 대체로 안정적이었습니다. 특히 개발이 장기화되어 여

러 버전을 사용하거나 개발자가 바뀔 수도 있으므로 첫 번째 방법은 충분치 않다고 느꼈습니

다. 개발 도중에 프로토콜에 메서드를 추가하는 경우 ‘구현 누락’이 생길 수도 있었습니다. 나

중에 추가한 메서드는 이전에 구현된 코드에서는 필요없는 경우가 많아, 그런 때에는 ‘없다면

아무것도 하지 않는’ 동작이 바람직할 경우가 많았습니다. 이때 첫 번째 방법이 충분치 않은

이유는 다음과 같은 코드를 실행해 보면 쉽게 알 수 있습니다.

#import <Foundation/Foundation.h>

// 프로토콜을 정의

@protocol MyCallbackProtocol <NSObject>

- (int)doCalc:(int)num;

@end

// ‘MyClass1’ 클래스에서 ‘MyCallbackProtocol’ 프로토콜을 포함하고 있음을 선언

@interface MyClass1 : NSObject <MyCallbackProtocol>

{

}

@end

// ‘MyClass2’ 클래스는 프로토콜을 선언하지 않음

@interface MyClass2 : NSObject

{

}

@end

// ‘MyClass3’ 클래스는 프로토콜을 지원하지 않음

@interface MyClass3 : NSObject

{

}

@end

// ‘MyClass4’ 클래스에서 ‘MyCallbackProtocol’ 프로토콜을 포함하고 있음을 선언

@interface MyClass4 : NSObject <MyCallbackProtocol>

{

}

@end

Page 95: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

95

S E C T I O N - 0 2 0 프로토콜 정의

// ‘MyClass1’ 클래스를 구현

@implementation MyClass1- (int)doCalc:(int)num{ return (num * num);}@end

// ‘MyClass2’ 클래스를 구현

@implementation MyClass2- (int)doCalc:(int)num{ return (num * num * num);}@end

// ‘MyClass3’ 클래스를 구현

@implementation MyClass3@end

// ‘MyClass4’ 클래스를 구현

// ‘MyCallbackProtocol’ 프로토콜을 구현한다고 선언했으나

// 필요한 메서드를 구현하지 않음

@implementation MyClass4@end

// 메인 함수

int main (int argc, const char *argv[]){ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // ‘MyCallbackProtocol’ 프로토콜을 구현한 인스턴스의 배열을 정의

id<MyCallbackProtocol> cbs[] = { [[[MyClass1 alloc] init] autorelease], [[[MyClass2 alloc] init] autorelease], [[[MyClass3 alloc] init] autorelease], [[[MyClass4 alloc] init] autorelease] }; // 각 인스턴스가 프로토콜에 적합한지 조사

int i; for (i = 0; i < 4; i++) { Protocol *protocol = @protocol(MyCallbackProtocol); BOOL b = [cbs[i] conformsToProtocol:protocol]; NSLog(@"instance %d conforms to protocol : %d", i, b); b = [cbs[i] respondsToSelector:@selector(doCalc:)]; NSLog(@"instance %d responds to selector : %d", i, b); } [pool drain];

return 0;

}

Page 96: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

96

S E C T I O N - 0 2 0 프로토콜 정의

이 코드에서는 네 개의 클래스를 정의하고 각 클래스의 인스턴스를 생성해서 그 인스턴스

가 프로토콜에 적합한지와 ‘doCalc:’ 메서드를 구현하고 있는지를 조사하고 있습니다.

이 코드를 실행한 결과는 다음과 같습니다.

2009-09-24 19:13:02.197 Protocol2[795:a0f] instance 0 conforms to protocol : 1

2009-09-24 19:13:02.200 Protocol2[795:a0f] instance 0 responds to selector : 1

2009-09-24 19:13:02.201 Protocol2[795:a0f] instance 1 conforms to protocol : 0

2009-09-24 19:13:02.201 Protocol2[795:a0f] instance 1 responds to selector : 1

2009-09-24 19:13:02.202 Protocol2[795:a0f] instance 2 conforms to protocol : 0

2009-09-24 19:13:02.202 Protocol2[795:a0f] instance 2 responds to selector : 0

2009-09-24 19:13:02.202 Protocol2[795:a0f] instance 3 conforms to protocol : 1

2009-09-24 19:13:02.203 Protocol2[795:a0f] instance 3 responds to selector : 0

첫 번째 인스턴스는 ‘MyClass1’ 클래스의 인스턴스입니다. 이 클래스는 ‘MyCallbackProtocol’

프로토콜을 따른다고 선언하고, 메서드를 구현했습니다. 따라서 ‘conformsToProtocol:’ 메서

드와 ‘respondsToSelector:’ 메서드가 모두 ‘YES’를 반환합니다.

두 번째 인스턴스는 ‘MyClass2’ 클래스의 인스턴스입니다. 이 클래스는 ‘MyCallbackProtocol’

프로토콜을 따른다고 선언하지는 않았으나, 메서드는 구현했습니다. 따라서 ‘conforms

ToProtocol:’ 메서드는 NO를 반환하고 ‘respondsToSelector:’ 메서드는 ‘YES’를 반환합니다.

세 번째 인스턴스는 ‘MyClass3’ 클래스의 인스턴스입니다. 이 클래스는 ‘MyCallbackProtocol’

프로토콜을 따른다고 선언하지 않았고, 메서드도 구현하지 않았습니다. 따라서 ‘conforms

ToProtocol:’ 메서드와 ‘respondsToSelector:’ 메서드 모두 ‘NO’를 반환합니다.

네 번째 인스턴스는 ‘MyClass4’ 클래스의 인스턴스입니다. 이 클래스는 ‘MyCallbackProtocol’

프로토콜을 따른다고 선언했지만, 필요한 메서드를 구현하지 않았습니다. 따라서 ‘conforms

ToProtocol:’ 메서드는 ‘YES’를 반환하고 ‘respondsToSelector:’ 메서드는 ‘NO’를 반환합

니다.

이 네 가지 패턴 중에서 실제로 프로토콜을 구현해서 인스턴스로서 기능하는 것은 ‘MyClass1’

클래스와 ‘MyClass2’ 클래스입니다. 여기서 판정을 내릴 때 ‘conformsToProtocol:’ 메서드를

이용했다가는 ‘MyClass4’ 클래스는 사용할 수 없는데도 판정을 통과해 실제로 사용되는 곳

에서 에러가 발생합니다.

한 프로그램에서 모든 개발이 끝난다면 메서드가 누락된 것을 컴파일하면서 검출할 수 있

으나 플러그인 같은 구조를 만들 때는 여러 프로그램에 걸쳐 인스턴스가 전달됩니다. 이때는

컴파일할 때 에러를 검출할 수 없습니다. 따라서 ‘respondsToSelector:’ 메서드를 사용해 메서

드의 구현 여부를 확인할 필요가 있습니다.

Page 97: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

97

S E C T I O N - 0 2 0 프로토콜 정의

f필수 메서드와 옵션 메서드의 지정

프로토콜 사용을 클래스 선언에서 선언하면 프로토콜에 정의된 메서드를 전부 구현해야 합

니다. 구현하지 않아도 빌드할 수는 있지만 컴파일할 때 경고가 표시됩니다. Objective-C 2.0

부터는 프로토콜을 정의하는 쪽에서 필수 메서드와 필요할 때만 정의하는 옵션 메서드를 지

정할 수 있습니다. 옵션 메서드는 정의하지 않아도 컴파일러의 경고 대상이 되지 않습니다.

@protocol 프로토콜명 <프로토콜리스트>

필수 메서드 정의

@optional

옵션 메서드 정의

@required

필수 메서드 정의

@end

옵션 메서드는 ‘@optional’ 밑에 정의합니다. 필수 메서드는 ‘@required’ 밑에 정의합니다.

이러한 정의를 생략하면 ‘@required’로 취급됩니다.

f프로토콜은 어떤 상황에서 사용해야 하나

프로토콜의 장점은 클래스 계층을 변경하지 않고 특정 인터페이스를 구현하고 있다고 선언

할 수 있다는 점입니다. 따라서 콜백 인터페이스와 같은 방법으로 사용하는 것이 좋습니다.

예를 들어 ‘AppKit’ 프레임워크의 ‘NSTableView’ 클래스는 ‘NSTableView’ 클래스 자체는

GUI 처리 구현에 특화되어 있으며 필요한 데이터는 ‘NSTableViewDataSource’ 프로토콜을

구현한 인스턴스로부터 ‘NSTableViewDataSource’ 프로토콜에 정의된 메서드를 통해 취득

합니다. 이처럼 일반적인 클래스에서 어떤 특별한 동작을 전달하기 위한 콜백 인터페이스로

사용하는 것이 좋습니다.

관련 항목 fff

• 카테고리 정의 ····························································· p.98

• 인스턴스에 특정 메서드가 있는지 확인하기 ··································p.625

Page 98: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

98

SECTION-021 VER. 1.0 2.0

카테고리 정의

� Objective-C의 카테고리 정의

‘카테고리 정의’는 클래스의 메서드를 분류하는 기능으로 기존의 클래스에 메서드를 추가할

수도 있습니다. 클래스에 메서드를 추가하려면 따로 자식클래스를 작성해서 그 자식클래스

에서 구현하는 방법도 있지만 카테고리를 이용하면 더욱 유연한 방식으로 메서드를 추가할

수 있습니다.

f정의 방법

카테고리의 정의 방법은 다음과 같습니다.

@interface 클래스명 (카테고리명)

메서드의 선언

@end

코드의 구현 방법은 다음과 같습니다.

@implementation 클래스명 (카테고리명)

메서드의 구현코드

@end

f예문

다음 코드는 카테고리를 사용해 ‘NSString’ 클래스에 메서드를 추가하는 예시입니다.

#import <Foundation/Foundation.h>

// 카테고리를 사용해 ‘NSString’ 클래스에 두 개의 메서드를 추가한다고 선언

@interface NSString (NameAddition)

- (NSString *)firstName;

- (NSString *)lastName;

@end

Page 99: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

99

S E C T I O N - 0 2 1 카테고리 정의

// 카테고리를 사용해 선언한 메서드를 구현

@implementation NSString (NameAddition)

- (NSString *)firstName

{

// 스페이스로 문자열을 구분

NSArray *tokens = [self componentsSeparatedByString:@" "];

// ‘objectAtIndex:’ 메서드는 무효한 인덱스 번호를 입력하면 예외를 발생시키므로

// 문자열 개수의 확인 필요

if ([tokens count] > 0)

{

return [tokens objectAtIndex:0]; // 첫 번째 문자열을 반환

}

return nil;

}

- (NSString *)lastName

{

// 스페이스로 문자열을 구분

NSArray *tokens = [self componentsSeparatedByString:@" "];

return [tokens lastObject]; // 구분한 문자열의 가장 마지막 문자열을 반환

}

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSString *str = [NSString stringWithString:@"Akira Hayashi"];

NSLog(@"First Name : %@", [str firstName]);

NSLog(@"Last Name : %@", [str lastName]);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2009-09-24 21:56:11.285 Category[1025:a0f] First Name : Akira

2009-09-24 21:56:11.287 Category[1025:a0f] Last Name : Hayashi

이 예제코드에서는 카테고리 정의를 사용해 ‘NSString’ 클래스에 ‘�rstName’ 메서드와

‘lastName’ 메서드를 추가했습니다. 추가한 메서드의 ‘self’는 ‘NSString’ 클래스의 인스턴스

가 됩니다.

이처럼 카테고리 정의를 사용하면 기존의 클래스에 메서드를 추가할 수 있으므로 새로 작

성한 클래스에 유틸리티적인 보조 메서드를 추가하는 방법 대신에 설계 단계부터 카테고리

정의를 사용하는 방법도 고려하기 바랍니다. 필자의 경험으로는 보조적인 함수나 메서드를

새로운 클래스로 추가하는 방법보다는 카테고리 정의를 이용해 기존의 클래스에 메서드를

추가하는 편이 더욱 일반적인 형태로 기술할 수 있었습니다.

Page 100: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

100

S E C T I O N - 0 2 1 카테고리 정의

f인스턴스 변수는 추가할 수 없음

카테고리 정의를 사용해 클래스를 확장할 때 메서드는 추가할 수 있지만 인스턴스 변수는

추가할 수 없습니다. 따라서 인스턴스 변수를 추가해야 하는 메서드를 추가하려면 클래스

로부터 상속받은 자식클래스를 작성하든지 독립된 함수를 작성하는 편이 좋습니다. 또 클

래스를 확장하는 방법보다는 새로운 클래스를 작성하는 편이 더 좋을 때도 있으므로 인스

턴스 변수의 추가가 필요한 클래스의 확장 시에는 어떤 방법을 사용할지 신중하게 검토해

야 합니다.

카테고리의 본래 기능은 클래스의 메서드를 분류별로 나누는 것입니다. 이 기능을 사용하면 복잡

한 클래스나 범용성이 높은 클래스에서 클래스를 사용하는 쪽이 필요로 하는 기능의 수준에 맞춰

공개할 인터페이스를 변경할 수도 있습니다. 예를 들어 영상 처리를 하는 클래스에서는 다음과 같

은 두 가지 인터페이스를 생각할 수 있습니다.

• 단순히 필터만 실행하는 간이 인터페이스

• 상세한 파라미터를 설정하고 알고리즘 지식까지 필요로 하는 인터페이스

카테고리를 사용해 이렇게 두 가지 인터페이스로 나누면 프로그램 사용자의 혼동을 막을 수 있습

니다. 또한 영상 처리를 하는 클래스는 나중에 알고리즘이 늘어나서 메서드가 증가할 수도 있습니

다. 이럴 때에도 카테고리로 분리하면 소스파일도 분리할 수 있으므로 유지보수가 쉬워집니다.

다음 코드는 간이 인터페이스를 ‘MyImageFilterBasic.h’ 파일에 정의하고 상세 인터페이스를

‘MyImageFilter.h’ 파일에 정의한 예제입니다. 이 클래스를 사용하는 쪽이 상세한 제어가 필요하

지 않을 때나 기존 동작을 구현하고 싶을 때에는 간이 인터페이스를 사용하고, 상세하게 제어를

하고 싶을 때는 상세 인터페이스를 사용할 수 있도록 구분해서 사용하게 되어 있습니다.

// ‘MyImageFilterBasic.h’ 파일

@interface MyImageFilter (Basic)

// 밝기를 변경하는 메서드

// 변경할 수준을 지정

- (BOOL)adjustLightness:(double)level;

@endif

COLUMN 간이 인터페이스와 상세 인터페이스의 구분

Page 101: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

101

S E C T I O N - 0 2 1 카테고리 정의

// ‘MyImageFilter.h’ 파일

@interface MyImageFilter

{

NSBitmapImageRep *bitmap; // 필요한 데이터 멤버

}

// 밝기를 변경하는 메서드

// 변경할 수준 이외에 콜백 처리나 알고리즘의 설정을 할 수 있게 함

- (BOOL)adjustLightness:(double)level

algorithm:(int)algorithm

additionalParam:(NSDictionary *)param

invocation:(NSInvocation *)invocation;

@end

Page 102: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

102

SECTION-022 VER. 1.0 2.0

프로퍼티 정의

� Objective-C의 프로퍼티 정의

프로퍼티는 일반적으로 속성이나 설정이라는 뜻입니다. Objective-C의 프로퍼티도 마찬가

지로 클래스의 인스턴스에 대한 속성이나 설정이라고 할 수 있습니다. Objective-C 1.0에서

프로퍼티의 조작은 메서드에서 정의했으며 보통 접근자 메서드라고 합니다. Objective-C 2.0

부터는 언어적으로 프로퍼티 개념을 도입해 이에 관한 전용 기술방법이 추가됐습니다. 또한

일반적인 조작을 할 때 이러한 기술방법으로 자동으로 메서드가 생성되게 바뀌었습니다.

f정의 방법

클래스 선언 내에 프로퍼티를 정의하는 방법은 다음과 같습니다.

@interface 클래스명 : 부모 클래스

{

}

@property 프로퍼티타입 프로퍼티명

@end

‘@property 프로퍼티타입 프로퍼티명’ 선언이 한 묶음으로 하나의 프로퍼티를 정의합니다.

이 정의는 다음 두 가지 메서드를 정의한 것과 같습니다.

- (프로퍼티타입) 프로퍼티명

- (void) set 프로퍼티명: (프로퍼티타입) value;

따라서 이 메서드들을 코드로 작성할 필요가 있습니다. 다음과 같이 기술하면 자동으로 메

서드가 구현됩니다.

@implmentation 클래스명

@synthesize 프로퍼티명

메서드의 구현

@end

‘@synthesize 프로퍼티명:’ 이라고 기술하면 프로퍼티명과 같은 이름의 인스턴스 변수가 있

다고 간주하고 그에 대한 설정자 메서드와 접근자 메서드가 자동으로 생성됩니다.

Page 103: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

103

S E C T I O N - 0 2 2 프로퍼티 정의

f예문

다음 예제코드는 ‘MyClass’ 클래스를 정의하고 ‘data’와 ‘dataName’ 이라는 두 가지 프로퍼

티를 정의하고 있습니다. ‘main’ 함수에서 이들 프로퍼티에 값을 설정하고 취득하는 코드입

니다.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

// 프로퍼티에서 사용할 인스턴스 변수 정의

int data;

NSString *dataName;

}

// 두 개의 프로퍼티 정의

@property int data;

@property (copy) NSString *dataName;

@end

@implementation MyClass

// 두 개의 프로퍼티에 대한 접근자 메서드 생성

@synthesize data;

@synthesize dataName;

- (id)init

{

self = [super init];

if (self)

{

// 인스턴스 변수 초기화

data = 0;

dataName = nil;

}

return self;

}

- (void)dealloc

{

// 인스턴스 변수 소멸

[dataName release];

[super dealloc];

}

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *c = [[[MyClass alloc] init] autorelease];

[c setDataName:@"The Data"]; // 프로퍼티 ‘dataName’ 설정

[c setData:20]; // 프로퍼티 ‘data’ 설정

Page 104: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

104

S E C T I O N - 0 2 2 프로퍼티 정의

// 두 개의 프로퍼티 값을 취득해 로그에 출력

NSLog(@"%@ : %d", [c dataName], [c data]);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2009-09-24 22:32:19.248 Property[1120:a0f] The Data : 20

이 코드에서는 ‘@property int data;’와 ‘@synthesize data;’ 두 구문에 의해 멤버변수 ‘int data’

값의 설정자 메서드와 접근자 메서드가 생성됐습니다. 또한 ‘@property (copy) NSString*

dataName;’과 ‘@synthesize dataName;’ 두 구문에 의해 멤버 변수 ‘NSString* dataName’의

값의 설정자 메서드와 접근자 메서드가 생성됐습니다.

f프로퍼티명을 변수명과 다르게 하려면

이 책에서 인스턴스 변수는 로컬 변수와 구별하기 위해 앞단에 _를 붙였습니다. 그러나 프로

퍼티명에는 ‘_’를 붙이지 않습니다. 이렇게 프로퍼티로 사용할 변수명과 다른 이름의 프로퍼

티를 선언하려면 다음과 같이 기술합니다.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

// 프로퍼티에 사용할 인스턴스 변수 정의

int _data;

}

// 프로퍼티 정의

@property int data;

@end

@implementation MyClass

// 프로퍼티 ‘data’의 인스턴스 변수로 ‘_data’를 사용한다고 정의

@synthesize data = _data;

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *c = [[[MyClass alloc] init] autorelease];

// 메서드 호출은 ‘@property’에서 지정한 프로퍼티명으로 실행

Page 105: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

105

S E C T I O N - 0 2 2 프로퍼티 정의

[c setData:20];

NSLog(@"%d", [c data]);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-16 23:47:48.455 Property2[610:a0f] 20

프로퍼티명의 선언은 ‘@property’에 기술합니다. ‘@property’에서 선언한 프로퍼티에 어떤

인스턴스 변수를 사용할지는 ‘@synthesize 프로퍼티명 = 인스턴스변수’ 구문에서 지정합니

다. 위의 코드에는 ‘data’ 프로퍼티의 인스턴스 변수로써 ‘_data’를 지정하고 있습니다.

f접근자 메서드 구현 방법

접근자 메서드를 독자적으로 구현하려면 ‘@synthesize’를 사용하지 않고 프로퍼티명에 따른

메서드명을 사용합니다. 설정자 메서드만 구현하고 접근자 메서드는 자동으로 생성하려면

‘@synthesize’ 명령문은 그대로 두고 구현하고 싶은 메서드를 구현합니다. 가령 ‘@synthesize’

명령을 기술한 상태에서 설정자 메서드와 접근자 메서드를 모두 구현해도 문제는 없습니다.

‘@synthesize’에서 생성된 메서드보다 독자적으로 구현한 메서드가 우선됩니다.

다음 코드는 설정자 메서드인 ‘setData:’ 메서드에서 값을 검사하기 위해 설정자 메서드만

을 구현하는 예입니다.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

int _data;

}

// 프로퍼티 정의

@property int data;

@end

@implementation MyClass

// 접근자 메서드를 자동생성

@synthesize data = _data;

// 설정자 메서드는 독자적으로 구현

- (void)setData:(int)newValue

{

Page 106: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

106

S E C T I O N - 0 2 2 프로퍼티 정의

// 값을 검사. 0 이상 10 미만일 때만 설정

if (newValue >= 0 && newValue < 10)

{

_data = newValue;

}

}

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *c = [[[MyClass alloc] init] autorelease];

// 검사한 값이 범위 안이므로 설정됨

[c setData:5];

NSLog(@"%d", [c data]);

// 10 이상이므로 설정되지 않음

[c setData:12];

NSLog(@"%d", [c data]);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같으며 ‘[c setData:12]’는 설정자 메서드인 ‘setData:’ 메서

드의 값 검사에서 무시되어 설정되지 않았음을 알 수 있습니다.

2009-09-25 12:26:09.518 Property3[1328:a0f] 5

2009-09-25 12:26:09.521 Property3[1328:a0f] 5

f인스턴스 변수가 반드시 필요한 것은 아니다

프로퍼티를 정의할 때는 프로퍼티의 타입, 프로퍼티의 이름, 그 프로퍼티의 접근자 메서드

만을 지정합니다. 따라서 그 프로퍼티가 클래스의 내부에 기억되는 방법과 취득되는 방법은

규정하고 있지 않습니다. 그러므로 지원할 인스턴스 변수가 반드시 필요한 것은 아닙니다.

다음 코드의 ‘data’ 프로퍼티는 1970년부터 지금까지 몇 초 지났는지 값을 반환하는 프로퍼

티입니다.

Page 107: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

107

S E C T I O N - 0 2 2 프로퍼티 정의

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

}

// 프로퍼티를 읽기전용으로 정의

@property (readonly) int data;

@end

@implementation MyClass

// 접근자 메서드를 구현

- (int)data

{

// 1970년부터 지금까지 몇 초 지났는지 반환

return (int)[[NSDate date] timeIntervalSince1970];

}

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *c = [[[MyClass alloc] init] autorelease];

NSLog(@"%d", [c data]);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다(실제 수치는 실행한 일시에 따라 바뀜).

2010-01-16 23:48:37.743 Property4[640:a0f] 1263653317

f프로퍼티 속성을 지정한다

프로퍼티에는 속성이 있습니다. 지정한 속성에 따라 ‘@synthesize’에서 생성되는 접근자 메

서드의 내용이 달라집니다. 속성은 다음 구문과 같이 ‘@property’ 뒤에 괄호를 붙여서 지정하

며 여러 개의 속성을 지정하려면 ‘,’ 로 구분합니다.

@property (속성) 프로퍼티타입 프로퍼티명;

속성은 다음 표와 같습니다.

Page 108: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

108

S E C T I O N - 0 2 2 프로퍼티 정의

속성 설명

Getter 접근자 메서드 이름을 지정함. ‘getter = 메서드명’ 구문으로 지정함

Setter 설정자 메서드 이름을 지정함. ‘setter = 메서드명’ 구문으로 지정함

Readwrite 읽기 쓰기가 가능한 프로퍼티를 의미함. 디폴트 값이므로 특별히 지정할 필요

는 없음

Readonly 읽기 전용 프로퍼티를 의미함. 이 속성을 지정한 프로퍼티는 설정자 메서드를

구현할 필요가 없음

assign, retain, copy 설정자 메서드의 프로퍼티 값을 유지하는 방법을 설정함. 세 가지 중에서 한

가지를 선택함. 디폴트 값은 ‘assign’

Nonatomic 프로퍼티 값을 설정/취득할 때, 스레드간에 동기화 하지 않음. 지정하지 않으

면 스레드 사이에서 항상 동기 처리를 함

f설정자 메서드 유지 방법

속성으로 지정할 수 있는 설정자 메서드의 프로퍼티 값을 유지하는 방법에는 ‘assign’, ‘retain’,

‘copy’ 3종류가 있습니다. ‘retain’, ‘copy’는 Objective-C 클래스의 인스턴스를 프로퍼티로 사

용할 때 지정합니다. 각 방법은 다음과 같이 동작합니다.

• assign

‘assign’을 지정하면 프로퍼티의 값을 단순히 ‘=’ 연산자로 대입합니다. ‘ int’ 등의 Objective-C 클래스의 인스턴스 이외에는 이 방법이 적당합니다. 또 속성에서 유지방

법을 지정하지 않았을 때의 디폴트 동작도 ‘assign’입니다.

• retain

‘retain’을 지정하면 프로퍼티의 변경 전 값으로 갖고 있던 인스턴스는 ‘release’ 메서드

를 호출해서 소멸하고 새로운 값으로 전달된 인스턴스의 ‘retain’ 메서드를 호출하고 나

서 프로퍼티의 값으로 유지시킵니다.

• copy

‘copy’를 지정하면 프로퍼티의 변경 전 값으로 갖고 있던 인스턴스는 ‘release’ 메서드를 호출하여 소멸하고 새로운 값으로 전달된 인스턴스는 ‘copy’ 메서드로 복사본을 생성

해 생성된 복사본을 프로퍼티의 값으로 유지합니다.

f도트 연산자

프로퍼티에서는 ‘.’ 연산자(도트 연산자)를 사용해 읽고 쓸 수 있습니다. 도트 연산자는 다음

과 같이 사용합니다.

Page 109: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

109

S E C T I O N - 0 2 2 프로퍼티 정의

오브젝트.프로퍼티명

프로퍼티 값의 설정은 다음과 같이 ‘=’ 연산자를 이용합니다.

오브젝트.프로퍼티명 = 새로운 값

다음 코드는 ‘.’ 연산자를 사용해 프로퍼티를 읽고 쓰고 있습니다.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

// 프로퍼티에 사용할 인스턴스 변수를 정의

int _data;

}

// 프로퍼티를 정의

@property int data;

@end

@implementation MyClass

// 프로퍼티 ‘data’의 인스턴스 변수로 ‘_data’를 사용한다고 정의

@synthesize data = _data;

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *c = [[[MyClass alloc] init] autorelease];

// 프로퍼티에 값을 설정

c.data = 50;

// 프로퍼티에서 값을 취득

int i = c.data;

NSLog(@"%d", i);

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-16 23:50:28.255 Property5[780:a0f] 50

Page 110: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

110

S E C T I O N - 0 2 2 프로퍼티 정의

Objective-C 1.0은 언어적으로 프로퍼티를 지원하지는 않습니다. 따라서 ‘도트 연산자’를 사용해

서 프로퍼티를 읽고 쓸 수는 없지만 프로퍼티의 정의에 의해 생성되는 접근자 메서드와 같은 메서

드를 구현함으로써 간접적으로 프로퍼티와 비슷한 효과를 구현할 수 있습니다.

다음 코드는 스레드의 동기화 처리는 하지 않지만, ‘@synthesize data = _data’에서 생성한 접근

자 메서드와 비슷한 처리를 합니다.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject{ NSString* _str;}// 프로퍼티 정의를 사용할 수 없으므로 접근자 메서드를 선언

- (void)setStringValue:(NSString *)newValue;- (NSString *)stringValue;@end

@implementation MyClass

// 설정자 메서드 구현

- (void)setStringValue:(NSString *)newValue{ // 변수 ‘newValue’가 ‘_str’과 같은 인스턴스라면

// ‘[_str release];’ 로 소멸되므로 다른 인스턴스인지 검사

if (_str != newValue) { [_str release]; _str = [newValue copy]; }}

// 접근자 메서드 구현

- (NSString *)stringValue;{ return _str;}

@end

int main (int argc, const char *argv[]){ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; MyClass *c = [[[MyClass alloc] init] autorelease]; // 설정자 메서드를 호출

[c setStringValue:@"THE STRING"]; // 접근자 메서드를 호출

NSLog(@"%@", [c stringValue]); [pool drain]; return 0;}

COLUMN Objective-C 1.0의 프로퍼티

Page 111: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

111

S E C T I O N - 0 2 2 프로퍼티 정의

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-17 00:02:09.067 Property6[873:a0f] THE STRING

Page 112: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

112

SECTION-023 VER. 1.0 2.0

예외 처리

� Objective-C의 예외 처리

‘NSArray’ 클래스에서 범위를 벗어난 엘리먼트를 취득하려고 하면 ‘Foundation’ 프레임워크

클래스는 예외를 발생시킵니다. 예외가 발생하면 그 시점에서의 처리는 예외 처리로 이동해

이후의 코드는 실행되지 않으며 예외 처리 핸들러로 발생한 예외를 받아들여 적절하게 에러

처리를 할 수 있습니다. 또한 ‘Foundation’ 프레임워크뿐만 아니라 프로그램에서도 예외가

발생할 수 있습니다.

에러 처리를 할 때 항상 예외 처리 핸들러를 사용해야 할지 아니면 예외 처리 핸들러를 전혀

사용하지 말아야 할지에 대해 다양한 견해가 있을 것입니다. 필자의 개인적인 생각으로는 프

로그램을 진행할 수 없을 때나 예상치 못한 에러가 발생했을 때에만 예외 처리 핸들러를 한

정해서 사용해야 한다고 봅니다. 하지만 이것도 어디까지나 하나의 견해일 뿐입니다.

f예외 처리 핸들러 구문

예외 처리 핸들러는 ‘예외가 발생할 가능성이 있는 코드’, ‘예외가 발생했을 때 처리하는 코

드’, ‘예외의 발생 유무와 관계없이 실행되는 코드’ 세 부분으로 나뉩니다. 예외의 발생 유무와

관계없이 실행되는 코드인 ‘@�nally’는 생략할 수 있습니다.

@try

{

예외가 발생할 가능성이 있는 코드

}

@catch (NSException *exception)

{

예외가 발생했을 때 처리하는 코드

}

@finally

{

예외의 발생 유무와 관계없이 실행되는 코드

}

f예외 정보는 ‘NSException’ 클래스

예외 처리 핸들러에서 받아들인 예외 정보는 실제로는 ‘NSException’ 클래스의 인스턴스입

니다. ‘NSException’ 클래스는 발생한 예외에 관한 각종 정보를 보유할 수 있습니다.

Page 113: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

113

S E C T I O N - 0 2 3 예외 처리

다음 코드는 ‘NSArray’ 클래스에서 고의로 범위를 벗어난 값을 지정해 예외를 발생시킨 후

발생한 예외정보를 로그에 출력하고 있습니다.

#import <Foundation/Foundation.h>

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

@try

{

NSArray *theArray = [NSArray arrayWithObjects:

@"0", @"1", @"2", nil];

// 인덱스 번호 4의 엘리먼트는 없으므로

// ‘NSArray’ 클래스는 예외를 발생시킴

NSString *str = [theArray objectAtIndex:4];

// 이 코드는 실행되지 않음

NSLog(@"The String : %@", str);

}

@catch (NSException *e)

{

// 예외를 처리하기 위한 코드

NSLog(@"Name : %@", [e name]);

NSLog(@"Reason : %@", [e reason]);

NSLog(@"UserInfo: %@", [[e userInfo] description]);

}

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2010-07-16 00:41:22.289 ObjCTest[3476:307] Name : NSRangeException

2010-07-16 00:41:22.297 ObjCTest[3476:307] Reason : *** -[NSArray objectAtIndex:]:

index 4 beyond bounds [0 .. 2]

2010-07-16 00:41:22.301 ObjCTest[3476:307] UserInfo: (null)

f예외를 발생시키기

예외를 발생시키려면 ‘NSException’ 클래스의 메서드를 사용합니다. 다음 코드는 ‘do�row’

메서드로 예외를 발생시켜 호출한 쪽 함수에서 예외를 처리합니다.

Page 114: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

114

S E C T I O N - 0 2 3 예외 처리

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

}

- (void)doThrow;

@end

@implementation MyClass

- (void)doThrow

{

// 예외를 발생시킴

[[NSException exceptionWithName:@"MyException"

reason:@"Not Implemented Method"

userInfo:nil] raise];

}

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

@try

{

MyClass *p = [[[MyClass alloc] init] autorelease];

[p doThrow];

}

@catch (NSException *e)

{

// 예외를 처리하는 코드

NSLog(@"Name : %@", [e name]);

NSLog(@"Reason : %@", [e reason]);

NSLog(@"UserInfo: %@", [[e userInfo] description]);

}

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같으며 예외를 발생시켰을 때 설정한 정보를 예외 처리를

위한 ‘@catch’에서 받았음을 알 수 있습니다.

2009-09-25 00:49:16.504 Exception2[2121:a0f] Name : MyException

2009-09-25 00:49:16.507 Exception2[2121:a0f] Reason : Not Implemented Method

2009-09-25 00:49:16.507 Exception2[2121:a0f] UserInfo: (null)

Page 115: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

115

S E C T I O N - 0 2 3 예외 처리

f ‘@try ~ @catch ~ @finally’ 구문은 GCC 3.3 이후부터 지원

‘@try’, ‘@catch’, ‘@�nally’ 세 가지 구문을 사용한 예외 처리는 GCC 3.3 이후 버전으로 빌드

하는 Mac OS X 10.3 이후 버전부터 사용할 수 있으며 iPhone OS에서도 사용할 수 있습니

다. 그 이전 환경에서 예외 처리가 필요하면 다음과 같이 ‘NS_DURNING’, ‘NS_HANDLER’,

‘NS_ENDHANDLER’ 매크로를 사용하면 됩니다. 하지만 이 매크로는 반드시 Mac OS X

10.3 이전 환경에서만 사용해 주세요.

NS_DURING

// 예외가 발생할 가능성이 있는 코드

NS_HANDLER

// 예외를 처리하는 코드

NS_ENDHANDLER

발생한 예외는 ‘localException’ 변수에 들어갑니다. 또한 ‘NS_HANDLER’부터 ‘NS_

ENDHANDLER’ 사이에는 ‘return’ 문을 사용할 수 없습니다. ‘NS_ENDHANDLER’ 아래를

실행하지 않고 이 블록에서 메서드를 빠져나가고 싶을 때는 ‘NS_VALUERETURN()’ 매크

로 혹은 ‘NS_VOIDRETURN’ 매크로를 사용해야 합니다. ‘NSVALUERETURN()’ 매크로는

‘NS_VALUERETURN(반환값, 반환형)’ 형식으로 사용합니다.

다음 코드에서는 ‘NSArray’ 클래스에서 일부러 범위를 벗어난 값을 설정해 예외를 발생시

킨 후 받아들인 예외 정보를 매크로를 통해 로그에 출력하고 있습니다.

#import <Foundation/Foundation.h>

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NS_DURING

NSArray *theArray = [NSArray arrayWithObjects:

@"0", @"1", @"2", nil];

// 인덱스 번호 4의 엘리먼트가 없으므로 ‘NSArray’ 클래스는 예외를 발생시킴

[theArray objectAtIndex:4];

NS_HANDLER

// 예외를 처리하는 코드

NSLog(@"Name : %@", [localException name]);

NS_ENDHANDLER

[pool drain];

return 0;

}

Page 116: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

116

S E C T I O N - 0 2 3 예외 처리

이 코드를 실행한 결과는 다음과 같습니다.

2010-01-17 00:25:14.435 Exception3[1101:a0f] Name : NSRangeException

Page 117: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

117

SECTION-024 VER. 1.0 2.0

블록 구문

� Objective-C의 블록 구문

Mac OS X 10.6 이후 버전과 iPhone OS 4.0 이후 버전부터는 블록 구문을 사용할 수 있습니

다. 블록 구문을 사용하면 함수를 정의하지 않고 로컬함수를 변수와 같이 생성할 수 있습니

다. 블록 구문은 다음과 같이 정의합니다.

반환형 (^블록명)(파라미터의타입)

예를 들어 다음 코드에서는 파라미터로 전달된 값의 제곱을 계산해서 반환하는 처리를 블

록 구문으로 기술하고 있습니다.

#import <Foundation/Foundation.h>

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// ‘square’라는 블록 구문의 변수를 정의

// 반환형은 ‘int’ 타입, 파라미터로 ‘int’ 타입 하나를 가짐

int (^square)(int);

// ‘square’의 내용을 블록 구문으로 기술함

square = ^(int x) {

return x * x; // 파라미터 ‘x’를 제곱하여 반환

};

for (int i = 0; i < 10; i++)

{

// ‘square’에 파라미터 ‘i’를 전달해서 반환된 값을 로그에 출력

NSLog(@"%d x %d = %d", i, i, square(i));

}

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같으며 전달된 값이 제곱으로 반환됐음을 알 수 있습니다.

Page 118: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

118

S E C T I O N - 0 2 4 블록 구문

2009-09-25 01:20:13.377 Block[2348:a0f] 0 x 0 = 0

2009-09-25 01:20:13.379 Block[2348:a0f] 1 x 1 = 1

2009-09-25 01:20:13.380 Block[2348:a0f] 2 x 2 = 4

2009-09-25 01:20:13.380 Block[2348:a0f] 3 x 3 = 9

2009-09-25 01:20:13.381 Block[2348:a0f] 4 x 4 = 16

2009-09-25 01:20:13.381 Block[2348:a0f] 5 x 5 = 25

2009-09-25 01:20:13.381 Block[2348:a0f] 6 x 6 = 36

2009-09-25 01:20:13.382 Block[2348:a0f] 7 x 7 = 49

2009-09-25 01:20:13.382 Block[2348:a0f] 8 x 8 = 64

2009-09-25 01:20:13.382 Block[2348:a0f] 9 x 9 = 81

f메서드의 파라미터로 블록 사용하기

블록을 파라미터로 하는 메서드는 변수를 선언하지 않고 블록 자체를 파라미터로 기술합니

다. 예를 들면 ‘NSArray’ 클래스의 ‘enumerateObjectsUsingBlock:’ 메서드는 ‘NSArray’ 클래

스의 인스턴스가 가진 엘리먼트를 순서대로 블록에 전달하는 메서드로써 다음과 같이 정의

됩니다.

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block

따라서 다음과 같이 파라미터에 직접 블록을 기술할 수 있습니다. 다음 코드는 ‘NSArray’

클래스 인스턴스의 각 엘리먼트에 ‘NSNumber’ 클래스의 인스턴스가 들어 있는 형태이며 제

곱해서 로그에 출력합니다.

#import <Foundation/Foundation.h>

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// 0 – 9까지의 값이 들어간 배열을 생성

NSArray* theArray = [NSArray arrayWithObjects:

[NSNumber numberWithInt:0],

[NSNumber numberWithInt:1],

[NSNumber numberWithInt:2],

[NSNumber numberWithInt:3],

[NSNumber numberWithInt:4],

[NSNumber numberWithInt:5],

[NSNumber numberWithInt:6],

[NSNumber numberWithInt:7],

[NSNumber numberWithInt:8],

[NSNumber numberWithInt:9],

nil];

Page 119: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

01

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER02

119

S E C T I O N - 0 2 4 블록 구문

[theArray enumerateObjectsUsingBlock:

^(id obj, NSUInteger idx, BOOL *stop) {

// 파라미터 ‘obj’가 각 엘리먼트임

// 이 경우는 ‘theArray’에는 10개의 엘리먼트가 있으므로

// 이 부분은 10번 호출됨

int x = [obj intValue];

NSLog(@"%d x %d = %d", x, x, x * x);

}];

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같습니다.

2009-09-25 01:33:42.103 Block2[2439:a0f] 0 x 0 = 0

2009-09-25 01:33:42.106 Block2[2439:a0f] 1 x 1 = 1

2009-09-25 01:33:42.106 Block2[2439:a0f] 2 x 2 = 4

2009-09-25 01:33:42.107 Block2[2439:a0f] 3 x 3 = 9

2009-09-25 01:33:42.107 Block2[2439:a0f] 4 x 4 = 16

2009-09-25 01:33:42.107 Block2[2439:a0f] 5 x 5 = 25

2009-09-25 01:33:42.108 Block2[2439:a0f] 6 x 6 = 36

2009-09-25 01:33:42.108 Block2[2439:a0f] 7 x 7 = 49

2009-09-25 01:33:42.108 Block2[2439:a0f] 8 x 8 = 64

2009-09-25 01:33:42.109 Block2[2439:a0f] 9 x 9 = 81

f블록을 파라미터로 갖는 메서드 구현

블록을 파라미터로 갖는 메서드를 구현하려면 다음과 같이 합니다. 다음 코드는 블록이 ‘int’

타입의 파라미터를 한 개 가지며 ‘int’ 타입을 반환하는 예입니다.

#import <Foundation/Foundation.h>

@interface MyClass : NSObject

{

}

// 마지막 파라미터에 블록을 지정함

// 블록은 ‘int’ 타입의 파라미터를 한 개 가지며 ‘int’ 타입의 값을 반환

- (void)calcRange:(NSRange)range usingBlock:(int (^)(int x))block;

@end

@implementation MyClass

- (void)calcRange:(NSRange)range usingBlock:(int (^)(int x))block

{

for (int i = 0; i < range.length; i++)

{

Page 120: 오브젝티브-C 핸드북 : 사전처럼 바로 찾아 바로 쓰는

01

02

03

04

05

06

07

08

09

10

11

12

13

14

부록

Obje

ctive-C

문법

CH

AP

TER

02

120

S E C T I O N - 0 2 4 블록 구문

// 블록 호출은 블록 변수에 ‘( )’를 붙여서 ‘( )’ 내에 파라미터를 기술함

NSLog(@"%d : %d", i, block(i));

}

}

@end

int main (int argc, const char *argv[])

{

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

MyClass *c = [[[MyClass alloc] init] autorelease];

// 메서드의 파라미터로 블록을 직접 기술하고 있음

[c calcRange:NSMakeRange(0, 10) usingBlock:^(int x) {

return x * x; // 제곱해서 반환

}];

[pool drain];

return 0;

}

이 코드를 실행한 결과는 다음과 같으며 블록을 사용한 계산 처리가 실행돼 블록에서 반환

한 값이 로그 출력으로 전달됨을 알 수 있습니다.

2009-09-25 01:55:19.209 Block3[2561:a0f] 0 : 0

2009-09-25 01:55:19.212 Block3[2561:a0f] 1 : 1

2009-09-25 01:55:19.213 Block3[2561:a0f] 2 : 4

2009-09-25 01:55:19.213 Block3[2561:a0f] 3 : 9

2009-09-25 01:55:19.213 Block3[2561:a0f] 4 : 16

2009-09-25 01:55:19.214 Block3[2561:a0f] 5 : 25

2009-09-25 01:55:19.214 Block3[2561:a0f] 6 : 36

2009-09-25 01:55:19.215 Block3[2561:a0f] 7 : 49

2009-09-25 01:55:19.215 Block3[2561:a0f] 8 : 64

2009-09-25 01:55:19.215 Block3[2561:a0f] 9 : 81

Mac OS X 10.6 이후 버전이나 iPhone OS 4.0부터 등장한 기술 중에 ‘Grand Central Dispatch’

(GDC)가 있습니다. ‘GCD’는 CPU 코어를 포함해 시스템 레벨에서 이용할 수 있는 연산장치로 태

스크를 분산시키는 기술입니다. 이러한 태스크를 기술할 때도 블록을 사용합니다. ‘GCD’의 API는

‘libdipatch.dylib’라는 라이브러리로 구현되며 각 API에서 태스크로 블록을 전달합니다. ‘GCD’는

전달받은 블록을 연산장치에 효율적으로 분산시키고 블록을 실행합니다. 블록 자신이 어떻게 분

산되었는지는 관계없이 하나의 태스크로 실행시킵니다.

멀티 코어 CPU가 일반화되고 앞으로도 코어의 증가나 CPU 이외의 연산장치를 이용하는 기술이

발전해 감에 따라 블록과 ‘GCD’의 조합은 더욱 중요시될 것입니다.

COLUMN Grand Central Dispatch (GCD)와 블록