How to sync CoreData and a REST web service asynchronously and the same time properly propagate any REST errors into the UI

前端 未结 4 789
别跟我提以往
别跟我提以往 2020-12-07 07:03

Hey, I\'m working on the model layer for our app here.

Some of the requirements are like this:

  1. It should work on iPhone OS 3.0+.
  2. The source of
4条回答
  •  醉酒成梦
    2020-12-07 07:26

    There are three basic components:

    1. The UI Action and persisting the change to CoreData
    2. Persisting that change up to the server
    3. Refreshing the UI with the response of the server

    An NSOperation + NSOperationQueue will help keep the network requests orderly. A delegate protocol will help your UI classes understand what state the network requests are in, something like:

    @protocol NetworkOperationDelegate
      - (void)operation:(NSOperation *)op willSendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
      - (void)operation:(NSOperation *)op didSuccessfullySendRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
      - (void)operation:(NSOperation *)op encounteredAnError:(NSError *)error afterSendingRequest:(NSURLRequest *)request forChangedEntityWithId:(NSManagedObjectID *)entity;
    @end
    

    The protocol format will of course depend on your specific use case but essentially what you're creating is a mechanism by which changes can be "pushed" up to your server.

    Next there's the UI loop to consider, to keep your code clean it would be nice to call save: and have the changes automatically pushed up to the server. You can use NSManagedObjectContextDidSave notifications for this.

    - (void)managedObjectContextDidSave:(NSNotification *)saveNotification {
      NSArray *inserted = [[saveNotification userInfo] valueForKey:NSInsertedObjects];
      for (NSManagedObject *obj in inserted) {
        //create a new NSOperation for this entity which will invoke the appropraite rest api
        //add to operation queue
      }
    
      //do the same thing for deleted and updated objects
    }
    

    The computational overhead for inserting the network operations should be rather low, however if it creates a noticeable lag on the UI you could simply grab the entity ids out of the save notification and create the operations on a background thread.

    If your REST API supports batching, you could even send the entire array across at once and then notify you UI that multiple entities were synchronized.

    The only issue I foresee, and for which there is no "real" solution is that the user will not want to wait for their changes to be pushed to the server to be allowed to make more changes. The only good paradigm I have come across is that you allow the user to keep editing objects, and batch their edits together when appropriate, i.e. you do not push on every save notification.

提交回复
热议问题