3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SwiftLint:non_optional_string_data_conversion の落とし穴

Last updated at Posted at 2024-08-16

APIから取得した data型を .utf8 の String に変換したい場合、SwiftLint ではタイトルの通り、non_optional_string_data_conversionという warning が発生します。

使用技術

  • Swift
  • Xcode
  • SwiftLint

non_optional_string_data_conversion とは?

さて、今回の話の中心となる non_optional_string_data_conversion とはなんでしょうか。
タイトルにもある通り、これは SwiftLint のルールの1つです。

このルールの内容は、

Prefer using UTF-8 encoded strings when converting between Stringand Data
訳:StringData 間の変換時に、UTF-8エンコードされた文字列を優先的に使用する
というものです。

例えば、以下のコードはこのルールには違反しません。

Non Triggering Examples
Data("foo".utf8)
String(decoding: data, as: UTF8.self)

一方で、以下のコードは違反となり、トリガーされます。トリガーされたコードは、Xcode上で warning として表示されます。

Triggering Examples
"foo".data(using: .utf8)
String(data: data, encoding: .utf8)

注目すべきポイント

今回注目したいのは、Data 型をエンコードする際に使う、String(decoding: data, as: UTF8.self) についてです。
このメソッドの便利な点は、String 型を返す点です。

一方、Xcode上で warning が出る String(data: data, encoding: .utf8) は、Optional<String> を返します。

では、両者の違いはなんでしょうか。
String(decoding: data, as: UTF8.self) は、たとえ data がUTF-8として正しくエンコードできない場合でも、String 型として値を返します。
それに対して、String(data: data, encoding: .utf8) は、エンコードに失敗すると nil を返します。

つまり、String(decoding: data, as: UTF8.self) は、デコードに失敗した場合でも文字化けした String 型を返してしまう可能性があるということです。

したがって、このイニシャライザを使用する際は、data が確実に UTF-8 としてエンコード可能であることを確認した上で使用することをお勧めします。
以下は、この問題に関するサンプルコードです。

この問題の落とし穴

上記を踏まえて、今回注意したいのは、non_optional_string_data_conversion がSwiftLint 上では "Enabled by default: Yes"、つまりデフォルトのルールとして設定されている点です。
そのため、.swiftlint.yml ファイルに、このルールを除外する必要があります。

ルールの除外方法

このルールの除外方法は簡単です。
ファイル内で disabled_rules の配下に non_optional_string_data_conversion を追記するだけです。

.swiftlint_yml
disabled_rules:
  - ... 除外したいその他のルール
  - non_optional_string_data_conversion
  - ...

エンコードが確実ではない場合の回避方法

では、UTF-8でエンコード可能であると確実に言えない場合、どのようにしてエンコードしたら良いでしょうか。

1つの解決策として、オプショナルバインディングして、nil の場合は別の文字列を返すのが良いでしょう。
以下は、そのサンプルことです。

if let html = String(data: invalidData, encoding: .utf8) {
  print(html)
} else {
  print("エンコード失敗")
}

最後に

今回紹介した「落とし穴」は、String(decoding: data, as: UTF8.self) を推奨するルールが SwiftLint でデフォルトで有効化されている点にあります。
そのため、必要に応じて .swiftlint.yml に設定を追加する必要があります。
また、エンコードが確実ではない場合、オプショナルバインディングをしてあげる必要があります。

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?