• 검색 결과가 없습니다.

iOS 앱 개발 Lecture 02 - 오브젝티브-C

N/A
N/A
Protected

Academic year: 2022

Share "iOS 앱 개발 Lecture 02 - 오브젝티브-C"

Copied!
58
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

iOS 앱 개발

Lecture 02 - 오브젝티브-C

동의대학교 게임공학과 서진석

jsseo@deu.ac.kr

(2)

목차

‣ 프로퍼티

오브젝티브-C

‣ strong과 weak

‣ nil과 BOOL

‣ 인스턴스 메소드, 클래스 메소드

‣ 동적 바인딩

‣ 인트로스펙션

• Foundation 프레임워크

‣ NSObject, NSString, NSMutableString

‣ NSNumber, NSValue, NSData, NSDate

‣ NSArray, NSDictionary, NSSet, ...

‣ 열거

‣ 프로퍼티 리스트

(3)

프로퍼티(Property)

• 왜 프로퍼티를 사용하는가?

‣ 인스턴스 변수에 대한 안전성과 확장성 지원

‣ Lazy Instantiation, UI 업데이트, 일관성 체크 (예, speed < 1)

• 프로퍼티를 위한 인스턴스 변수는?

‣ 항상 필요한 것은 아님

‣ 어떤 계산에 의해서 값을 반환하는 getter 메소드 구현 가능

(4)

프로퍼티(Property)

• 닷 표기법 (dot notation)은 왜 사용하는가?

‣ 코드가 깔끔해짐

‣ 다른 메소드와 프로퍼티 접근을 서로 구분

‣ C 구조체 문법과 동일

‣ C 구조체와의 차이점 - 메시지 전송이 불가능

- 거의 대부분 정적 할당: 스택(stack)

(5)

닷 표기법

typedef struct { float x;

float y;

} CGPoint; 클래스 이름처럼 대문자로 시작하는 구조체 “CGPoint”

(6)

닷 표기법

typedef struct { float x;

float y;

} CGPoint;

@interface Bomb : NSObject

@property CGPoint position;

@end

@interface Ship : Vehicle

@property float width;

@property float height;

@property CGPoint center;

- (BOOL)getHitByBomb:(Bomb *)bomb;

@end

인자로 전달된 bomb과 리시버 객체가 충돌하였는지를 검사하여 BOOL 값 반환

(7)

닷 표기법

typedef struct { float x;

float y;

} CGPoint;

@interface Bomb : NSObject

@property CGPoint position;

@end

@interface Ship : Vehicle

@property float width;

@property float height;

@property CGPoint center;

- (BOOL)getHitByBomb:(Bomb *)bomb;

@end

@implementation Ship

@synthesize width, height, center;

- (BOOL)getsHitByBomb:(Bomb *)bomb {

float leftEdge =

self.center.x - self.width/2;

float rightEdge = ...;

return ((bomb.position.x >= leftEdge) &&

! ! ! (bomb.position.x <= rightEdge) &&

! ! ! (bomb.position.y >= topEdge) &&

! ! ! (bomb.position.y <= bottomEdge));

}

@end 객체의 프로퍼티에

접근하기 위한 닷 표기법 구조체의 멤버에

접근하기 위한 닷 표기법

(8)

strong vs weak

strong

소유하는 클래스가 더이상 참조하지 않을 때까지 메모리(heap)에 유지

만약, 소유하는 클래스가 이 포인터에 nil을 대입하면 메모리 해제

즉, 아무도 strong 프로퍼티로 참조하지 않으면 메모리에서 해제

iOS 4, Xcode 4.2 이후 지원

weak

누군가 strong 프로퍼티로 참조할 때까지만 메모리에 유지

만약 아무도 strong 프로퍼티로 참조하지 않으면, 자동으로 nil을 대입

iOS 5 이후 지원

(9)

strong vs weak

• 가비지 콜렉션 (garbage collection)은 아님!

