web-dev-qa-db-ja.com

サーバーからのデータをキャッシュするクライアント(iOS)のコアデータ

バックエンドと通信する多くのiOSアプリを作成しました。ほぼ毎回、HTTPキャッシュを使用してクエリをキャッシュし、応答データ(JSON)をObjective-Cオブジェクトに解析しました。この新しいプロジェクトでは、Core Dataのアプローチが意味をなすかどうか疑問に思っています。

私が考えたのは次のとおりです。

IOSクライアントはサーバーにリクエストを行い、JSONからCoreDataモデルへのオブジェクトを解析します。

サーバーを直接取得する代わりに、新しいオブジェクトが必要になるたびに、CoreDataを解析して、その要求を既に行ったかどうかを確認します。そのオブジェクトが存在し、有効期限が切れていない場合、取得したオブジェクトを使用します。

ただし、オブジェクトが存在しないか、有効期限が切れている場合(ここにキャッシュロジックが適用されます)、サーバーからオブジェクトを取得し、それに応じてCoreDataを更新します。

このようなアーキテクチャを使用すると、次のことが可能になると思います。1.バックエンドへの不要なクエリを回避します

ここでSO Gods:

  1. この種の場合、バックエンドロジックをもう一度コーディングする必要があることは知っています(Server + CoreData)が、これはやり過ぎですか?
  2. 見積り不足の制限はありますか?
  3. 他のアイデアは?
57

まず、登録済みのiOS開発者であれば、WWDC 2010セッションにアクセスできるはずです。これらのセッションの1つでは、「セッション117、サーバー駆動型のユーザーエクスペリエンスの構築」について説明しました。 iTunesで検索 できるはずです。

REST/JSON/Core Dataのスマートな組み合わせは魅力のように機能し、コードを再利用する場合は時間を大幅に節約できますが、HTTPに関する知識(およびCore Dataに関する知識が必要) 、アプリのパフォーマンスと安全性を高めたい場合)。

