3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

WKWebView のnavigationDelegateのメソッド経由で得られるエラーがローカライズされない

Last updated at Posted at 2020-06-17

概要

WKWebView を使って Web ページを読み込む処理を実装したところ、端末がオフライン状態で通信失敗する等のエラー時に、 WKWebViewnavigationDelegate のメソッド経由で得られるエラーがローカライズされない問題に遭遇しました。

ローカライズされないというのは、より具体的にいうと、アプリを実行している端末の言語設定に関わらず、 Error オブジェクトの localizedDescription 等のローカライズ可能な文字列が常に英語になっているということです。

Xcodeプロジェクトの設定をいろいろと試したり、インターネット上での検索をしたりしているうちに、この問題が iOS 側の問題である可能性が高いことがわかりました。

確認環境

ビルド環境

  • macOS 10.15.5
  • Xcode 11.5 (11E608c)
  • Deployment Target: iOS 13.0

実行環境

  • 機種・OS
    • iPhone 11 Pro Max (iOS 13.5.1)
  • 言語と地域の設定
    • 使用する言語の優先順序: 日本語、English(英語)
    • 地域: 日本

確認方法

Xcodeプロジェクトの多言語対応

実際に WKWebView のエラーを確認をする前に、Xcode プロジェクトの多言語対応をします。今回は、アプリを英語と日本語に対応させます。

下の画像のようにして、Xcode プロジェクトについての設定画面で Info ペインの中の Localizations セクションの + ボタンから Japanese (ja) を選択することにより、日本語対応を追加します。これにより、デフォルトで対応していた英語に加えて、日本語にも対応するようになります。

project_info_localizations.png

WKWebView で Web ページを読み込んだ時のエラー内容を確認する

WKWebView を使って Web ページを読み込むための実装例を以下に示します。コードの中では読み込み対象の URL を https://www.example.com としていますが、この部分は実際に読み込みたいページの URL に置き換えてください。

SampleViewController.swift
import UIKit
import WebKit

class SampleViewController: UIViewController {
    
    @IBOutlet private weak var webView: WKWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        webView.navigationDelegate = self

        let url = URL(string: "https://www.example.com")!
        let request = URLRequest(url: url)
        webView.load(request)
    }
}

extension SampleViewController: WKNavigationDelegate {
    
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        
    }
    
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        print(error)
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print(error)
    }
    
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {

    }
}

アプリを実行する端末がオフライン状態のときに、この SampleViewController に遷移させてみると、 webView(_:didFailProvisionalNavigation:withError:) が呼び出されます。このメソッドの引数に渡される Error オブジェクトは次のようになっていました。

WKWebViewの通信エラー
Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline." UserInfo={NSErrorFailingURLKey=https://www.example.com/, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <747BB86D-7AFF-478E-B62E-E0496E9CBE3A>.<2>, _kCFStreamErrorCodeKey=50, NSLocalizedDescription=The Internet connection appears to be offline., _WKRecoveryAttempterErrorKey=<WKReloadFrameErrorRecoveryAttempter: 0x600001993540>, networkTaskDescription=LocalDataTask <747BB86D-7AFF-478E-B62E-E0496E9CBE3A>.<2>, _kCFStreamErrorDomainKey=1, NSErrorFailingURLStringKey=https://www.example.com/, NSUnderlyingError=0x6000017b7e70 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}}

アプリが日本語に対応していて、端末の言語設定で日本語が優先されているのにもかかわらず、 NSLocalizedDescription の値が The Internet connection appears to be offline. となっています。

比較: URLSession の通信エラーを確認する

WKWebView の通信エラー内の情報はローカライズされませんが、他のエラーについてはどうでしょうか。比較として、 URLSession の通信エラーについても確認してみます。

アプリを実行する端末がオフライン状態のときに次の処理を実行して、出力されるエラー情報を確認します。

URLSessionの通信エラーを確認
let session = URLSession(configuration: .default)
let url = URL(string: "https://www.example.com")!
let task = session.dataTask(with: url) { _, _, error in
    if let error = error {
        print(error)
    }
}
task.resume()

dataTask(with:completionHandler:)completionHandler に渡される Error オブジェクトは次のようになっていました。

URLSessionの通信エラー
Error Domain=NSURLErrorDomain Code=-1009 "インターネット接続がオフラインのようです。" UserInfo={NSUnderlyingError=0x600003d97390 {Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)" UserInfo={_kCFStreamErrorCodeKey=50, _kCFStreamErrorDomainKey=1}}, NSErrorFailingURLStringKey=https://www.example.com/, NSErrorFailingURLKey=https://www.example.com/, _kCFStreamErrorDomainKey=1, _kCFStreamErrorCodeKey=50, NSLocalizedDescription=インターネット接続がオフラインのようです。}

URLSession のエラーでは、NSLocalizedDescription の値が インターネット接続がオフラインのようです。 となっていて、日本語にローカライズされていることがわかります。

iOS 側の問題である可能性

インターネット上で関連情報がないか検索していたところ、次のバグレポートを発見しました。

rdar://22818481: Localized Error Messages missing in WKWebView

多言語対応しているアプリにおいて webView(_:didFailProvisionalNavigation:withError:) から得られるエラーの localizedDescription がローカライズされない(常に英語となる)という、まさに今回問題としている現象が指摘されています。また、このバグレポートのページによると、iOS 8.x, 9, 10においてこの問題が発生していることが報告されています。

もしこれが本当に iOS 側の問題だったのだとすると、現時点での最新バージョンである iOS 13.5.1 においてもまだ解決されていないのかもしれません。しかし、この現象について言及している他のページが見つからなかったので、果たして本当に iOS 側の問題なのか確信を持てずにいます。

今後 iOS のアップデートがあったときには、このエラーのローカライズについての変更があるのかに注目しようと思います。

3
4
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
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?