‣ 보다 좋은 방법

‣ ARC(Automatic Reference Counting)라고 함

‣ retain, release, autorelease 등을 사용할 수 없으며, 컴파일러가 자동 으로 코드 생성

(10)

strong vs weak

• 객체가 소멸될 때 무엇인가를 하고 싶다면?

‣ dealloc 메소드가 호출됨

‣ 하지만, 직접 구현할 일은 거의 없음

‣ 이유: 무엇을 하기엔 이미 너무 늦은 시간

- (void)dealloc {

[[NSNotificationCenter defaultCenter] removeObserver:self];

}

(11)

nil

• 아무 것도 가리키지 않는 포인터 변수 값

id obj = nil;

NSString *hello = nil;

• 기본 데이터 타입에서의 “0(영)”과 유사

• 객체 생성 시 모든 인스턴스 변수는 0으로 설정됨

‣ 객체의 경우 nil로 설정

‣ 실제 내부에서는 nil 도 0으로 정의되어 있음

(12)

nil

• 암묵적인 테스트 가능

if (obj) { // if (obj != nil) 과 동일 // ...

}

if (!obj) { // if (obj == nil) 과 동일 // ...

}

• nil에 메시지 전송 가능

‣ 아무 코드도 실행하지 않음

int i = [obj methodWhichReturnsAnInt]; // i는 0 id a = [obj methodWhichReturnsAnObject];! // a는 nil

CGPoint p = [obj getLocation]; // p의 값은 보장 안됨 (이유: C 구조체)

(13)

BOOL

• 오브젝티브 C의 부울리언 타입

‣ 실제로는 unsigned char 타입을 typedef

‣ 암묵적인 테스트 가능

if (flag) { // if (flag == YES) 와 동일 // ...

}

if (!flag) { // if (flag == NO) 와 동일 // ...

}

‣ 0은 NO, 그 밖의 값은 YES

YES와 NO 사용

(14)

인스턴스 vs 클래스 메소드

- 기호로 시작+ 기호로 시작

- (BOOL)dropBomb:(Bomb *)bomb

at:(CGPoint)position from:(double)altitude;

+ (id) alloc;

+ (Ship *)motherShip;

+ (NSString *)stringWithFormat:...

Bomb : 클래스

힙에 할당된 객체 포인터를 넘김

CGPoint : C 구조체

포인터가 아니므로, 값이(value) 직접 전달 스택에 생성

(15)

인스턴스 vs 클래스 메소드

- 기호로 시작

보통의 메소드

호출 문법

+ 기호로 시작

• 생성 & 유틸리티 메소드

호출 문법

- (BOOL)dropBomb:(Bomb *)bomb

at:(CGPoint)position from:(double)altitude;

+ (id) alloc;

+ (Ship *)motherShip;

+ (NSString *)stringWithFormat:...

[<인스턴스 포인터> 메소드]

Ship *ship = ...; // Ship 인스턴스 died = [ship dropBomb:cracker at:dropPoint from:300.0];

[클래스 메소드]

Ship *ship = [Ship motherShip];

NSString *str =

[NSString StringWithFormat:@"%g",r];

[[ship class] doSomething];

ship은 인스턴스

인스턴스 메소드 “class”는 클래스를 반환

“doSomething”은 클래스 메소드

(16)

인스턴스 vs 클래스 메소드

- 기호로 시작

보통의 메소드

호출 문법

• self/super는 인스턴스

self : 자신의 인스턴스 메소드

호출

super : 수퍼클래스의 인스턴스

메소드 호출

+ 기호로 시작

• 생성 & 유틸리티 메소드

호출 문법

• self/super는 클래스

self : 자신의 클래스 메소드 호

super : 수퍼클래스의 클래스 메

소드 호출

- (BOOL)dropBomb:(Bomb *)bomb

at:(CGPoint)position from:(double)altitude;

+ (id) alloc;

