[swift]挫折しながら覚えるiOS開発その14 細かい部分の調整(UIAlertController等)


前回は、GoogleAnalyticsの組み込みを行いました。

今回はネットワーク未接続時のAlert表示や、TableViewの選択状態解除など、申請までにやっておいたほうがよさそうな細かい調整を行います。

1. アラートを出す(UIAlertController)

ネットワーク未接続時に一覧ページ(キャッシュが切れている場合)や詳細ページにアクセスした場合は、ページを表示できないのでアラートを出すようにしたいです。

そこで、まずはBaseViewControllerにアラート表示を行うメソッドを追加しました。

# BaseViewController.swift

func showNetworkAlert() {
    let alertController = UIAlertController(
        title: "通信に失敗しました",
        message: "電波状況を確認の上、もう一度お試しください。",
        preferredStyle: .Alert
    )

    let defaultAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
    alertController.addAction(defaultAction)

    presentViewController(alertController, animated: true, completion: nil)
}

これでこのメソッドを呼び出せばアラート表示ができるようになりました。

続いて、一覧ページ(MasterTableViewController)のsetupLinksメソッドでエラーが起きた場合はアラート表示を行うようにします。

# MasterTableViewController.swift

func setupLinks(forceReload: Bool = false) {
    let defaults = NSUserDefaults.standardUserDefaults()
    let cachedJson: AnyObject? = defaults.objectForKey("cachedJson")
    let expireUnixtime: NSTimeInterval = defaults.doubleForKey("expireUnixtime")
    let currentUnixtime = NSDate().timeIntervalSince1970
    let cacheClearParam = Int(currentUnixtime/100)

    if (expireUnixtime == 0 || currentUnixtime > expireUnixtime || forceReload == true) {
        Alamofire.request(.GET, "http://qiita-stock.info/api.json?t=\(cacheClearParam)")
            .responseJSON { _, _, data, error in
                // エラーの場合はアラートを表示
                if (error != nil) {
                    self.showNetworkAlert()
                    return
                }

                self.loadTableCells(data!)

                defaults.setObject(data, forKey:"cachedJson")
                defaults.setDouble(currentUnixtime + 60 * 60 * 24, forKey: "expireUnixtime")
                defaults.synchronize()
        }
    } else {
        if let data: AnyObject = cachedJson {
            self.loadTableCells(data)
        }
    }
}

本来はエラーの内容に応じて細かくアラートを出し分けたほうがよいですが、今回は一括で「通信に失敗しました」というアラートを出すようにしています。

最後に、詳細ページ(LinkDetailViewController)のwebView(webView: UIWebView, didFailLoadWithError error: NSError)でもネットワークエラーの場合にアラートを行うようにします。

# LinkDetailViewController.swift

func webView(webView: UIWebView, didFailLoadWithError error: NSError) {
    // エラーコードで出しわけ
    if (error.code == NSURLErrorNotConnectedToInternet) {
        self.showNetworkAlert()
    }

    // インジケータを非表示にする
    UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}

これで通信エラー時にアラートを表示することができました。

また、ステータスバーのインジケータが動き続けないように、ページ読み込みできなかった場合もfalseにするようにしています。

インジケータの詳細に関しては、その8で設定を行っています。

2. 詳細ページの読み込み途中で一覧ページに戻った場合にインジケータを止める

1.の最後でインジケータの設定が出てきましたが、詳細ページの読み込み途中で一覧ページに戻った場合、networkActivityIndicatorVisibleがtrueのままになってしまいます。

そこで、BaseViewControllerのviewWillAppearメソッド内で、インジケータを非表示にするようにしておきます。

こうすることで読み込み途中に一覧ページに戻った場合もインジケータが非表示になります。

# BaseViewController.swift

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    // analytics設定
    // ...

    // インジケータを非表示にする
    UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}

3. TableViewの選択状態を解除する

現状だと、一覧ページからSegueで詳細ページに遷移後、また一覧ページに戻るとセルが選択状態のままになってしまっています。

そこで、セルが選択された際に呼ばれる、tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath)メソッド内でセルの選択を解除するようにします。

# MasterTableViewController.swift

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath:NSIndexPath) {
    // セルの選択状態を解除
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

これで詳細ページから戻ってくるとセルの選択状態が解除されるようになりました。

今回まででひと通りの機能ができたので、次回はいよいよアプリ申請を行ってみます。

参考