iOS MVVM Tutorial: Refactoring from MVC | raywenderlich.com

@tonioverzeworld I’ve edited the article to use weatherbit.io. Hope you’ll give it a try.

Wow!
I got an email from Dark Sky, Apple seems to have acquired it. Thought of updating that here, and seems the tutorial has already been updated to use a different API. Neat!

Thanks, I’ll do it this week-end. Thanks for this quick update !

I have a similar question:
when the submitAction is declared in the IBAction promptForLocation in the WeatherViewController, the closure to the UIAlertAction has an unowned reference to the alert and a weak reference to the WeatherViewController.

let submitAction = UIAlertAction(
      title: "Submit",
      style: .default) { [unowned alert, weak self] _ in

according to the swift docs

Use a weak reference when the other instance has a shorter lifetime—that is, when the other instance can be deallocated first. 

In contrast, use an unowned reference when the other instance has the same lifetime or a longer lifetime.

Why aren’t both of these references declared as unowned?
The alert outlives submitAction but doesn’t the WeatherViewController as well?

Rather than focus on the lifecycle durations, let’s look at what unowned and weak really mean. Both will not cause the reference to be retained. Using weak will treat the reference as optional and make sure that the reference is not nil before attempting to use it. Using unowned will not check for nil and can cause a crash. So neither is right or wrong, just safer (weak) and more dangerous (unowned). When you use unowned, you must be sure that the reference will always be populated when invoked.

Here is a discussion about weak vs unowned at SwiftLee:

The only benefit of using unowned over weak is that you don’t have to deal with optionals. Therefore, using weak is always safer in those scenarios.

1 Like

To gain a better understanding of the Box class, I abstracted it into an Xcode playground and started testing it with String types. The one thing I’m having trouble understanding is how does changing the value on boxedString trigger my print function to be called? I understand the first call to print function, but the second call confuses me. I also observed the didSet property calling listener, but I’m still not seeing how the magic happens. Here is the code:

final class Box<T> {

typealias Listener = (T) -> Void
private var listener: Listener?

var value: T {
    didSet {
        listener?(value)
    }
}

init(_ value: T) {
    self.value = value
}

func bind(listener: Listener?) {
    self.listener = listener
    listener?(value)
  }
} 

// Testing Box
let boxedString = Box("Chris")

boxedString.bind { name in
    print("Value changed: \(name)")
}

boxedString.value = "Chuck"

When you call bind on the boxedString, you provide a function that calls print and boxedString retains a copy of that function in the listener property then immediately calls that listener.

{ name in
    print("Value changed: \(name)")
}

is your listener function.

Then when you change the value of the boxedString, the didSet method is immediately invoked, causing the listener function to be invoked again. For as long as the boxedString stays in memory, it will keep a copy of the listener that you provided and invoke it each time the value changes. That is the magic of using didSet in Swift.

Hope that answers your question.

Chuck, I had been pounding my head at this for 4 hours yesterday. You helped me understand the whole data binding concept in its entirety. Thank you!

1 Like

Great tutorial loved it thank you

While going through it I noticed the before app has an error asking for where the “clear-sky” image is. You go into the storyboard and it indeed is missing.

Also there’s a typo in the tutorial: “You must import the app for texting. Immediately below import XCTest , add the following”

Good finds, @kaylanx. As you can see in the discussion above, had to change weather APIs from DarkSky to Weatherbit after the tutorial was released. I guess I missed a few things. I’ll clean then up now. Thanks for bringing them to my attention.

1 Like

This is one of the best tutorials I have ever seen! Thank you so very much for creating a tutorial that not only covers the pertinent content so thoroughly but also does it in a way that is very easy to understand. Very awesome. :+1:

Thank you for taking the time to share some feedback. Very motivating. I’m truly glad that you found it helpful.

Thanks for the article. I think if we use Delegation method as data binding it is more like MVP than MVVM. since the viewModel is depend on view.

Hi Chuck,

Thank you for the tutorial. I have a question here.
Can we use Boxing as a data binding method for any kind of app (big or small).
I am still in the learning phase of Combine framework.

The best explanation there can be of the Boxing concept. Thank you so much for this tutorial. Really enjoyed it!

I am trying to understand why did the code for presenting the alert may cause retain cycle. I am confused because the alert is not declared as a property in the view controller like the geocoder is. Please let me know if my understanding below is correct.

The alert is presented on the view controller (self) so the view controller holds a strong reference to it and vice versa, thus we need to access self using weak attribute to avoid retain cycle. Likewise the submit action is added onto the alert thereby alert holding a strong reference to it and vice versa. And hence we use unowned alert so as to avoid retain cycle.

Am I correct? Thank You.

You basically have it, though I’d word it slightly differently. The alert variable is a stack variable that only exists for the duration of the promptForLocation(_:) call. The closure for the UIAlertAction will grab strong references to alert and to self unless you make them weak or unowned. In this case, the alert is actually very short lived and really doesn’t represent much of a risk of a retain cycle. But it is my practice to use weak references to be cautious whenever the closure is retained by the other type. It truly is a confusing topic and I recommend you study it deeply until it really clicks. Advanced Swift Memory Management is a good tutorial to deep dive into this topic.

You can use boxing in any sized app, but it really is a simplistic approach. The Combine framework is much more robust and will have many advantages if you have the option to use it.