본문 링크 (Original Link)

스위프트에서 빈 옵셔널 String 다루기

2017.09.09

#

by Nathan Chan, translated by pilgwon

스위프트의 String 옵셔널은 약간 이상합니다. String? 타입은 “불가능”한 값이 두 가지 있습니다: nil"". 이것은 버그와 예상치 못 한 동작을 처리하고 익히기가 번거롭게 만들 수 있습니다.

예를 들어 UITextFieldtext속성이 String?입니다. 우리는 텍스트 필드가 비었있을 때 적절하게 유저에게 알림을 줄 수 있고, 나중에 사용할 수 있도록 텍스트 String의 래핑을 해제하는 동안 다음 코드를 작성할 수 있습니다:

if let title = textField.text else {
    if title.isEmpty {
        // 알림: 텍스트필드가 비어있습니다!
    }
    // 타이틀 String이 지금 래핑이 풀려있고, 비어있지도 않고, 사용할 준비가 되었습니다
}

textField.text?.isEmpty ?? true와 같이 guard let이나 옵셔널 체이닝의 조합을 사용하는 것도 좋습니다. 어느 쪽이든, 구현 방법은 정신 사납고, 당신은 여러가지 그리고/또는 네스티드 조건문들을 다뤄야 할 것입니다.

스위프트 익스텐션이 구해줄 것입니다!

익스텐션은 이미 존재하는 클래스, 스트럭쳐, 열거형 또는 프로토콜 타입에 새로운 함수를 추가할 수 있게 해줍니다. where과 함께라면, 당신은 익스텐션을 특정 타입 또는 적합한 타입으로 제한 할 수 있습니다.

그렇다면 이것을 어떻게 String?에 대한 빈 String 값을 처리하는 데에 적용할 수 있을까요? 이제 익스텐션 안에서 nilIfEmpty 속성을 정의해서 옵셔널 String을 제한해 봅시다. 이것은 빈 String을 nil으로 바꾸거나 String?의 원래 값을 반환합니다.

extension Optional where Wrapped == String {
    var nilIfEmpty: String? {
        guard let strongSelf = self else {
            return nil
        }
        return strongSelf.isEmpty ? nil : strongSelf
    }
}

이제는 위의 코드를 정리하여 텍스트 필드가 비어있는 경우를 감지하여 사용자에게 경고하고 텍스트 String의 래핑을 해제 할 수 있습니다:

guard let title = textField.text.nilIfEmpty else {
    // 알림: 텍스트필드가 비어있습니다!
    return
}
// 타이틀 String이 지금 래핑이 풀려있고, 비어있지도 않고, 사용할 준비가 되었습니다

이쁘지 않나요?

이 익스텐션은 유저가 map이나 flatMap과 같은 고차원의 함수를 쓸 때 간단하게 쓸 수 있습니다:

let stuff = ["nate", "", nil, "loves", nil, "swift", ""]

let a = stuff.map { $0.nilIfEmpty }
print(a) // [Optional("nate"), nil, nil, Optional("loves"), nil, Optional("swift"), nil]

let b = stuff.flatMap { $0.nilIfEmpty }
print(b) // ["nate", "loves", "swift"]

끝나기 전에…

혹시 빈 옵셔널 String을 다루기 위한 다른 접근 방법을 아시나요? 저는 매우 듣고 싶습니다. 댓글을 달아주시거나 저를 트위터 @nathanwchan에서 찾아주세요.