+ (Ship *)motherShip;

+ (NSString *)stringWithFormat:...

[<인스턴스 포인터> 메소드]

Ship *ship = ...; // Ship 인스턴스 died = [ship dropBomb:cracker at:dropPoint from:300.0];

[클래스 메소드]

Ship *ship = [Ship motherShip];

NSString *str =

[NSString StringWithFormat:@"%g",r];

[[ship class] doSomething];

(17)

메소드

다양한 메소드의 예

- (double)performOperation:(NSString *)operation;

- (NSMutableArray *)operandStack;

- (NSString *)stringByAppendingString:(NSString *)otherString;

- (void)doSomething;

- (void)doSomethingWithThingOne:(Thing *)one andThingTwo:(Thing *)two;

- (NSArray *)collectButterfliesWithSpotCount:(int)spots;

- (NSComparisonResult)compare:(NSString *)aString

options:(NSStringCompareOptions)mask range:(NSRange)range;

+ (double)yieldForPhotonTorpedoOfType:(PhotonTorpedoType)type;

(18)

인스턴스 생성 (Instantiation)

다른 객체로부터 새로운 객체 생성

‣ NSString: - (NSString *)stringByAppendingString:(NSString *)otherString;

‣ NSString & NSArray: - (id)mutableCopy;

‣ NSArray: -(NSString *)componentsJoinedByString:(NSString *)separator;

항상 새로운 객체를 생성하지는 않음

‣ NSArray: - (id)lastObject;

‣ NSArray: - (id)objectAtIndex:(int)index;

‣ 이미 존재하는 객체의 경우 포인터만 반환 (새로 생성하지 않음)

클래스 메소드를 이용한 객체 생성

‣ NSString: + (id)stringWithFormat:(NSString *)format, ...;

‣ UIButton: + (id)buttonWithType:(UIButtonType)buttonType;

‣ NSMutableArray: + (id)arrayWithCapacity:(int)count;

‣ NSArray: + (id)arrayWithObject:(id)anObject;

(19)

인스턴스 생성 (Instantiation)

• 객체를 직접 생성하기

‣ 2 단계 필요 : 메모리 할당(allocation)과 초기화(initialization)

‣ 1단계 후에 2단계를 위한 메소드 바로 호출

NSMutableArray *stack = [[NSMutableArray alloc] init];

CalculatorBrain *brain = [[CalculatorBrain alloc] init];

(20)

인스턴스 생성 (Instantiation)

메모리 할당

‣ NSObject의 클래스 메소드 + (id)alloc 이 힙에 메모리 할당

‣ 모든 인스턴스 변수를 위한 공간 할당

초기화

‣ 기본적인 인스턴스 메소드인 - (id)init 메소드만 정의하거나

‣ 좀 더 복잡하고 다양한 - (id)init* 메소드 정의

‣ 초기자, 초기화 메소드, 이니셜라이저, ...

(21)

인스턴스 생성 (Instantiation)

• 좀 더 복잡한 init 메소드

‣ 객체 초기화에 인자가 필요하면 init으로 시작하는 이름으로 메소드 정의

• 다양한 초기자를 갖는 NSString의 예

예) - (id)initWithFrame:(CGRect)aRect // UIView를 위한 초기화 메소드 UIView *myView = [[UIView alloc] initWithFrame:thePerfectFrame];

- (id)initWithCharacters:(const unichar *)characters length:(int)length;

- (id)initWithFormat:(NSString *)format, ...;

- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding;

(22)

인스턴스 생성 (Instantiation)

• 지정된 초기자 (designated initializer)

‣ 다수의 초기자가 있는 경우, 대표적인 메소드를 하나 지정

‣ 다른 초기자(편의 초기자)는 지정된 초기자를 호출하여 초기화

‣ 서브클래스의 지정된 초기자는 수퍼클래스의 지정된 초기자를 호출 하여 초기화

