BLOG main image
분류 전체보기 (92)
Cocoa Touch (11)
Cocoa (10)
Objective-C (13)
Swift (6)
Development (11)
Tools (11)
Books (7)
etc (21)
Application release (1)
Document Project (1)
105,799 Visitors up to today!
Today 2 hit, Yesterday 2 hit
daisy rss
tistory 티스토리 가입하기!
'ios'에 해당되는 글 2건
2015. 6. 18. 18:09

Objective-C를 처음 접했을 때 가장 마음에 드는 것 중 하나가 collection에 저장될 수 있는 객체의 타입이 달라도 된다는 것이었다. 하나의 array안에 NSString과 NSNumber를 같이 넣는 다는 것은 C++을 주로 사용하던 나에게는 정말 충격적인 일이었다.


세월이 흘러 어느덧 Swift라는 새로운 언어에 익숙해져야 하는 순간이 왔다. 첫 인상부터 별로였던지라 (genertic이 첫 인상을 나쁘게 하는데 일조했다.) 마지못해서 슬슬 보고는 있는데... 역시 오늘 완전 사람 속을 뒤집어 놓는 케이스를 만났다.


JSON 데이터를 파싱하는 NSJSONSerialization 클래스를 한번 보자.


+ (id nullable)JSONObjectWithData:(NSData * nonnull)data
                          options:(NSJSONReadingOptions)opt
                            error:(NSError * nullable * nullable)error // nullable은 도대체 또 뭐냐


위는 Objective-C의 경우이다. 리턴 타입이 id라고 되어있지만 우리는 경험상 이것이 NSArray거나 NSDictionary임을 알고 있다.

그냥 안에든 객체를 id로 다루면 아무 문제없이 깔끔하게 원하는 작업을 수행할 수 있다.


하지만...


다음은 Swift이다 . Objective-C에서 id는 즉 Swift에서 AnyObject. 뭐 이 정도는 봐줄만 하다.


class func JSONObjectWithData(_ data: NSData,
                      options opt: NSJSONReadingOptions) throws -> AnyObject


가지고 있는 JSON이 Dictionary라는 사실은 알고 있다. 그래서 다음과 같은 방법으로 casting을 시도했다.


let dict = jsonObject as? [AnyObject: AnyObject]

let dict = jsonObject as? [AnyObject: Any]


Objective-C에서는 key는 NSCopying만 지원하면 된다고 규정하고 있고 value는 id이면 뭐든 가능하다.

첫 시도는 가당찮게 에러를 보는 것으로 끝났다. 그럼 어떻게 하면 되지?


let dict = jsonObject as? [NSCopying: AnyObject]


위는 어처구니 없는 다음 시도였으나 될리가 없다. 안될 것이라고 생각하고 쓴 멍청한 코드다.

잠시 머리를 돌려본다. Dictionary의 key 조건은 hashable이다. 이렇게 해본다.


let dict = jsonObject as? [HashableAnyObject]


역시 에러다. 이쯤되면 조금 짜증이 나기 시작한다. 다시 다음과 같은 방법들도 써본다


let dict = jsonObject as? Dictionary<AnyObject, AnyObject>

let dict = jsonObject asDictionary<HashableAnyObject>

let dict = jsonObject asDictionary<AnyObjectAnyObject?>


역시 안된다. 이쯤되면 완전 짜증이 머리 끝까지 솟구친다.

키를 string으로 제한시켜본다.


let dict = jsonObject as? Dictionary<String, AnyObject>

let dict = jsonObject as? [StringAnyObject]


아... 이제 된다. 키가 String이 아닌 dictionary나 가변적인 경우는 어떡하지? 하지만 이런 고민은 잠시 접어두자. 된것만 해도 어디냐며...

여기에 키의 타입을 바꾸거나 value의 타입을 바꾸면 또 안된다. 아, value를 AnyObject?로 해도 안됨을 주의!


이 사단은 별로 유용하지도 않은 generic이라는 이상한걸 들고와서 벌어진 일이다.

Objective-C를 사용하던 사람입장에서는 Swift의 casting과 generic이 얼마나 사람을 열받게  만드는지 한번 느껴보시기 바란다.

yagom | 2015.06.19 01:53 신고 | PERMALINK | EDIT/DEL | REPLY
저는 그래서 JSON 파싱은 Objective-C로 해요...^^; 마음속에서 솟구쳐 오르는 저 무언가를 참기는 힘들 것 같아요...ㅎㅎ
maccrazy | 2015.06.19 09:40 신고 | PERMALINK | EDIT/DEL
:) 그런 방법을 쓰시는군요.
저는 한 프로젝트에 여러 언어를 섞어쓰는 것을 좀 싫어해서 swift로 하면 최대한 swift로 하고 있는데 계속 마음속에서 뭔가가 솟구치는군요. ㅋㅋ
하지만 뭐 어쩌겠습니다. 돌이키기엔... 애플이 그리로 가겠다는데 방법이 없네요.
Name
Password
Homepage
Secret
2011. 1. 1. 23:18
Asset Library를 사용해서 AssetsGroup을 가져오기 위해서 사용하는 block인 ALAssetsLibraryGroupsEnumerationResultsBlock(휴.. 길다.)을 사용할 때 enumeration을 중단 시키고 싶을 때는 어떻게 하라고 되어있는데 어이없게도 enumeration이 종료 되었을 때를 어떻게 판단할 지는 문서화 되어있지 않다.
별도로 completion block을 설정하거나 completion  notification이 정의 되어있지 않은걸 보니 결국 ALAssetsLibraryGroupsEnumerationResultsBlock 파라메터 가지고 어떻게든 확인해봐야 한다는 결론이 나는데...
파라메터라는게  ALAssetsGroup과 BOOL *형의 stop(이것은 enumeration을 중단 시키기 위해서 사용된다.) 밖에 없다.
결국, ALAssetsGroup이 nil이면 enumeration이 종료된 것이라고 판단 할 수 밖에 없는데 (일단 그렇게 들어오는 듯 하다. 하지만 문서에는 없다.) 참 불안하지 않을 수 없다. 이왕이면 확실하게 문서화 해주던지 그걸로 판별하지 말라고 써놓던지...

결국, 결론은 "문서화 되어있지 않지만 ALAssetsGroup의 값이 nil로 들어오면 끝난것 같다." 이다.

사족 : 굳이 completion 정보를 알 필요 있을까 싶기도 하다. 어차피 async로 작동되고 언제 끝날지도 모르는데 enumeration 될 때마다 정보를 모델에 넣고 UI를 갱신해도 될 것이라는... 그렇지만 asset의 수가 엄청나게 많을 때 reload되는데 문제 없을까? (이건 나중에 걱정하기로 하고...)
Name
Password
Homepage
Secret
prev"" #1 next