iOS Design Patterns - Part 3: MVC-N | Ray Wenderlich

Learn about Model-View-Controller (MVC) and the dreaded massive view controller problem and how Model-View-Controller-Networking (MVC-N) can save the day.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/3816-ios-design-patterns/lessons/3

Thank you:) Some notes. (I edited 4 times this post!, I’m sorry)

This video is more about Singleton Pattern and MVC Pattern with enhancing Network handling.
MVC-N probably is a teacher slung, but, please, provide me with a link that proves that MVC-n term exist. I found here an MVC-N talk but is referred to N as an extension and not a pattern.

In the code, the instructor uses word Injection wrongly and maybe gives the wrong intention to the student about DEPENDANCY INJECTION (another pattern that not used actually in this episode).
Please replace word injection with Singleton or Dependancy (without injection as we don’t inject anything in the constructor or outside from our Object).

Inside the completion closure, I liked that guard of weak self but I would prefer to name it as weakSelf and not StrongSelf as your guard is only check if it’s nullable. The strongSelf could lead the student to think that is a strong reference but is not.

Resume for this video.
Replace article topic to Singleton, remove word injection and add a small topic front of the video about Singleton Pattern. More reference links about every pattern in use to other sites (or Wikipedia) would be nice.

Question: Why we use the DispatchQueuemain in the Network Singleton handlers.

All my notes are in the mood to improve the lesson. Feel free to correct me and lets produce the best results for this topic.

Thank you again for this delightful video.

@kostapappas Thank you for your feedback. You made several points, and I want to address these in turn, hopefully providing useful information to future viewers too. :]

This series went through several proposals prior to creation. I initially did want to cover the Singleton pattern.

However, we as a team decided this series should be kept short, and 11 videos just isn’t enough to cover every design pattern and related concepts.

Hence, we made certain assumptions about viewers’ knowledge, including a basic understanding of iOS and common design patterns. You may notice that MVC, Singleton, Delegate, etc patterns aren’t covered explicitly in this series. We assumed most iOS developers would already know about this, and we wanted to present material that would be valuable to most iOS developers.

I interpret this statement as having two parts: (1) Is MVC-N actually a design pattern, and (2) where did it come from?

In response to (1), I propose, and Wikipedia agrees, that a design pattern is a reusable, template solution to a common development problem.

With this definition is mind,

  • Does MVC-N solve a common development problem?

Yes, most apps need to talk with an external resource, and you need some way to handle this.

  • Is MVC-N a reusable, template solution?

MVC-N proposes that networking logic doesn’t belong in models, views or controllers, the main “types” used in MVC. Instead, this logic should be pulled into separate classes that can be used, in composition fashion, wherever needed. This isn’t a concrete implementation, but rather, it’s a methodology: a reusable, template solution.

Thereby, yes, MVC-N is a design pattern.

In response to (2), I personally learned about the idea of “MVC-N” (although, not necessarily by this name) from AFNetworking, one of the earliest open-source networking libraries to be widely used for iOS development in Objective-C.

AFNetworking has an AFHTTPSessionManager class. The documentation suggests the following:

Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass AFHTTPSessionManager, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application.

Doesn’t that near exactly describe the idea of MVC-N presented in this video? :wink:

As for the name “MVC-N” itself, I’ll confess this is simply what I’ve both heard it commonly called and call it myself. Articles like the one you mentioned by Marcus Zarra also use this name too, so if anything, I’d say it’s not wrong to call it this.

Actually, “dependency injection” is exactly what I meant.

Whether you’re injecting a dependency as a singleton or using a dependency injection container, you’re still doing dependency injection, right?

I wanted to cover dependency injection explicitly within this series too, but alas, this concept got cut due to time constraints as well.

Also, since we’re nitpicking a bit here, I wouldn’t call “dependency injection” a design pattern. If anything, I’d simply call it a design paradigm or practice, maybe?

That is, dependency injection is simply when you pass a dependency to a consuming object.
There are two main ways to do this:

  1. property injection
  2. initializer injection

An example of property injection would be:

let person = Person()
let pet = Pet(name: "Rover")
person.pet = pet

An example of initializer injection would be:

let pet = Pet(name: "Rover")
let person = Person(pet: pet)

You’d be hard pressed to say that either of the above is actually using a design pattern…

Sure, you can use dependency injection frameworks like Swinject to help manage dependencies across your application too (and I recommend you do!), but this isn’t required by any means to do “dependency injection.”

Sorry, you’re mistaken here.

strongSelf is a strong reference for the duration of the closure.

This is why you don’t have to unwrap it (use either ? or !) anytime you access properties on it thereafter, which you would have to do if it were weak.

This is a convenience for callers. If you didn’t dispatch to the main queue, any callers doing operations that must be done on main (e.g. UI related) would have to dispatch to it themselves.

If you prefer, you can instead pass in the queue to dispatch to the method itself. You’d just change the method signature to also take a dispatch queue.

Thank you again for your comments @kostapappas.
I’m sure other viewers will have these questions too, so hopefully this helps them in future as well. :smiley:

2 Likes

Thank you for the extended feedback.

  • I agree with the team. 11 minutes it’s a PERFECT choice.
  • As junior dev too many names confuses me. So I’m trying to keep the Patterns as described in GoF and use design principle terms for Clean Code best practices. So (for me) MVC-N = Separation Of Concerns and Single Responsibility as a design principles and implementation of Singleton design pattern.
  • Setter or property Injection in Swift, as we don’t have @Required like Java is not preffered by me. Yes! and thank you for proposing the Swinject. Defenitely I will explore it.
  • About strongSelf, yes you are 100% correct. The guard let a = weakSomething creates a strong reference for this duration of the closure as increase the reference number. Also a let is always a strong reference (only var can be weak). It was an excellent time to clear that (more here)
  • I need more time to investigate the DispatchQueue. Is something that probably I’m doing wrong.

