Objective-C Tips from WWDC 2013

애플 WWDC2013, Session 228에 소개된 내용들 중 iOS나 Mac 개발시 자주쓰일만한 팁들을 추려내서 간단히 정리해보았다.

서브스크립팅(subscripting) 사용하기

Modern Objective-C 문법이 적용되면서 NSDictionary나 NSArray같은 foundation 데이터 구조객체들은 서브스크립팅을 이용하여 다음과같이 간결하게 작성이 가능하게되었다.

[myArray objectAtIndex:3] -> myArray[3]
[myDictionary objectForKey:@"key"] -> myDictionary[@"key"]

사용자가 만든 커스텀 클래스에도 서브스크립팅을 위한 set/get메서드만 잘 정의해두면 훨씬 더 간결한 프로그램 작성이 가능하다.

MyCustomArray 클래스에

위 두가지 메서드 구현시 다음과같이 배열처럼 인덱스로 바로 접근 가능

get: NSLog(@“%@“, myCustomInstance[1]);

set: myCustomInstance[0] = @“test";

딕셔너리(dictionary)의 경우 아래 두가지 메서드를 구현해주면 된다.

NSExpression: 문자열로된 수식 계산

스트링(string)형태로 된 수식을 계산하고 싶을때 유용하게 사용될 수 있다.

위 코드의 출력값은 result: 200000000003 이다.

NSArray reverse ordering

reverseObjectEnumerator를 사용하면 손쉽게 reverse array를 만들 수 있다.

NSNumber vs. NSValue

Objective-C를 접한지 얼마 안된경우 이 비슷한 이름을 가진 두가지 클래스의 차이점이 뭔지 헷갈릴경우가 많다.

구분하자면,

  • NSNumber의경우 int, float, bool 등의 원시 타입(primitive type)을 객체화시켜 저장하는데 사용
  • NSValue의 경우 scalar값들이나 struct (NSRange, CGPoint, NSRect 등)을 객체화시켜 저장

예1)

예2) 사용자정의 구조체

NSString이 아닌 객체를 dictionary의 key로 사용하기

딕셔너리에 키(key)에 대해 값(value)를 셋팅할경우, 키는 항상 copy되어 사용되기때문에 키로 사용되는 클래스는 항상 NSCopying 프로토콜을 따라야한다. 일반적으로 딕셔너리의 키값으로 많이 사용되는 NSString의 경우 이 프로토콜을 따르고있다.

myObject 객체가 NSCopying 프로토콜을 따를경우 에는 다음과 같이 사용해도 아무 문제가 없지만

NSCopying 프로토콜을 따르지 않을경우 크래쉬가 발생한다. 이때 해당 객체가 NSCopying프로토콜을 따르도록 수정해도되지만, 해당객체가 다른 라이브러리에서와서 직접적인 수정이 어려운 경우 다음과같이 NSValue 객체로 한번 wrapping 해주면 문제가 해결된다(NSValueNSCopying프로토콜을 따르기 때문).

valueWithNonRetainedObject: 메서드의 경우 해당 객체(object)를 retain하지 않는다는 점에 주의해야 한다.

NSDataDetector

자주사용되는 특정 스트링 패턴을 긴 문자열내에서 손쉽게 추출해주는 라이브러리.

  • Dates
  • Addresses
  • Links
  • Phone numbers

    NSString *string = @”123 Main St. / (555) 555-5555″;
    NSError *error;
    NSDataDetector *detector = [NSDataDetector
    dataDetectorWithTypes:NSTextCheckingTypeLink |
    NSTextCheckingTypePhoneNumber
    error:&error];
    [detector enumerateMatchesInString:string
    options:kNilOptions
    range:NSMakeRange(0, [string length])
    usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags,
    BOOL *stop) {
    NSLog(@”Match: %@”, result);
    }];