Data-model to controller communication when using NSURLSession

Hi,


I have a very simple goal: I'd like to have a data-model manage its own network fetching. It would be implemented as an object containing an array of partially-loaded objects. (Ex: MyNetworkObject.arrayOfUserObjects[0].userImage).


In use, the controller will ask the data-model for some data in the array. If the data is available, it will be immediately displayed on the view. If it is not available, the data-model will tell the controller "hold on. Let me fetch the data." The controller will then put a loading indicator on the view. When done fetching, the data-model will tell the controller "Okay here's the data" and it will be displayed on the view.


Here's my problem: I'm unsure of the best practice for telling the controller that the data-model is either currently fetching data or done fetching data. Should the data-model fully encapsulate the NSURLSession and send a NSNotifcation when done fetching? Should the controller be a delegate of the data-model be notified of changes that way? Or should the controller be the NSURLSession delegate and receive updates from the NSURLSessionTask directly?

Also, I was under the impression that delegation was reserved for communication between views and controllers. Would using a delegate between the data-model and the controller be a violation of MVC? It appears that's how NSURLSession works, so I'm a little thrown off.

Replies

In my opinion, the model should fully encapsulate the method of communication. So when iOS 11 rolls around and NSURLSession is deprecated for the Next Big Thing (TM) like NSURLConnection was 🙂 you don't have to change your controller too. That's just an opinion though. If it ends up with a bunch of boilerplate then it might not be ideal either.


I think a delegate is fine between the model and controller *if* you will only ever have one entity interested in model changes. If there might be more than one "delegate" some day then you are looking at a custom delegate implementation more like a Java listener list (add / remove delegate methods, and the model keeps a list, not just a single delegate property) or the more common notifications or KVO.

Thanks for the response.


The data-model will have to be used by more than one controller, so delegation is out. What do you think about using closures?

Also, I was under the impression that delegation was reserved for communication between views and controllers.

No, delegation is a generally useful pattern throughout the object stack.

Would using a delegate between the data-model and the controller be a violation of MVC?

I think you’re being a bit too literal with regards the structure of MVC. It’s very common to have ‘controller style’ objects that live within the model layer.

The way I like to deal with this is to have my model-to-view controller interface defined entirely in non-networking terms. That is, a view controller just displays model objects and it understands the idea that:

  • the model may change for whatever reason (A)

  • the view controller may want to hint to the model that it’s a good time to refresh (B)

  • the view controller may want to reflect that refreshing state to the user in some way (C)

I then have my network controllers (which are not view controllers) mutate the model in the same way as any other controller, and all the view controllers adjust accordingly. I use a ‘low coupling’ mechanism (a notification, say) to pass the refresh request (B) from the model to the network controller.

The thing I like about this approach is that:

  • my view controllers know nothing about networking, so I can test them in a non-networked environment by simply pointing them at a model and mutating the model

  • likewise, my networking code know nothing about my view controllers, so I can test that without have a GUI up

  • model mutations are communicating to the view controller (A) on the main thread, so I don’t have to worry about threading in my view controllers

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"