‣ 서브클래스의 편의 초기자는 서브클래스의 지정된 초기자를 호출하 여 초기화

(23)

인스턴스 생성 (Instantiation)

• 초기자가 반환하는 객체의 타입

‣ 초기자는 서브클래스에서 호출될 수 있으므로, id 타입을 반환하도록 함

‣ id : 모든 클래스 객체를 가리킬 수 있는 포인터

‣ 반환된 객체 포인터를 원하는 객체 포인터로 변환 (정적 타이핑의 예)

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

(24)

인스턴스 생성 (Instantiation)

• 지정된 초기자 만들기

@implementation MyObject - (id)init

{

self = [super init]; // 수퍼클래스의 지정된 초기자 if (self) {

// 서브클래스를 위한 초기화 작업 }

return self; // [super init]이 실패면 서브클래스 초기화도 실패 }

@end

(25)

인스턴스 생성 (Instantiation)

편의 초기자 만들기

@implementation CalculatorBrain

- (id)initWithValidOperations:(NSArray *)anArray {

self = [self init];

self.validOperations = anArray; // self가 nil이면 아무일도 하지 않음 }

@end

수퍼클래스가 아닌 현재 클래스의 지정된 초기자 호출 초기화 작업을 변경하고 싶으면 지정된 초기자만 변경 지정된 초기자에서만 수퍼클래스의 지정된 초기자 호출

(26)

동적 바인딩

• 모든 객체는 힙(heap)에 할당

‣ 즉, 포인터 변수만 사용 가능

NSString *s = ...; // 정적 타이핑 (컴파일 타임에 타입 결정) id obj = s; // 동적 타이핑 (런타임에 타입 결정)

‣ “id” 자체가 포인터, “id *”는 이중 포인터

• 메시지 전송에 실행할 코드는 런타임에 결정

‣ 메소드가 없으면, 컴파일 타임에는 경고만 발생

‣ 메소드가 없으면, 런 타임에 예외 발생, 프로그램 종료

• 포인터 변수의 타입 변환(캐스팅)

id obj = ...;

NSString *s = (NSString *)obj;

‣ 위험한 코드가 될 수 있음 (인트로스펙션 사용 !)

(27)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move]; 컴파일러 경고 없음

s는 Vehicle이기도 하므로 문제 없음

s “isA” Vehicle (s는 Vehicle에 isA 관계 성립)

(28)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

컴파일러 경고 없음

s는 Vehicle이기도 하므로 문제 없음

(29)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

컴파일러 경고 발생 런타임에는 문제 없음

우리는 s가 원래 Ship 객체임을 알지만, 컴파일러는 s를 Vehicle 객체로 간주

(30)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

id obj = ...;

[obj shoot];

컴파일러 경고 없음

런타임에는 예외 발생 가능, 프로그램 종료 가능 컴파일러는 shoot이라는 메소드를 알고 있음 id는 어떤 객체도 가리킬 수 있으므로,

shoot 메시지에 반응을 할 수도 있다고 생각함 만약, NSObject *obj 라면 컴파일러 경고 발생

(31)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

id obj = ...;

[obj shoot];

[obj someMethodNameThatNoObjectAnywhereRespondsTo];

컴파일러 경고 발생

런타임에도 예외 발생, 프로그램 종료 컴파일러는 처음 본 메소드

(32)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

id obj = ...;

[obj shoot];

[obj someMethodNameThatNoObjectAnywhereRespondsTo];

NSString *hello = @”hello”;

[hello shoot];

컴파일러 경고 발생

런타임에도 예외 발생, 프로그램 종료

컴파일러는 NSString 클래스에 shoot 메소드가 없는 것을 알고 있음

(33)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

id obj = ...;

[obj shoot];

[obj someMethodNameThatNoObjectAnywhereRespondsTo];

NSString *hello = @”hello”;

[hello shoot];

Ship *helloShip = (Ship *)hello;

컴파일러 경고 없음 런타임에도 문제 없음

(34)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

id obj = ...;

[obj shoot];

[obj someMethodNameThatNoObjectAnywhereRespondsTo];

NSString *hello = @”hello”;

[hello shoot];

Ship *helloShip = (Ship *)hello;

[helloShip shoot];

컴파일러 경고 없음

런타임에 예외 발생, 프로그램 종료

(35)

객체 타이핑

@interface Vehicle : NSObject - (void)move;

@end

@interface Ship : Vehicle - (void)shoot;

@end

Ship *s = [[Ship alloc] init];

[s shoot];

[s move];

Vehicle *v = s;

[v shoot];

id obj = ...;

[obj shoot];

[obj someMethodNameThatNoObjectAnywhereRespondsTo];

NSString *hello = @”hello”;

[hello shoot];

Ship *helloShip = (Ship *)hello;

컴파일러 경고 없음

런타임에 예외 발생, 프로그램 종료

(36)

인트로스펙션 (Introspection)

• 언제 id를 사용하는가?

‣ NSArray 배열은 서로 다른 종류의 객체 보관이 가능

‣ 배열의 원소에 메시지를 보내기 전에 클래스를 알아야 함

• 모든 NSObject 서브클래스의 메소드

‣ isKindOfClass: 해당 클래스인지 조사 (서브클래스 포함)

‣ isMemberOfClass: 해당 클래스인지만 조사

‣ respondToSelector: 해당 메소드가 있는지 조사

(37)

인트로스펙션 (Introspection)

• 인트로스펙션 메소드의 인자

‣ 클래스의 경우 class라는 클래스 메소드 사용

‣ 메소드의 경우 셀렉터(SEL) 타입 사용

‣ @selector() 키워드로 SEL 타입 생성

if ([obj isKindOfClass:[NSString class]]) {

NSString *s = [(NSString *)obj stringByAppendingString:@"xyzzy"];

}

if ([obj respondsToSelector:@selector(shoot)]) { [obj shoot];

}

(38)

인트로스펙션 (Introspection)

• SEL은 셀렉터를 위한 오브젝티브 C 데이터 타입

SEL shootSelector = @selector(shoot);

SEL moveToSelector = @selector(moveTo:);

‣ 타겟/액션에서 주로 사용

[button addTarget:self action:@selector(digitPressed:)];

• 셀렉터를 이용하여 메소드 수행 가능

‣ NSObject의 performSelector:

performSelector:withObject: 메소드 사용

[obj performSelector:shootSelector];

[obj performSelector:moveToSelector withObject:coordinate];

(39)

Foundation 프레임워크

NSObject

‣ iOS SDK의 모든 객체의 베이스 클래스

‣ 메모리 관리 메소드 구현

‣ 인트로스펙션 메소드 구현

‣ -(NSString *)description 메소드 구현

- 주로 오버라이딩 하여 사용

- NSLog() 함수의 %@ 부분에 사용 - 객체를 설명하기 위한 메소드

(40)

Foundation 프레임워크

NSString

‣ 유니코드 기반의 문자열 객체 (다국어 지원)

‣ iOS SDK에서는 C의 char* 대신 NSString 사용

‣ 문자열 상수는 @”foo”와 같이 문자열 앞에 @문자 사용

‣ NSString 객체는 변경 불가능 → 이뮤터블 데이터 타입

‣ 주로 NSString 객체에 메시지를 보내어 새로운 객체 생성

[display setText:[[display text] stringByAppendingString:digit]];

// display의 text 프로퍼티 문자열 뒤에 digit을 붙인 후 다시 설정 display.text = [display.text stringByAppendingString:digit];

// 위와 동일한 작동 (프로퍼티의 게터와 세터 실행)

display.text = [NSString stringWithFormat:@"%g", brain.operand];

// 클래스 메소드 사용: 팩토리 메소드 패턴의 예

‣ 많은 유틸리티메소드 제공

(41)

Foundation 프레임워크

• NSMutableString

‣ 변경 가능한 문자열 객체

‣ NSString의 서브 클래스

‣ 새로운 객체를 생성하지 않고 변경 가능

NSMutableString *mutString = [[NSMutableString alloc] initWithString:@“0.”];

[mutString appendString:digit];

(42)

Foundation 프레임워크

NSNumber

‣ int, float, double, BOOL등과 같은 기본 데이터 타입의 객체화를 위한 래퍼(wrapper) 클래스

NSNumber *num = [NSNumber numberWithFloat:36.5];

float f = [num floatValue];

‣ 객체만 담을 수 있는 컬렉션 데이터 타입에 유용 ( NSArray, NSDictionary, NSSet)

NSValue

‣ 구조체나 포인터 타입의 객체화

CGPoint point = CGPointMake(25.0, 15.0);

NSValue *val = [NSValue valueWithCGPoint:point];

CGPoint point2 = [val CGPointValue];

(43)

Foundation 프레임워크

NSData

‣ 바이트 단위의 raw 데이터

‣ 저장, 읽기, 전송 등에 사용

NSDate

‣ 날짜와 시간을 위한 클래스

‣ 현재 시간을 알아오거나, 시간에 대한 정보 저장

‣ NSCalendar, NSDateFormatter, NSDateComponent 등과 함께 사용

(44)

Foundation 프레임워크

NSArray

‣ 순서가 있는 컬렉션 타입

‣ 이뮤터블(변경 불가능), 생성할 때만 멤버 추가 가능

+ (id)arrayWithObjects:(id)firstObject, ...; // nil로 끝나는 다수의 객체 NSArray *primaryColors =

[NSArray arrayWithObjects:@"red", @"yellow", @"blue", nil];

+ (id)arrayWithObject:(id)soleObjectInTheArray; // 생각보다 유용!

- (int)count;

- (id)objectAtIndex:(int)index;

- (id)lastObject; // 원소가 하나도 없으면 nil 반환, 매우 유용!

- (NSArray *)sortedArrayUsingSelector:(SEL)aSelector;

- (void)makeObjectsPerformSelector:(SEL)aSelector

withObject:(id)selectorArgument;

- (NSString *)componentsJoinedByString:(NSString *)separator;

- (BOOL)containsObject:(id)anObject; // 느림, 대신에 NSOrderedSet 사용

(45)

Foundation 프레임워크

• NSMutableArray

‣ 원소를 바꿀 수 있는 배열

+ (id)arrayWithCapacity:(int)initialSpace; // initialSpace: 성능에 도움 + (id)array;

- (void)addObject:(id)anObject; // 배열 끝에 추가

- (void)insertObject:(id)anObject atIndex:(int)index;

- (void)removeObjectAtIndex:(int)index;

- (void)removeLastObject;

- (id)copy; // 이뮤터블 NSArray 반환

// 이뮤터블에서 뮤터블 생성: mutableCopy 사용

‣ 위 외에도 NSArray의 모든 메소드 사용 가능 (NSMutableArray는 NSArray의 서브클래스)

(46)

Foundation 프레임워크

• NSDictionary

‣ 키(key)로 원소(value)에 한번에 접근 (해시 테이블, 맵)

‣ 이뮤터블(변경 불가능), 생성할 때만 멤버 추가 가능

‣ 키는 다음 메소드를 구현하는 객체만 가능

- (NSUInteger)hash;

- (BOOL)isEqual:(NSObject *)obj;

‣ NSObject는 포인터 값을 hash 값으로 사용

‣ NSObject는 포인터 값이 같으면 isEqual:의 결과가 YES

‣ 주로 NSString을 키로 사용

(47)

Foundation 프레임워크

• NSDictionary

‣ 주요 메소드

+ (id)dictionaryWithObjects:(NSArray *)values forKeys:(NSArray *)keys;

+ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;

NSDictionary *base = [NSDictionary dictionaryWithObjectsAndKeys:

[NSNumber numberWithInt:2], @"binary",

[NSNumber numberWithInt:16], @"hexadecimal", nil];

- (int)count;

- (id)objectForKey:(id)key;

- (NSArray *)allKeys;

- (NSArray *)allValues;

(48)

Foundation 프레임워크

• NSMutableDictionary

‣ 변경가능한 NSDictionary

+ (id)dictionary; // 빈 디렉토리 생성

// 이 외에도 NSDictionary의 다양한 초기자 사용 가능 - (void)setObject:(id)anObject forKey:(id)key;

- (void)removeObjectForKey:(id)key;

- (void)removeAllObjects;

- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;

(49)

Foundation 프레임워크

NSSet

‣ 순서가 없는 컬렉션 타입

‣ 이뮤터블(변경 불가능), 생성할 때만 멤버 추가 가능

‣ 주요 메소드

- (int)count;

- (BOOL)containsObject:(id)anObject;

// anObject가 있는지 조사 ( == 비교) - (id)anyObject;

// 순서가 없으므로, 아무 객체나 반환 - (void)makeObjectsPerformSelector:(SEL)aSelector;

- (id)member:(id)anObject;

// isEqual 메소드 사용

// isEqual 메소드에 따라 결과가 다름

‣ 모든 원소는 유일 (NSCountedSet는 중복된 원소도 가능)

(50)

Foundation 프레임워크

• NSMutableSet

‣ 변경이 가능한 NSSet

- (void)addObject:(id)anObject; // 같은 원소가(isEqual: 메소드 사용) // 이미 있으면 아무 일도 안함

- (void)removeObject:(id)anObject;

- (void)unionSet:(NSSet *)otherSet;

- (void)minusSet:(NSSet *)otherSet;

- (void)intersectSet:(NSSet *)otherSet;

(51)

Foundation 프레임워크

• NSOrderedSet

‣ 순서가 있는 컬렉션 타입

‣ 이뮤터블(변경 불가능), 생성할 때만 멤버 추가 가능

‣ 모든 원소는 유일

‣ NSArray와 NSSet의 중간 형태

‣ NSArray보다 “contains” 메소드가 빠름

‣ NSSet 과는 달리 순서가 있음

‣ NSSet의 서브클래스는 아니지만 거의 유사한 메소드 제공

‣ NSMutableOrderedSet 도 사용 가능

(52)

열거 (Enumeration)

• 컬렉션의 멤버를 for 루프에서 열거

for in 키워드 사용

‣ 예) NSString의 NSArray

