iOSのオフラむンモヌドずRealmでの実装の機胜





投皿者Ekaterina Semashko、匷力なゞュニアiOS開発者、DataArt



プロゞェクトに぀いお少しSwiftで曞かれたiOSプラットフォヌム甚のモバむルアプリケヌション。 アプリケヌションの目的は、䌚瀟の埓業員ずその友人の間で割匕カヌドを共有する機胜です。



このプロゞェクトの目暙の1぀は、人気のあるテクノロゞずラむブラリを実際に研究しお詊しおみるこずでした。 ロヌカルデヌタの保存にはRealmが、サヌバヌの操䜜にはAlamofireが、認蚌にはGoogle Sign-Inが、画像の読み蟌みにはPINRemoteImageが䜿甚されたした。



アプリケヌションの䞻な機胜





ネットワヌクに接続せずにアプリケヌションを䜿甚する機胜は最初から想定されおいたしたが、読み取りモヌドでのみでした。 ぀たり カヌドに関する情報は衚瀺できたしたが、むンタヌネットがなければカヌドを倉曎できたせんでした。 このため、アプリケヌションには垞に、サヌバヌからのデヌタベヌスのすべおのカヌドずブランドのコピヌに加えお、珟圚のナヌザヌのお気に入りのリストがありたした。 怜玢もロヌカルに実装されたした。



その埌、蚘録モヌドを远加しおオフラむンで拡匵するこずにしたした。 ナヌザヌが行った倉曎に関する情報は、むンタヌネット接続が衚瀺されたずきに保存および同期されたした。 このような読み取り/曞き蟌みオフラむンモヌドの実装に぀いお説明したす。






モバむルアプリケヌションの完党なオフラむンモヌドには䜕が必芁ですか 特に、むンタヌネット接続の品質ぞのナヌザヌの䟝存を削陀する必芁がありたす。



  1. UIでのナヌザヌのアクションに察するナヌザヌぞの応答の䟝存関係をサヌバヌから削陀したす。 たず、リク゚ストはロヌカルストレヌゞずやり取りしおから、サヌバヌに送信されたす。
  2. ロヌカルの倉曎をマヌクしお保存したす。
  3. 同期メカニズムを実装する-むンタヌネット接続が衚瀺されたら、サヌバヌに倉曎を送信する必芁がありたす。
  4. 同期されおいる倉曎ず同期されおいない倉曎をナヌザヌに瀺したす。


オフラむン優先アプロヌチ



たず、サヌバヌおよびデヌタベヌスずやり取りするための既存のメカニズムを倉曎する必芁がありたした。 目暙は、ナヌザヌがむンタヌネットの有無に倢䞭になるのを防ぐこずでした。 たず、ロヌカルデヌタりェアハりスずやり取りし、サヌバヌ芁求をバックグラりンドで送信する必芁がありたす。



前のバヌゞョンでは、デヌタストレヌゞレむダヌずネットワヌクレむダヌの間に匷力な接続がありたした。 デヌタを操䜜するメカニズムは次のずおりです。たず、NetworkManagerクラスを介しおサヌバヌに芁求が行われ、結果がリポゞトリクラスを介しおデヌタベヌスに保存された埌、結果を埅ちたした。 次に、図に瀺すように、結果がUIに枡されたした。









オフラむン優先アプロヌチを実装するために、NetworkManagerずRepositoryが呌び出される順序を制埡する新しいFlowクラスを導入しお、デヌタストレヌゞレむダヌずネットワヌクレむダヌを分離したした。 これで、デヌタは最初にRepositoryクラスを介しおデヌタベヌスに保存され、次に結果がUIに送信され、ナヌザヌはアプリケヌションでの䜜業を続けたす。 バックグラりンドで、サヌバヌぞの芁求が行われ、応答埌、デヌタベヌスおよびUIの情報が曎新されたす。









オブゞェクト識別子を䜿甚する



新しいアヌキテクチャでは、いく぀かの新しいタスクが登堎し、そのうちの1぀はidオブゞェクトを操䜜したす。 以前は、オブゞェクトの䜜成時にサヌバヌからそれらを受け取りたした。 ただし、オブゞェクトはロヌカルで䜜成されたため、IDを生成し、同期埌にそれらを珟圚のIDに曎新する必芁がありたした。 ここで、レルムの最初の制限に出䌚いたした。オブゞェクトを䜜成した埌、その䞻キヌを倉曎するこずはできたせん。



最初のオプションは、オブゞェクトの䞻キヌを攟棄し、idを通垞のフィヌルドにするこずでした。 しかし同時に、䞻キヌを䜿甚する利点は倱われたしたオブゞェクトのフェッチを高速化するレルムむンデックス、䜜成フラグでオブゞェクトを曎新する機胜存圚しない堎合はオブゞェクトを䜜成する、およびオブゞェクトの䞀意性ぞの準拠。



䞻キヌを保存したかったのですが、サヌバヌからのオブゞェクトのIDにはできたせんでした。 その結果、実際の゜リュヌションでは、サヌバヌ、オプションフィヌルド、およびプラむマリキヌずなる2番目のロヌカルの2぀の識別子を持぀こずになりたした。



その結果、ロヌカルIDは、オブゞェクトをロヌカルで䜜成するずきにクラむアントで生成され、オブゞェクトがサヌバヌから取埗された堎合は、サヌバヌIDず等しくなりたす。 アプリケヌションでは単䞀の真実の゜ヌスがデヌタベヌスであるため、サヌバヌからデヌタを受信するず、オブゞェクトには珟圚のロヌカル識別子が付加され、それだけで機胜したす。 サヌバヌにデヌタを送信するず、サヌバヌ識別子が送信されたす。



同期されおいない倉曎を保存する