そのため、重要なのはRESTおよびCore Dataを理解することです。

  • [〜#〜] rest [〜#〜] の理解は、HTTPメソッド(GET、POST、PUT、DELETE、... HEAD?)および応答コード(2xx、3xx、4xx、5xxの理解を意味します)およびヘッダー(Last-Modified、If-Modified-Since、Etag、...)

  • コアデータを理解するということは、モデルの設計方法、関係の設定、時間のかかる操作(削除、挿入、更新)の処理、およびUIが応答し続けるようにバックグラウンドで物事を発生させる方法を知ることを意味します。もちろん、sqliteでローカルにクエリを実行する方法(たとえば、idをプリフェッチするため、サーバー側で同等のものを取得したら、新しいオブジェクトを作成する代わりにオブジェクトを更新できます)。

言及したタスクに再利用可能なAPIを実装する予定がある場合は、RESTとCore Dataを理解する必要があります。これはおそらく最も多くのコーディングを行うためです。(既存のAPI-- ASIHttpRequest ネットワーク層(またはその他)と、適切なJSONライブラリ(例 [〜#〜] sbjson [〜#〜] )は解析を行います。

このようなAPIをシンプルにするための鍵は、サーバーがRESTfulサービスを提供し、エンティティが必要な属性(dateCreated、dateLastModifiedなど)を保持して、リクエストを作成できるようにすることです(ASIHttpRequestを使用して、GET、PUT、 POST、DELETE)および適切なHttp-Headersを追加します。例えば条件付きGETの場合:If-Modified-Since。

既にCore Dataに慣れており、JSONを処理でき、HTTP要求を簡単に実行して応答を処理できる場合(ここでも、ASIHttpRequestが非常に役立ちますが、他にもあります。または、下位レベルApple NS-Classes and do it your))、必要なのは、リクエストに正しいHTTPヘッダーを設定し、Http-Response-Codesを適切に処理することです(サーバーがRESTに対応していると仮定)。

サーバー側の同等のものからCore-Dataエンティティを再更新することを回避することが主な目標である場合は、エンティティに「最終変更」属性があることを確認し、サーバーに条件付きGETを実行します( 「If-Modified-Since」エンティティへのHttp-Header「last-modified」日付。リソースが変更されなかった場合、サーバーはStatus-Code 304(Not-Modified)で応答します(サーバーがRESTフルであると仮定)変更された場合、サーバーは「Last-Modified」Http-Headerを最後の変更が行われた日付に設定し、Status-Code 200で応答し、リソースを本体で配信します(例:JSON形式)。

ですから、いつものように、あなたの質問に対する答えは、いつものようにおそらく「それは依存します」です。それは主に、再利用可能なdo-it-allコアデータ/レストレイヤーに何を入れたいかによって異なります。

数字を教えてください:希望する場所に私のものを置くのに6か月かかりました(空き時間で、週に3〜10時間のペースで)。正直なところ、リファクタリング、名前の変更、それを許可するにはまだ特別なユースケース(リクエストのキャンセル、ロールバックなど)を処理し、きめ細かいコールバック(到達可能性、ネットワーク層、シリアル化、コアデータの保存など)を提供します。しかし、それは非常にクリーンで精巧で最適化されており、私の雇用主の一般的なニーズ(複数のiOSアプリを備えた広告のオンライン市場)にうまくいけばうまくいきます。その時間には、APIの学習、テスト、最適化、デバッグ、および絶えずAPIの変更が含まれていました(最初に機能を追加し、次に改善し、次に根本的に単純化し、再度デバッグします)。

市場投入までの時間が優先される場合は、シンプルで実用的なアプローチを使用することをお勧めします:再利用性を気にせず、学習を念頭に置き、次のプロジェクトでリファクタリングし、コードをあちこちで再利用および修正します。最終的に、すべての経験の合計が、APIがどのように機能し、何を提供するかという明確なビジョンに具体化されます。まだお持ちでない場合は、プロジェクト予算の一部となるように努力し、安定したサードパーティAPIをできるだけ再利用してみてください。

長い応答に申し訳ありませんが、一般的なAPIやフレームワークを構築するようなものに踏み込んでいると感じました。それらには時間、知識、ハウスキーピング、長期的なコミットメントが必要であり、ほとんどの場合、時間を無駄にすることはありません。

特定のキャッシュシナリオを処理してアプリのオフライン使用を許可し、ネットワークトラフィックを最小限に抑えたい場合は、もちろんこれらの機能を実装するだけです。リクエストにif-modified-sinceヘッダーを設定し、last-modifiedヘッダーまたはetagsを検査し、その情報を永続エンティティに永続的に保持して、後のリクエストでこの情報を再送信できるようにします。もちろん、同じHTTPヘッダーを使用して、イメージなどのリソースを(永続的に)ローカルにキャッシュすることもお勧めします。

サーバー側のサービスを(RESTフルな方法で)変更する余裕がある場合は、それを適切に実装すれば問題ありません(経験から、ネットワーク/解析コードの3/4を節約できます)サービスが適切に動作する場合のiOS側(適切なHTTPステータスコードを返し、nilのチェック、文字列からの数値変換、日付を回避し、暗黙的な文字列の代わりにlookup-idを提供するなど)。

そんな贅沢がなければ、そのサービスは少なくともRESTに対応している(これは非常に役立ちます)か、クライアント側の問題を修正する必要があります(多くの場合、苦痛です)。

93
codeclash

私は私のプロジェクトのサーバーキャッシュの側面をリファクタリングするにはプロジェクトから離れすぎているので試すことができなかった解決策がありますが、それはまだ答えを探している人々にとって有用でなければなりません:

http://restkit.org/

それは私がやったことを正確に行いますが、私がやったことよりもはるかに抽象化されています。そこには非常に洞察に満ちたものがあります。私はそれが誰かを助けることを願っています!

それは有効なアプローチだと思います。私はこれを何回もしました。トリッキーな部分は、同期を処理する必要がある場合です。クライアントとサーバーの両方が同時に物事を変更できる場合。ほとんどの場合、これにはアプリ固有のマージロジックが必要です。

5
Chris Eidhof