Upload
satoshi-asano
View
4.074
Download
0
Embed Size (px)
Citation preview
iPhoneアプリの通信エラー処理id:ninjinkun / @ninjinkun
はじめに
• 年末にiOS Advent Calendarに参加しました
• 25日まで毎日日替わりで記事を書く
• http://atnd.org/events/22792
• http://ninjinkun.hatenablog.com/entry/2011/12/23/224918
はじめに
• 通信エラー処理の設計• ケーススタディ• 実装
通信は失敗する通信エラー処理の設計
• 内蔵IO→だいたい成功するものと思って設計してる
• 容量オーバー、ファイル名重複etc…
• 通信IO→失敗する可能性を考慮して設計する
• iPhoneはモバイルデバイス
• 通信は高い確率で失敗する• 辺境、トンネル、etc…
• 異常系ではなく正常系の一部として捉える
理想的なエラー処理通信エラー処理の設計
• 偉い人曰く…
エラーメッセージボックスは、プログラムがバカなので処理を停止するといっているようなものであり、避けなければならない
エラーメッセージには、究極のアイロニーがある。ユーザーがエラーを犯すのを防いではくれないのだ。
理想的なエラー処理通信エラー処理の設計
• 偉い人曰く…
エラーダイアログは、必ず礼儀正しく、わかりやすく問題点を示し、役に立つものでなければならない。
ユーザーに必要な情報を提供した上で、必ず一つは解決策を提示せよ
エラー処理プラン通信エラー処理の設計
松 ユーザーの操作をインタラプトせずにレジュームする
竹 ユーザーの操作をインタラプトしてレジュームする
梅 エラーメッセージを表示するだけ
ケーススタディ
• Path
ケーススタディ
• 失敗してもメッセージボックスに入る• アプリが終了してもバックグラウンドで勝手にレジューム
• OS組み込みだからできること
• ユーザーがエラーを意識しなくても良くなっている• 松プラン
ケーススタディ
• アップロードキューが実装されている• 失敗するとレジュームできる• 複数の写真をレジューム可能• ユーザーが自力でレジュームする作業は必要• 竹プラン
ケーススタディ
• 通信が失敗しても何も言わない• ひどい
Path
ケーススタディ
• 失敗しても成功したように見せている• 後から通信が繋がれば再度送信(自動)• 単なるPOST / GETではなくデータを同期している(?)
• ユーザーにエラーを意識させない• 松プラン• その反面送信が完了していないことには気づかない…
実装
• エラーの表示• UIAlertView
• レジューム処理• UIViewControllerの復元
• キューhttps://github.com/ninjinkun/AlertResume
エラーの表示実装
• UIAlertView
• NSErrorと協調させると便利
• NSAlertViewにはNSErrorを引数に取るコンストラクタが存在していた
• …ですよね?
エラーの表示実装
• NSErrorには表示用のパラメータが揃っている
• 全てuserInfoのデータへのショートカット
• localizedDiscription
• localizedFailureReason
• localizedRecoverySuggestion
• localizedRecoveryOptions
エラーの表示実装
NSArray *buttons = [NSArray arrayWithObjects:@"キャンセル", @"再試行する", nil]; NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys: @"ネットワークエラーが発生しました", NSLocalizedDescriptionKey, @”ネットワークに接続できません”, NSLocalizedFailureReasonErrorKey, @"接続を確認して…", NSLocalizedRecoverySuggestionErrorKey, buttons, NSLocalizedRecoveryOptionsErrorKey, nil]; NSError*error = [NSError errorWithDomain:@"com.hoge.fuga" code:100 userInfo:userInfo];
エラーの表示実装
• UIAlertViewに食わせて表示する@implementation UIAlertView (NSErrorAddition)
-(id)initWithError:(NSError *)error { self = [super init]; if (self) { self.title = [error localizedDescription]; self.message = [[NSArray arrayWithObjects:[error localizedFailureReason], [error localizedRecoverySuggestion], nil] componentsJoinedByString:@"\n"]; NSArray* optionTitles = [error localizedRecoveryOptions]; for (NSString *title in optionTitles) { [self addButtonWithTitle:title]; } } return self;}
@end
レジューム処理実装
• ViewControllerごとレジューム
• POSTの画面をもう一度開きます
• レジューム操作が直感的• 予期しないところでViewControllerが開いてしまう
レジューム処理実装
• キューでレジューム• リクエストをキューに保存しておく• 成功したらキューからは削除• 失敗したらキューのビューから再試行操作を行う• キューをプレビューするビューを作る必要有り
まとめ
• 通信エラー処理の方法について考察した• 通信エラーは正常系の一部として考えよう• 様々なアプリのケースを観察した• Pathはがんばっている
• 通信エラー処理を実装してみた• UIAlertView
• レジューム処理2種類
• 大変だけどがんばりましょう
最近出たこの本が結構良いと思ってますおまけ
• iOSプログラミング 第2版
• アーロン・ヒレガス, ジョー・コンウェイ