NSArray *myArray = ...;

for (NSString *string in myArray) {

double value = [string doubleValue];

} // 만약 string이 NSString이 아니면 오류 발생

‣ id의 NSSet

NSSet *mySet = ...;

for (id obj in mySet) {

if ([obj isKindOfClass:[NSString class]]) { // NSString 메소드를 안전하게 실행

} }

(53)

Foundation 프레임워크

• 딕셔너리 타입에서의 열거

NSDictionary *myDictionary = ...;

for (id key in myDictionary) {

! // key에 대한 처리

! id value = [myDictionary objectForKey:key];

! // value에 대한 처리 }

(54)

프로퍼티 리스트

• 계층 구조로 이루어진 컬렉션 데이터 타입

‣ 다음 클래스 객체로만 이루어진 트리 형태의 자료 구조

- NSArray, NSDictionary, NSNumber, NSString, NSDate, NSData

‣ 멤버가 모두 프로퍼티 리스트인 NSArray도 프로퍼티 리스트 - NSString의 NSArray도 프로퍼티 리스트

- 위 NSArray를 멤버로 갖는 NSArray도 프로퍼티 리스트

‣ 모든 키와 밸류가 프로퍼티 리스트인 NSDictionary도 프로퍼티 리스트

- 키가 NSString이고 밸류가 NSNumber인 NSDictionary를 멤버로 갖는 NSArray도 프로퍼티 리스트

(55)

프로퍼티 리스트

용도

‣ 파일로 저장, 읽어 오기 가능

‣ 인터넷으로 부터 전송 받은 데이터로 객체 생성 가능

[plist writeToFile:(NSString *)path atomically:(BOOL)];

plist = [NSArray arrayWithContentsOfFile:@"path"];

(56)

프로퍼티 리스트

• NSUserDefaults

‣ 프로퍼티의 응용 예

‣ 프로그램이 종료되어도 항상 저장되어 있는 NSDictionary

‣ 간단한 환경 설정 데이터를 저장할 때 적합

‣ 주로 standardUserDefaults라는 클래스 메소드로 객체 얻어옴

[[NSUserDefaults standardUserDefaults] setArray:rvArray

forKey:@"RecentlyViewed"];

(57)

프로퍼티 리스트

• NSUserDefaults

‣ 주요 메소드

- (void)setDouble:(double)aDouble forKey:(NSString *)key;

- (NSInteger)integerForKey:(NSString*)key;

- (void)setObject:(id)obj forKey:(NSString *)key;

// obj도 프로퍼티 리스트 - (NSArray *)arrayForKey:(NSString *)key;

// 만약 밸류가 NSArray가 아니면 nil 반환

‣ 저장

[[NSUserDefaults standardUserDefaults] synchronize];

(58)

알림

• 이 문서는 iTunesU “iPAD and iPhone Application

Development”(Fall 2011-2012) 강좌에서 제공하는 자료를 번역, 수 정 및 재구성한 것으로 원본은 http://www.stanford.edu/class/

cs193p/cgi-bin/drupal/ 에서 다운로드 가능합니다.

• 이 콘텐츠는 크리에이티브 커먼즈 저작자표시-비영리-동일조건변 경허락 3.0 미국 라이선스에 따라 이용할 수 있습니다. 라이선스 전 문을 보시려면 http://creativecommons.org/licenses/by-nc-sa/3.0/us/

를 방문하거나, 다음의 주소로 서면 요청해주십시오. Creative

Commons, 444 Castro Street, Suite 900, Mountain View, California,

94041, USA

참조

관련 문서

수험생은 지원한 대학이 지정하는 장소에 지정된 시각까지 반드시 입실하여 관계자의 안내에 따라야 하며, 지정된 시각까지 고사장에 입실하지

수험생은 지원한 대학이 지정하는 장소에 지정된 시각까지 반드시 입실하여 관계자의 안내에 따라야 하며, 지정된 시각까지 고사장에 입실하지

합숙 환경이 평소 생활환경과 달라 불편할 수 있으나, 동료 멘토들과의 공동 생활 자체가 뜻깊은 경험의 기회가 됩니다.. 지정된

수험생은 지원한 대학이 지정하는 장소에 지정된 시각까지 반드시 입실하여 관계자의 안내에 따라야 하며, 지정된 시각까지 고사장에 입실하지

수험생은 지원한 대학이 지정하는 장소에 지정된 시각까지 반드시 입실하여 관계자의 안내에 따라야 하며, 지정된 시각까지 고사장에 입실하지 못하여 발생하는 불이익은 수험생이 감수하여야

수험생은 지원한 대학에서 지정하는 장소에 지정된 시간까지 반드시 입실하여 관계자의 안내에 따라야 하며, 지정된 시간까지 고사장에 입실하지

수험생은 지원한 대학에서 지정하는 장소에 지정된 시간까지 반드시 입실하여 관계자의 안내에 따라야 하며, 지정된 시간까지 고사장에 입실하지

• 그 밖의 경우 물품이 매도인의 운송수단 상에서 양화되지 아니하고 매수인에 의하여 지정된 운송인 또는 기타의 자의 임의처분상태로 둘 때 인도가 완료되는 것이며