후반에서는 Objective-C 문법이 변한 부분에 대한 내용이 많았다.
1. Modernization
Xcode 리펙토링부분에 보면 최신 Objective-C 문법으로 변환해주는 기능이 있는데, 이걸 설명하면서 최신 문법에 대한 설명이 있었다.
Modernize에서 커버해주는 기능이
- Object literals
- Container literals
- Subscripting
이 있고 더 자세한 내용은 WWDC 2012년 405를 보라고 한다.
여기서 literal이라 함은
[NSArray arraywith...] -> @[]
[NSNumber numberWith...] -> @1988
이런 식으로 간단하게 변한 부분을 말하는 것 같다.
Container는 Dictionary와 Array에 해당하는 부분 같은데,
Dictionary
[_dict objectForKey:@"key"] -> _dict[@"key"]
[_dict setObject:arg forKey:@"key"] -> _dict[@"key"] = arg;
Array
[_array objectAtIndex:0] -> _array[0]
[_array replaceObjectAtIndex:0 withObject:tmp] -> _array[0] = tmp
이렇게 변한부분을 말한다.
2. SDK Improvement
Xcode에서 실수하기 쉬운 부분을 오류로 잡아주는 부분이 향상됬다고 한다.
instancetype
리턴타입 에러 잡을 때 (NSDictionary 리턴해야 하는데 NSArray 리턴하는 경우) 예전에는 id가 리턴타입이어서 에러를 못잡았는데 이번엔 instancetype으로 바꼈다.
+ (instancetype)array;
instancetype은 리턴 타입을 위한 용도로 쓰인다.
만약에
dictionary *dic = [NSarray array]
이러면 array 리턴 타입이랑 dic 타입이 다르니까 오류 메세지를 띄우게 된다.
Explicitly-Typed Enums
예를 들어
NSURLHandleStatus status = NSURLSessionTaskStateRunning;
이러면 예전에는 enum이 int 였으므로 오류표시가 안난다. 개인적으로 이런 식의 실수를 은근히 했었다..
Before
enum {ABC,JKL, XYZ};
typedf NSUInteger MyEnum;
After
enum MyEnum : NSUInteger {ABC,JKL, XYZ};
typedf MyEnum MyEnum;
그 외의 워닝
예를들어
if () return NSURLHandleStatus;
else if () return NSURLSessionTaskStateRunning;
이런식으로 앞의 리턴과 뒤의 리턴타입이 다르면 에러 보여주게 변경됬다.
3. ARC 성능
맥에서 가비지 컬렉션을 없앨 모양인가보다. 새로 추가되는 API들은 ARC를 쓰도록 구현되었다고 한다.
그리고 __weak refernce가 iOS7.0이랑 OSX 10.9에서 거의 2배 빨라졌다고 한다.
ARC Migrator
migrator가 대부분은 해주지만 직접 해야하는 것도 있다.
migrator은 refactor 메뉴에서 찾을 수 있다.
migrator가 해주는 것
- retain/release/autorelease 삭제
- 빈 dealloc 메소드 삭제
- NSAutoreleasePool을 @autoreleasepool로 변환
그 외의 해야 하는 부분
- 구조체에 있는 “id”
- 이게 가능한지 몰랐다.. 찾아보니 id 타입이 C 언어에 정의되어있다고 한다. ( /usr/include/objc/objc.h )
- 메모리 관리 API 사용하는 부분
CoreFondation and ARC
CFBridgingRetain()하면 카운트가 1 오르고, CFBridgingRelease()하면 카운트가 1 줄어든다.
그리고 __bridge로 캐스팅하면 카운트가 그대로라 실수를 줄일 수 있다.
보통 CF 함수들은 “..create()”와 ..copy..()” 같은 것들은 카운트 1을 늘린다.
그 외의 것은 카운트가 그대로이다.
예외상황을 위해서 CF_RETURNS_RETAINED, CF_RETURNS_NOT_RETAINED, CF_RELEASES_ARGUMENT가 있다.
이번에 추가된 것은 위의 내용들을 암시적으로 bridging하는 것이 허용됬다.
사용방법은 CF_IMPLICIT_BRIDGING_ENABLED, CF_IMPLICIT_BRIDGING_DISABLED 이 둘 사이에 암시적으로 쓰는 내용을 넣으면 되는 것 같다. 아래는 예제이다.
#include <CoreFoundation/CoreFoundation.h>
CF_IMPLICIT_BRIDGING_ENABLED
EXArrayRef EXFooCreateCopy(…);
const void *EXFooGetValueAtIndex(EXArrayRef theArray, CFIndex idx);
const void *EXFooRandomPlusOne(EXArrayRef theArray) FC_RETURNS_RETAINED;
CF_IMPLICIT_BRIDGING_DISABLED
IMPLICIT 블락이 내에서 FC_RETURNS_RETAINED를 추가한 이유는 이름 보고 정확히 retain을 해야할지 카운트를 그대로 둬야할지 헷갈려서 쓴거라고 했던 것 같다..