Original Link
by Nathan Chan
translated Korean by pilgwon
Swiftの String Optionalはちょっと変なところがあります String?
typeは “不可能”な値を二つ持っています: nil
と ""
. これはバグと予想外の動作を処理しにくくなる時があります。
例えば UITextField
の text
属性の String?
です。テキストフィールドが空の時に適切にユーザー知らせられるし、後で利用できるようにテキストStringのラッピングを解除する間、次のコードを作成します:
if let title = textField.text else {
if title.isEmpty {
// alert: テキストフィールドが空いてます!
}
// タイトルStringが現在ラッピングが外れており、空いてもなく、利用可能な準備ができました
}
textField.text?.isEmpty ?? true
のように guard let
かoptional chainingを利用することもいいと思います。どちらにしても実装方法はやりにくく、様々なネストした条件文を使わないといけません。
その時、Swift Extensionに救われるでしょ!
Extensionは既に存在するclass, structure, enumeration, またはprotocol typeに新たなfunctionの追加が可能になります。 where
を利用することで、Extensionを特定タイプまたは適切なタイプに制限することも可能です。
だとするとどうやって String?
に対して空 Stringの値を処理するところに適用するのでしょうか? これからExtensionの中で nilIfEmpty
属性を定義してoptional 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が現在ラッピングから解除されていて、空いてもなく、利用する準備ができました
どうでしょうか?
このExtensionはユーザーが map
か flatMap
という高次元のFunctionを実装する時に簡単に利用できます:
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"]
最後に…
もし空のOptional Stringを使うための違うアクセス方法がありましたらOriginal Link
に書き込んでいただくかTwitter @nathanwchanでメンションをお願い致します。