2011-02-02 9 views
54

He escrito muchas aplicaciones iOS que se comunicaban con el servidor. Casi siempre, utilicé el caché de HTTP para almacenar en caché las consultas y analizar los datos de respuesta (JSON) en objetos Object-C. Para este nuevo proyecto, me pregunto si un enfoque de Core Data tendría sentido.Core Data en el cliente (iOS) para almacenar datos en caché desde un servidor Estrategia

Aquí es lo que pensaba:

El cliente iOS hace la solicitud al servidor y analizar los objetos de JSON para modelos CoreData.

Cada vez que necesito un objeto nuevo, en lugar de buscar el servidor directamente, analizo CoreData para ver si ya hice esa solicitud. Si ese objeto existe y no ha expirado, uso el objeto recuperado.

Sin embargo, si el objeto no existe o ha expirado (se aplicaría aquí alguna lógica de almacenamiento en caché), buscaría el objeto desde el servidor y actualizaría CoreData en consecuencia.

creo que tener una arquitectura de este tipo podría ayudar con las siguientes: 1. Evitar consultas innecesarias al backend 2. Permitir un soporte completo para navegar sin conexión (Usted todavía puede hacer consultas relacionales con el RDBMS de DataCore)

ahora aquí está mi pregunta a SO dioses:

  1. sé que esto requiere un poco de codificar la lógica de fondo por segunda vez (servidor + CoreData) pero esto es una exageración?
  2. ¿Alguna limitación que tenga menos de la estimada?
  3. ¿Alguna otra idea?

Respuesta

90

Antes que nada, si eres un desarrollador de iOS registrado, deberías tener acceso a las sesiones de la WWDC 2010. Una de esas sesiones cubrió un poco de lo que está hablando: "Sesión 117, Creación de una experiencia de usuario basada en el servidor". Debería poder find it on iTunes.

Una combinación inteligente de REST/JSON/Core datos funciona como un encanto y es un gran ahorro de tiempo si va a volver a utilizar su código, sino que requerirá el conocimiento sobre HTTP (y el conocimiento sobre la base de datos, si desea que su aplicaciones para un buen rendimiento y seguridad).

Por lo tanto, la clave es comprender REST y Core Data.

  • Comprender REST significa Métodos entendimiento HTTP (GET, POST, PUT, DELETE, ... CABEZA?) Y la respuesta-Codes (2xx, 3xx, 4xx, 5xx) y soportes de conexión (Last-Modified, If- Modificado-Since, Etag, ...)

  • La comprensión de los datos básicos significa saber cómo diseñar su modelo, establecer relaciones, manejar las operaciones que requieren mucho tiempo (elimina, inserta, actualizaciones) y cómo hacer que las cosas sucedan en el fondo para que su UI se mantenga receptiva. Y, por supuesto, cómo consultar localmente en sqlite (por ejemplo, para la obtención previa de identificadores para que pueda actualizar objetos en lugar de crear nuevos una vez que obtenga los equivalentes del lado del servidor).