REALY Thank you for the feedback. Keep up the good work :slight_smile:

Thanks for these great course.

Small question.

I see in a lot of apps that all API calls are in one network client like you did here.

I usually have network client that handles success/errors but the API calls are static functions in the associated models. for example:

class Product {
    var name: String!

    class func getProducts(callback: ...  ) {}
}

What do you think about this approach? is this better then having all API calls in one client?

Thanks

Have you guys heard of the MVCS pattern? (the last -S is for Store). Basically it’s just a generalized version of MVC-N.

In my experience, there’s three main trains of thought about this:

  1. Pull networking into its own entity… which gives MVC-N shown here.

  2. Put networking in the models… basically like Facebook Parse did.

  3. Use a hybrid of the above… Firebase sort of does this.

Which of these is “the best” to do? It depends on your project, of course. :]

I’ve personally had the best experience with MVC-N in my own projects, especially if I need to share networking across two or more apps.

However, you can make any of the three options above work… just think about what you’re trying to do and plan ahead.

In particular, whenever I’m architecting a solution, I’ll run it through the SOLID principles and see if it breaks any principle that I’m unhappy about or anticipate will be a big issue later on.

If you’re not familiar with SOLID, I highly recommend learning it as soon as possible. In particular, I highly recommend Clean Code: A Handbook of Agile Software Craftsmanship, which is the de-factor go-to source for learning SOLID.

Without SOLID, I’d be lost in most development that I do each day… SOLID is a useful testbed for experimenting with “what-if” scenarios, if you will. At least, that’s how I use it. ;]

Thanks for great tutorial.

I am new to iOS development and i have few questions.

Is it absolutely necessary for NetworkClient to be singleton?
Will it be wrong to keep it as ordinary class and create instance for request?

I am very interested in this part of code. Can you explain me what is it for?
// MARK: - Instance Properties
public var dataTask: URLSessionDataTask? {
get {
return objc_getAssociatedObject(self, &AssociationKey.dataTask) as? URLSessionDataTask

} set {
  dataTask?.cancel()
  objc_setAssociatedObject(self, &AssociationKey.dataTask, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}

}

It’s useful to make the network client a singleton. For example, you can later implement network request queuing, response cache, etc, which is much easier to do if it’s a singleton.

I my own apps, I tend to create a network client for each endpoint (that is, different urls) as necessary. Each of which is a singleton, or even better, injected using a dependency injection library such as Swinject.

This is an associated property. You can learn more about them from this excellent NSHipster article.

UIImageView+URL.swift adds a convenience method to set an image from a URL onto an image view.

This is a very simple example of how to do this. You can check out AlamofireImage for a very nice, complete implementation of this.

:]

Thanks,
Just got back from the library with Clean Code. :smile:

Thanks a lot for you answer.

I know it’s not a design pattern but what do you think about wrapping all in Operations,

you could have a group operation that contains 2 operations, one for downloading a resource and the other one for parsing … you will have to inject your network client as a weak reference to the constructor of your operation.

In 2015 WWDC, they had a session on advanced operation … I tend to follow this principle

thanks

Awesome course, dude! it help me think more and understand why we use these patterns, I love the expression on your face~😄

1 Like

This is good but we can better this implementation to remove repetitive code and make it testable. “loadProducts” could be a part of protocol. This protocol can have default implementation to get products. Both home and business products view controllers can adhere to this protocol. and we can just pass enum value i.e. home or business to loadProducts with a callback. You will not need to inject singleton network client to view controller. This will make the code more testable as we can easily mock the service by implementing the same protocol.

rwcleanbackend.herokuapp.com is down which makes working with the network code a bit difficult

Regarding @kostapappas’ point about dependency injection and your response:

I was also confused by your “Injections” comment in the example code. I think both of you have valid points, but I tend to agree with @kostapappas. Dependency injection is at least in my understanding generally considered an alternative to using Singletons.

In fact this article is fairly explicit about it. It is titled “Avoiding Singleton Abuse”, and a proposed solution is to use dependency injection.

https://www.objc.io/issues/13-architecture/singletons/

All of which goes to show none of this is really set in stone. I would suggest however in future videos that when you make a potentially confusing comment like this in your code or when you create a variable like strongSelf, that you explain what’s going on in the video.

@jrg.developer Do you have any feedback regarding this? Thank you - much appreciated! :]

I just checked the service and don’t see any interruptions.

However, it’s running on a free Heroku instance, which sleeps after a period of inactivity.

The requests should still work, but it may take up to 30 seconds to return the first response.

After the first response, however, the responses should be very quick. :]

By “dependency injection,” I was referring to passing dependencies into a consuming / using object, as opposed to having the logic coupled / built into the object itself.

In this albeit loose definition, using a “singleton” is a type of dependency injection… but let’s be honest, it’s a weak form of dependency injection at best, right?

That is, the consuming object still has issues such as tight coupling to the singleton, which “good” dependency injection avoids (see SOLID -> Dependency Inversion Principle).

If this was a full-fledged app in production that I would need to maintain and support over time, I would likely use Swinject and setup dependency injection containers to handle dependency configuration and injection.

I really wanted to cover dependency injection in depth as part of this series – from its simplest form of passing an object around to using dependency injection containers via libraries like Swinject – but alas due to time constraints, I wasn’t able to cover it.

Perhaps in a future revision of this series, this topic can be covered and given the time it deserves. :]

I agree! This is exactly the next step I would take to refactor this code. :]

Explaining all of this would take additional video time, however, and we decided to focus on other patterns instead.