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)
106,090 Visitors up to today!
Today 0 hit, Yesterday 7 hit
daisy rss
tistory 티스토리 가입하기!
'2015/06'에 해당되는 글 4건
2015. 6. 23. 00:40

Swift에서 사라진 performSelector를 대신해서 구현하는 많은 방법들, 예를 들면 GCD, 클로져, 타이머, 심지어 NSThread를 동원하는 방법들이 거론되고 있지만 진정한 핵심을 놓치고 있는것 같다.
대체 가능한 수단이 존재하는 것은 사실이다. (물론 훨씬 지저분한 방법으로...) 하지만 가장 중요한 것은 객체와 메시지로 설명되는 객체지향의 가장 기본적인 내용 및 그것을 가장 우아하게 구현한 ObjC의 기능을 Swift에는 넣지 않았다는 것이다.
객체지향의 관점에서 Swift는 ObjC보다 한참 못한 언어인것 같다.

Name
Password
Homepage
Secret
2015. 6. 20. 00:55

종암님이 예전이 쓰셨던 글을 봤네요.

 

https://jongampark.wordpress.com/2014/10/16/swift-f-script/

 

오랫동안 잊고 있었던 수많은 삽질들의 기록을 어찌 이렇게 잘 해두셨는지.. :)

Swift가 이전 삽질과는 다른 것이 분명해 보이네요. 앞으로 어떻게 될지 궁금하기도 합니다.

결국 Cocoa Framework의 새 주인은 수많은 삽질끝에 Swift로 정리될 것인지...

Name
Password
Homepage
Secret
2015. 6. 19. 17:53


어떤 함수 안에서 특정 변수의 조건이 만족될 때 실행되어야 하는 코드가 있다고 하자

if-let문을 사용하게 되면 아래와 같이 if-let 피라미드를 쌓아 올리게 된다.


        if let id = info[“id"] as? NSNumber {

            if let userId = info[“userId"] as? NSNumber {

//  구현

            }

        }

        return



이렇게 피라미드가 쌓이는 꼴을 못보겠다면 다음과 같은 방법도 있다.


        if let id = info[“id"] as? NSNumber,

           let userId = info[“userId"] as? NSNumber {

// 구현

}

return


하지만 이 역시 별로 예뻐보이지는 않는다. 그래서 early exit를 하는 코드를 작성하기로 한다.


        let id = info[“id"] as? NSNumber

        if id == nil {

            return

        }

        let userId = info[“userId"] as? NSNumber

        if userId == nil {

            return

        }


뭔가 주절 주절 널어지는 느낌을 지울 수 없다.

그래 guard를 한번 써보자.


        guard let id = info[“id"] as? NSNumber,

              let userId = info[“userId"] as? NSNumber else {

                return

        }


이거나 if-let,let else 나... 아래를 보자. 어차피 else가 들어가긴 마찬가지 아닌가?


        if let id = info[“id"] as? NSNumber,

           let userId = info[“userId"] as? NSNumber { } else {

                return

        }


 게다가 나는 id나 userId같은 변수는 필요없다. 안쓰니까 친절하게 워닝까지 내어준다. let을 제거하기로 마음을 먹는다.


        guard info["id"] as? NSNumber != nil && info["userId"] as? NSNumber != nil else {

            return

        }


그렇게 하니 이번에는 조건이 뒤집어진다. 그러니까 “id도 있고 userId도 있으면”이 아니면 return인게다. 이건 말을 마구 꼬으는 느낌이다.

이걸 그냥 if문을 사용하면 아래와 같아진다.


        if info["id"] as? NSNumber == nil || info["userId"] as? NSNumber == nil {

            return

        }


id가 없거나 userId가 없으면 return이다. 훨씬 간결하네.

그럼 우리는 이것을 ObjC에서는 어떻게 표현했는지 보자.


        if (![info objectForKey:@"id"] || ![info objectForKey:@"userId"]) {

            return

        }

        

으응???


그래서 그나마 가장 합리적인 선택... 아래와 같은 방법을 쓰기로 했다.


        guard let _ = scheduleInfo["id"] as? NSNumber, let _ = scheduleInfo["userId"] as? NSNumber else {

            return

        }

Name
Password
Homepage
Secret
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
prev"" #1 next