Si va a implementar un API reutilizable para las tareas que usted ha mencionado, usted debe asegurarse de que comprende REST y de Datos Básicos, porque ahí es donde es probable que hacer el mayor codificación. (API existente - ASIHttpRequest para la capa de red (o cualquier otra) y cualquier buena lib JSON (por ejemplo, SBJSON) para el análisis hará el trabajo.

La clave para hacer que una API simple sea simple es hacer que su servidor proporcione un Servicio RESTful, y sus Entidades que tengan los atributos requeridos (dateCreated, dateLastModified, etc.) para que pueda crear Solicitudes (fácilmente con ASIHttpRequest, ya sea GET, PUT, POST, DELETE) y agrega los Http-Headers apropiados, por ej. para un GET condicional: If-Modified-Since.

Si ya se siente cómodo con Core Data y puede manejar JSON y puede hacer HTTP Request y manejar respuestas (de nuevo, ASIHttpRequest ayuda mucho aquí, pero hay otros, o puede apegarse al nivel inferior de Apple NS -Clases y hágalo usted mismo), entonces todo lo que necesita es establecer los Encabezados HTTP correctos para sus Solicitudes, y manejar los Códigos Http-Respuesta adecuadamente (suponiendo que su Servidor es REST-ful).

Si su objetivo principal es evitar volver a actualizar una entidad Core-Data desde un servidor equivalente, simplemente asegúrese de tener un atributo "last-modified" en su entidad, y realice un GET condicional a la server (estableciendo el Http-Header "If-Modified-Since" a la fecha de "última modificación" de sus entidades. El servidor responderá con el código de estado 304 (no modificado) si ese recurso no cambió (suponiendo que el servidor esté REST-ful). Si cambia, el servidor configurará el Http-Header "Last-Modified" a la fecha en que se realizó el último cambio, responderá con Status-Code 200 y entregará el recurso en el cuerpo (por ejemplo, en JSON formato).

Por lo tanto, como siempre, la respuesta es que su pregunta es como siempre, probablemente 'depende'. En su mayoría depende de lo que usted li ke poner su capa reutilizable de datos centrales/descanso.

A decir números: Me tomó 6 meses (en mi tiempo libre, a un ritmo de 3-10 horas por semana) a la mía en la que quería que fuera, y la verdad es que todavía estoy refactorización, el cambio de nombre , para permitirle manejar casos de uso especiales (cancelación de solicitudes, retrotraer, etc.) y proporcionar call-backs refinados (accesibilidad, capa de red, serialización, almacenamiento de datos centrales ...). Pero es bastante limpio, elaborado y optimizado y, con suerte, se adapta a las necesidades generales de mi empleador (un mercado en línea para los clasificados con múltiples aplicaciones de iOS). Ese tiempo incluía hacer aprendizaje, probar, optimizar, depurar y cambiar constantemente mi API (Primera funcionalidad de adición, luego mejorarla, luego simplificarla radicalmente y depurarla de nuevo).

Si su prioridad es el tiempo de lanzamiento al mercado, será mejor que tenga un enfoque simple y pragmático: no olvide reutilizar, solo tenga en cuenta las conclusiones y refactorice el siguiente proyecto, reutilice y corrija código aquí y allá . Al final, la suma de todas las experiencias podría materializarse en una visión clara de CÓMO funciona su API y lo que proporciona. Si todavía no has llegado, trata de hacer que forme parte del presupuesto del proyecto, y trata de reutilizar la mayor cantidad posible de API 3'rd-Party estables.

Disculpa la respuesta larga, sentí que estabas metiéndote en algo así como construir una API genérica o incluso un framework. Esas cosas toman tiempo, conocimiento, limpieza y compromiso a largo plazo, y la mayoría de las veces, son una pérdida de tiempo, porque nunca las terminas.

Si solo desea manejar situaciones de almacenamiento en caché específicas para permitir el uso sin conexión de su aplicación y minimizar el tráfico de red, entonces puede, por supuesto, implementar esas características. Simplemente configure los encabezados if-modified-since en su solicitud, inspeccione los encabezados o etags modificados por última vez y mantenga esa información persistente en sus entidades persistentes para que pueda volver a enviar esta información en las solicitudes posteriores. Por supuesto, también recomendaría el almacenamiento en caché (de forma persistente) de recursos, como imágenes localmente, utilizando los mismos encabezados HTTP.

Si tiene el lujo de modificar (de manera REST-ful) el servicio del lado del servidor, entonces está bien, siempre que lo implemente bien (por experiencia, puede ahorrar tanto como 3/4 de código de red/análisis iOS en el lado si el servicio se comporta bien (devuelve los códigos de estado HTTP adecuados, evita las comprobaciones nulas, las transformaciones numéricas de cadenas, fechas, proporciona ID de búsqueda en lugar de cadenas implícitas, etc.).

Si usted no tiene ese lujo, entonces o bien ese servicio es al menos REST-ful (lo que ayuda mucho), o tendrá que arreglar las cosas del lado del cliente (que es una molestia, a menudo).

+1

Gracias por referirse a la sesión WWDC, la estoy descargando ahora mismo. Ya sé cómo manejar el flujo de una aplicación Rest-ful. Lo que estaba preguntando era si era demasiado exagerado para emprender tal esfuerzo o no. A partir de su respuesta, no puedo decir si defiende una arquitectura así o si la respalda porque ya ha hecho una aplicación usando esta arquitectura específica. ¿Te importa aclarar? –

+0

Como siempre, la respuesta es probablemente 'depende'. – codeclash

+0

Editaré mi respuesta, el cuadro de comentarios no permite tantos caracteres :-) – codeclash

5

There es una solución por ahí que no pude probar porque yo también soy ahora en mi proyecto de refactorizar el aspecto de almacenamiento en caché del servidor de mi aplicación, pero debe ser útil para la gente por ahí que todavía están en busca de una respuesta:

http://restkit.org/

Hace exactamente lo que hice, pero es mucho más abstracta eso que hice Cosas muy perspicaces allí. ¡Espero que ayude a alguien!

+5

Para el registro: hay otra API nueva en github: https: //github.com/gowalla/AFNetworking. No proporciona persistencia de datos centrales (lo que hace RestKit), pero es una API muy buena y sólida basada en bloques para la interacción con servicios RESTful. También tiene soporte incorporado para JSON-Parsing (el rápido JSONKit para iOS <5 y el nuevo serializador JSON de Apple que comienza con iOS 5. SI quiere una fácil red asíncrona pero aún tiene control total sobre la persistencia de Datos del Núcleo esto parece una muy solución limpia – codeclash

+6

RestKit usa AFNetworking para su capa de red –

5

Creo que es un enfoque válido. Lo he hecho varias veces. La parte difícil es cuando tienes que lidiar con la sincronización: si el cliente y el servidor pueden cambiar las cosas al mismo tiempo. Casi siempre necesita lógica de fusión específica de la aplicación para esto.

Cuestiones relacionadas