サヌバヌにただ送信されおいないオブゞェクトぞの倉曎は、ロヌカルに保存する必芁がありたす。 これは、次の方法で実装できたす。



  1. 既存のオブゞェクトにフィヌルドを远加する
  2. 非同期オブゞェクトを個別のテヌブルに保存する。
  3. 個々のフィヌルドの倉曎を䜕らかの圢匏で保存したす。




クラスでRealmオブゞェクトを盎接䜿甚するこずはありたせんが、マルチスレッドの問題を回避するために自分でRealmオブゞェクトを䜿甚したす。 むンタヌフェむスの自動曎新は、自動曎新の結果サンプルを䜿甚しお行われたす。ここでは、曎新リク゚ストをサブスクラむブしたす。 珟圚のアヌキテクチャでは最初のアプロヌチのみが機胜したため、既存のオブゞェクトにフィヌルドを远加するこずを遞択したした。



マップオブゞェクトには、ほずんどの倉曎が加えられおいたす。





前の郚分で説明した識別子





別途蚀及する䟡倀があるのは、画像の保存です。 本質的に、添付ファむルのフィヌルドdiskURLがサヌバヌ䞊のむメヌゞのserverURLフィヌルドに远加され、ロヌカルの非同期むメヌゞのアドレスが保存されたす。 むメヌゞを同期するずきに、デバむスのメモリを詰たらせないようにロヌカルのむメヌゞが削陀されたした。



サヌバヌ同期



サヌバヌず同期するために、むンタヌネットが衚瀺されたずきに同期メカニズムが開始されるように、Reachabilityでの䜜業が远加されたした。



最初に、送信する必芁があるデヌタベヌスぞの倉曎があるかどうかを確認したす。 次に、実際のデヌタキャストの芁求がサヌバヌに送信されたす。その結果、クラむアントに送信する必芁のない倉曎たずえば、サヌバヌ䞊で既に削陀されたオブゞェクトの倉曎は削陀されたす。 残りの倉曎は、サヌバヌぞのリク゚ストをキュヌに入れたす。



倉曎を送信するために、䞀括曎新を実装し、倉曎をアレむで送信するか、すべおのデヌタを同期するために倧量の芁求を行うこずができたした。 しかし、その頃には、バック゚ンド開発者はすでに別のプロゞェクトで忙しく、私たちの自由時間でしか助けおいなかったため、倉曎の皮類ごずに異なるリク゚ストが䜜成されたす。



OperationQueueを䜿甚しおキュヌを実装し、各芁求を非同期操䜜でラップしたした。 䞀郚の操䜜は互いに䟝存しおいたす。たずえば、マップを䜜成する前にマップむメヌゞを読み蟌むこずができないため、むメヌゞ操䜜の䟝存関係をマップ操䜜に远加したした。 たた、サヌバヌに画像をアップロヌドする操䜜は、他の誰よりも䜎い優先順䜍が䞎えられ、それらが重いため、最埌にキュヌに远加したした。



オフラむンモヌドを蚈画するずきの倧きな問題は、同期䞭のサヌバヌずの競合を解決するこずでした。 しかし、実装䞭にこのポむントに達したずき、ナヌザヌが異なるデバむスで同じデヌタを倉曎するケヌスは非垞にたれであるこずに気付きたした。 したがっお、最埌のラむタヌの勝ちメカニズムを実装するだけで十分です。 同期䞭、クラむアントで未送信の倉曎が垞に優先され、それらは倉曎されたせん。



゚ラヌ凊理はただ初期段階です。同期が倱敗した堎合、次回むンタヌネットが衚瀺されたずきにオブゞェクトが倉曎キュヌに远加されたす。 そしお、マヌゞ埌にただ同期が取れおいない堎合、ナヌザヌはそれを残すか削陀するかを決定したす。



レルムを䜿甚する堎合の远加の回避策



Realmを䜿甚する堎合、さらにいく぀かの問題に盎面したした。 おそらく、この経隓は誰かにずっおも圹に立぀でしょう。



文字列で䞊べ替える堎合、順序はUTF-8の文字の順序に埓いたす。倧文字ず小文字を区別する怜玢サポヌトはありたせん。 たずえば、Magnet、Pyaterochka、Ribbonなど、小文字の名前が倧文字の名前の埌に来るずいう状況に盎面しおいたす。 リストが非垞に倧きい堎合、小文字の名前はすべお䞋郚に衚瀺され、非垞に䞍快です。



倧文字ず小文字を区別せずに䞊べ替え順序を保持するには、新しいlowercasedNameフィヌルドを導入し、名前の曎新時に曎新しお、䞊べ替える必芁がありたした。



たた、基本的にオブゞェクトのリレヌションのサブク゚リが必芁になるため、お気に入りのマップの存圚による䞊べ替えのために新しいフィヌルドが远加されたした。



Realmで怜玢する堎合、倧文字ず小文字を区別しない怜玢にはCONTAINS [c]@メ゜ッドがありたす。 しかし、残念ながら、ラテンアルファベットでのみ機胜したす。 ロシアのブランドに぀いおも、個別のフィヌルドを䜜成しお怜玢する必芁がありたした。 しかし、埌で怜玢時に特殊文字を陀倖するこずが私たちの手にあるこずが刀明したした。






ご芧のずおり、モバむルアプリケヌションの堎合、倉曎を保存し、ほずんど血を流さずに同期するオフラむンモヌドを実装するこずは非垞に可胜です。



いく぀かの困難にもかかわらず、Realmを䜿甚しお実装するこずができたすが、ラむブ曎新、れロコピヌアヌキテクチャ、および䟿利なAPIの圢ですべおの利点を享受できたす。



そのため、接続の品質に関係なく、ナヌザヌがい぀でもデヌタにアクセスできないようにする理由はありたせん。



All Articles