본문 바로가기
프로그래밍 놀이터/iOS

[Effective Objective-C] #3 메서드보다는 같은 일을 하는 리터럴 문법을 사용하라

by 돼지왕 왕돼지 2017. 7. 20.
반응형

 [Effective Objective-C] #3 메서드보다는 같은 일을 하는 리터럴 문법을 사용하라


출처 : Effective Objective-C

@, arraywithobjects, dictionarywithobjectsandkeys, effective objective-c, expression, Foundation, limitation, literal, literal array nil, literal dictionary nil, mutablecopy, nil, NSArray, NSDictionary, NSNumber, NSString, numberwithint, objectAtIndex, Objective-C, subscripting, syntactic sugar, variants, wrapping, [Effective Objective-C] #3 메서드보다는 같은 일을 하는 리터럴 문법을 사용하라, 가변, 간편 문법, 값-키 순, 리터럴 문법, 리터럴 배열, 리터럴 사전, 리터럴 숫자, 메서드, 문자열, 배열, 복사본, 불변 인자, 사전, 숫자, 안전, 제한, 첨자, 컴파일러 옵션, 크래시, 클래스 클러스터, 키-값 쌍, 하위 클래스


-

NSString, NSNumber, NSArray, NSDictionary 인스턴스 모두 리터럴 문법을 지원한다.



-

리터럴 문법을 사용하면 소스 코드 크기가 줄고 코드가 읽기 쉬워진다.




리터럴 숫자


-

정수, 실수, 불린 값을 Objective-C 로 감쌀(wrapping) 필요가 있다.

이는 숫자 타입을 다룰 수 있는 NSNumber 클래스를 이용해 할 수 있다.



-

리터럴을 쓰지 않으면 다음과 같이 생성한다.

NSNumber *number = [NSNumber numberWithInt:1];


그러나 리터럴을 사용하면 이렇게 간단하다.

NSNumber *number =  @1;



-

리터럴 문법은 표현식 (  expression ) 에도 작동한다.

NSNumber *number = @(x + y);




리터럴 배열


-

NSArray *animals = [NSArray arrayWithObjects:@“cat”, @“dog”, @“mouse”, @“badger”, nil];

=>

NSArray *animals = @[@“cat”, @“dog”, @“mouse”, @“badger” ];



-

리터럴 문법으로 배열을 생성할 때 주의해야 할 점이 있다.

만약 생성하려는 객체 중 단 하나라도 nil 이면 예외를 던진다.

리터럴 문법은 배열을 생성하고 대괄호 안에 있는 모든 객체를 배열에 추가해주는 간편 문법(syntactic sugar)이기 때문이다.



-

arrayWithObjects: 는 메서드의 내부 구현이 nil 인 인자 이전의 인자들만 받아들여 array 를 생성하게 되어 있다.

이 미묘한 차이 때문에 리터럴이 좀 더 안전하다.

기대했던 인자보다 적은 인자를 가진 채 배열이 생성되는 것보다 정당한 앱 크래시의 원인이 되는 예외가 던져지는 것이 더 낫기 때문이다.


cf)

syntactic sugar : 프로그래밍 언어에서 특정 문법을 좀 더 쉽게 읽을 수 있고 표현할 수 있게 하는 대체 문법



-

NSString *dog = [animals objectAtIndex:1]; 

=>

NSString *dog = animals[1];


이 방식도 리터럴의 한 종류인데, 첨자(subscripting)이라고 부른다.




리터럴 사전


-

NSDictionary *personData = [NSDictionary dictionaryWithObjectsAndKeys:@“Matt”, @“firstName”, “@Galloway”, @“lastName”, [NSNumber numberWithInt:28], @“age”, nil ];

=>

NSDictionary *personData = @{@“firatName” : @“Matt”, @“lastName” : @“Galloway”, @“age” : @28 };



-

dictionaryWithObject 는 사람들이 일반적으로 생각하는 키-값 쌍이 아니라, 값-키 순으로 입력해야 하기 때문에 개념적으로 더 어렵다.

리터럴은 그런 문제를 해결해준다. ( 키-값 쌍으로 표시 )



-

배열과 같이 사전 리터럴도 만일 값들 중 하나라도 nil 이면 예외를 던진다.

같은 이유로 이는 좋은 것이다.

dictionaryWithObjectsAndKeys: 메서드는 nil 이전의 값으로만 사전을 생성해서 의도치 않게 값을 읽어버리지만 사전 리터럴은 예외를 던지기 때문이다.



-

리터럴 문법으로 값에 접근도 가능하다.

NSString *lastName = [personData objectForKey:@“lastName”];

=>

NSString *lastName = personData[@“lastName”];




제한


-

리터럴 문법은 사소한 제한이 있다.

바로 생성된 객체의 클래스는 반드시 Foundation 프레임워크의 클래스여야 한다는 것이다. ( 문자열 제외 )

생성되기로 한 클래스 대신에 자신이 만든 커스텀 하위 클래스가 생성되게 하는 방법은 없다.


그러나 NSArray, NSDictionary, NSNumber 는 클래스 클러스터이기 때문에,

이 클래스들의 하위 클래스는 거의 만들지 않을 뿐 아니라 하위 클래스로 만들기도 쉽지 않다.

그리고 전반적으로 기능이 이미 잘 구현되어 있기 때문에 하위 클래스를 만들 필요도 거의 없다.


문자열은 커스텀 클래스를 사용할 수 있지만 컴파일러 옵션을 변경해야 한다.

이 옵션을 사용하는 것은 추천되지 않는다.

커스텀 구현에 대해 잘 알지 못한다면 그냥 NSString 을 사용하는 편이 더 낫기 때문이다.



-

문자열, 배열, 사전의 경우 불변 인자(variants)만 리터럴 문법에서 생성할 수 있다.

가변 인자가 필요하면 가변 복사본을 다음과 같은 방법으로 얻을 수 있다.

NSMutableArray *mutable = [@[@1, @2, @3, @4] mutableCopy];




기억할 점


-

문자열, 숫자, 배열, 사전을 생성할 때 리터럴 문법을 사용하라.

일반적인 객체 생성 메서드로 생성하는 것보다 더 명확하고 매우 간결한 방법이다.



-

배열의 인덱스, 사전의 키에 대한 접근은 첨자를 이용하라.



-

리터럴 문법으로 nil 을 배열이나 사전에 삽입하려고 하면 예외를 발생시킬 수 있으므로

배열이나 사전에 들어가는 값이 nil 이 아닌지 늘 확인하라.




반응형

댓글