MVVM & iOS - The Missing Rules - ios

I've being working for a bit now with MVVM along with Swift. The principle is very simple:
ViewController is responsible for the View;
ViewModel is responsible for the Model;
ViewController owns the View;
ViewController owns the ViewModel;
ViewModel own the Model;
period.
That's clear to me. But there are some questions I still have about it (they might sound stupid, but it's important to be as clear to newbies as the rules above):
Should ViewModel be responsible for the business logic? I mean, since ViewController don't own models, it feels right to place the biz logic in ViewModel;
Should ViewModel be a struct? This is a tricky one. I'm guessing ViewModel should also give an API to ViewController interact with data. Therefore, sometimes we need to use some escaping closures in order to fetch asynchronous data (e.g. HTTP calls). Structs can't hold it.
Should I hide non-outlets variables from ViewController? Sometimes we need a strong reference to some property in order to present views (e.g. keep the current page of an UIPageControl). Should ViewController hold this reference?
How can I fire ViewController updates from ViewModel? I do read about reactive programming, but my question is wider: Sometimes ViewModel needs ViewController to respond to some actions, which is the best way to do it? Should ViewModel keep specific callbacks to specific reactions ViewController can handle? I came across Srdan Rasic's post about "binding" properties and I got confused (perhaps its not related to this question at all).
I'll be glad if you guys can share your solutions. Thanks!

Your question is quite wide. Someone will certainly explain it more widely than me, or might have different opinions. But these are my observations:
1. Yes ViewModel should be the only component which handles business logic
2. I guess that you answered it yourself, it should be a class. I do not have any reason for why should it be struct. But if it fits your needs who am I to say.
3. Depends on the use. If you use it for purpose of a view, then it is okay to have it here. There also exists a concept of having separate ViewModels for smaller parts, unfortunately, do not know the name. I mean you have a main ViewModel for a whole view and subViewModels for subview. So you will not end up having a big bunch of a code in ViewModel. Also sometimes it is acceptable technical debt (hope that no on will kill me for saying that)
4. It goes like this. You will press the button, you will call the method in your ViewModel called buttonPressed(or triggers an event). Then your ViewModel will do its job, probably obtain a new data and sets the view for that. From what I've seen you might do it with having a weak reference to your View in your ViewModel, or bind reactive properties in your View. The second option will leave you without the need of having View in your ViewModel, but you will have to to register observer for every view setting property from ViewModel.

Related

Design Pattern for constructing an object which requires data from multiple UIViewControllers

In this question I want to discuss how to construct an object which requires data from multiple UIViewControllers which are embedded in an UINavigationController.
For this post I'm providing an example where I'm making a demo-app where users can buy fake plane-tickets. This is the oversimplified struct that represents a Ticket:
struct Ticket {
let originAirport: Airport // UIViewController 1 provides this data.
let destinationAirport: Airport // UIViewController 1 provides this data.
let departDate: Date // UIViewController 2 provides this data.
let returnDate: Date // UIViewController 2 provides this data.
let customerName: String // UIViewController 3 provides this data.
}
The process of booking a Ticket requires multiple steps / UIViewControllers. In every UIViewController I can get some - but not all data about the ticket. At the end of all steps I want a Ticket struct/object which has all the data in it's properties. What is a nice design pattern to handle this problem?
These are a few "solutions" I considered:
Passing data through segues: For every step / UIViewController I'd pass on a partly constructed Ticket object to the next UIViewController. This new UIViewController adds additional information to the object. The problem with this approach is that for every UIViewController I need to pass a Ticket object with partly filled in information. This means that the properties in Ticket are optional .. which doesn't make sense from the Ticket perspective: all properties are required. The other problem is that the UIViewControllers are tightly coupled with each other and this problem becomes bigger once the amount of steps increase.
Use a Singleton / UserDefaults: This is a hack-ish workaround
which isn't a solution to the problem.
Perhaps I'm dealing with an XY problem - maybe my solution doesn't make sense where I'm initialising the Ticket object once all steps are finished. But what would be a good approach to solve this problem?
The best solution for this, if you are saying that you that you go step by step is using dependency injection
This explains pretty good why you should avoid singletons and how dependency injection solves your problem
https://www.swiftbysundell.com/posts/avoiding-singletons-in-swift
Your first solution suggest this, but you don't necessarily need to send a Ticket object as a injection, you can send the different variables as a dictionary and at the last step transform the dictionary to an Ticket object
What you are describing is called Builder Pattern. You can read a short explanation here.
More detailed explanation is:
You may create class TicketBuilder. Why class? Well, classes are passed by reference, while structs are passed by value.
In every VC in the reservation process, you may have shared field "var ticket: TicketBuilder" as you have described in your question, passed by prepareForSegue method. The difference is that it all will be referenced to the first creation of the TicketBuilder instance(in the first VC - no unnecessary memory allocation YEY!).
What is more, as an implementation suggestion of the Builder Pattern, several things are important: var isBuild: Bool bool property, .canBuild()->Bool verification method and .build()->Ticket method that creates actual Ticket from TicketBuilder class.
Lastly, on my opinion, having Singleton Manager class for such a long reservation flow is pretty good solution, and I won't mind using it.

Will adding multiple methods in shared singleton class cause any performance issue?

In a shared class I created, some methods in the shared class are called only once from a view controller . Do I need to add those method inside view controller class? Will adding those methods directly inside view controller improve performance?
I know singleton instance will be allocated once and it will retain for whole application, In that case calling method from singleton class or adding method directly inside view controller doesn't make any performance difference is what I guess!
You should keep the methods separate in a Model class (often a singleton) if these methods do not belong in the View Controller class. That way you are implementing the MVC design pattern which is good to apply to your projects for many reasons (read a good design patterns book for more).
Performance is not something you have to worry at this point (you hardly ever see any improvement by adding these methods directly to the View Controller), but code readiness and clean code practices are something that will actually pay off.
Keep also in mind that the view controller is there for mediating control between the model and the views, so anything related to this task should be in the View Controller code.
Actually the Singleton class instance initialised once per application. So ideally you should use that for sharing common data between view controllers .
Now about method implementation. If those method are doing something which is not related to view controllers for example if those methods are modifying some data and returning back to the controller and if that is common throughout all the controllers then you can implement that in Singleton class . I dont think there will be any big performance issue if you go with either method . Its just matter of clean coding .

I need to understand why delegation in Objective-C is so important, what makes it so special?

So I've read about delegate explanation and practices a lot, but I still seem to not get it, I have specific questions and I would love to have some insightful simple answers.
Why use delegate over instance method? In UIAlertView why not just make – alertView:clickedButtonAtIndex: an instance method that will be called on my UIAlertView instance?
What is the delegate property? why do I have to make delegate property and define it with that weird syntax #property (nonatomic, strong) id <ClassesDelegate> delegate
Is delegate and protocol are two faces for a coin?
When do I know I should implement delegate in my app instead of direct calling?
Is delegate used as much and as important in Swift?
What gets called first and why? The method in the class who made himself a delegate? or the delegate method itself in class where it is declared?
Thank you for taking the time to go through this, I am desperately looking for a clear and helpful answers to my questions, feel free to give example or cover some related topic!
The advantage of delegation is Dependency Inversion.
Usually code has a compile-time dependency in the same direction of the run-time calling dependency. If this was the case the UITableview class would have a compile-time dependence on our code since it calls our code. By using delegation this is inverted, our code has a compile-time dependency on the UITableview class but the UITableview class calls our code at run-time.
There is a cost involved: we need to set the delegate and UITableview has to check at run-time that the delegate method is implemented.
Note: When I say UITableview I am including UITableviewDelegate and UITableviewDatasource.
See: Dependency inversion principle and Clean Code, Episode 13.
Maybe a real life example can better describe what's different in the delegation design pattern.
Suppose you open a new business, and you have an accountant to take care of the bureaucratic stuffs.
Scenario #1
You go to his office, and give him the information he needs:
the company name
the company # number/id
the number of employees
the email address
the street address
etc.
Then the accountant will store the data somewhere, and will probably tell you "don't forget to call me if there's any change".
Tomorrow you hire a new employee, but forget to notify your accountant. He will still use the original outdated data you provided him.
Scenario #2
Using the delegation pattern, you go to your accountant, and you provide him your phone number (the delegate), and nothing else.
Later, he'll call you, asking: what's the business name?
Later, he'll call you, asking: how many employees do you have?
Later, he'll call you, asking: what's your company address?
The day after you hire a new employee.
2 days later, he'll call you asking: how many employee do you have?
In the delegation model (scenario #2), you see that your accountant will always have on demand up-to-date data, because he will call you every time he needs data. That's what "don't call me, I'll call you" means when talking of inversion of control (from the accountant perspective).
Transposing that in development, for example to populate a table you have 2 options:
instantiate a table control, pass all the data (list of items to display), then ask the table to render itself
instantiate a table control, give it a pointer to a delegate, and let it call the delegate when it needs to know:
the number of rows in the table
the data to display on row no. n
the height the row no. n should have
etc.
but also when:
the row no. n has been tapped
the header has been tapped
etc.
Firstly, don't feel bad that all if stuff isn't clear yet. This is a good example of something that seems tricky at first, but just takes time really click. That will happen before you know it :-). I'll try and answer each of your points above:
1) Think of it this way - the way UIAlertView works now, it allows Apple to “delegate” the implementation of the alertView:clickedButtonAtIndex: to you. If this was an instance method of UIAlertView, it would be the same implementation for everyone. To customize the implementation would then require subclassing - an often over relied upon design pattern. Apple tends to go with composition over inheritance in their frameworks and this is an example of that. You can read more on that concept here: http://en.wikipedia.org/wiki/Composition_over_inheritance
2) The delegate property is a reference to the object which implements the delegation methods and whichs should be used to “delegate” those tasks to. The weird syntax just means this - a property that holds a reference to an object that adheres to the protocol.
3) Not quite - delegation leverages protocols as a means for it’s implementation. In the example above, the is this the name of a protocol that an object which can be considered a delegate for that class must adhere to. It is inside that protocol that the methods for which a delegate of that class must implement are defined. You can also have optional protocol methods but that’s a different topic.
4) If I understand the question correctly, I think a good sign that you may want a delegate to be implemented instead of simply adding instance methods to your object is when you think that you may want the implementation of those methods to be easily swapped out or changed. When the implementation of those methods changes considerably based on where/how the functionality your building is being used
5) Absolutely! Objective-C and Swift are programming languages and the delegation pattern is an example of a design pattern. In general design patterns are hoziontal concepts that transcend across the verticals of programming languages.
6) I’m not sure I understand you exactly but I think there’s a bit of misunderstanding in the question - the method does not get called twice. The method declared in the delegate protocol is called once - typically from the class that contains the delegate property. The class calls the delegates implementation of that property via something like:
[self.delegate someMethodThatMyDelegateImplemented];
I hope some of this helped!
Sometimes you want your UIAlertView to work different in different contexts. If you set your custom UIAlertView to be delegate of itself it has to provide all those contexts (a lot of if/else statements). You can also set seperate delegate for each context.
This way you say to your compiler that every class (id) which implements protocol ClassesDelegate can be set to this property. As a side note it should usually be weak instead of strong to not introduce reference cycle (class A holds B, and B holds A)
Protocol (interface in other languages) is used to define set of methods which should be implemented by class. If class conforms to the protocol you can call this methods without knowledge of the specific class. Delegate is pattern in which class A delegates some work to class B (e.g. abstract printer delegates his work real printer)
When you need few different behaviours which depends on context (e.g. ContactsViewController needs to refresh his list when download is finished, but SingleContactViewController needs to reload image, labels etc.)
It is one of the most fundamental patterns in programming, so yes.
It's the same method
You can't just add a method to UIAlertView, because you don't have the source code. You'd have to subclass UIAlertView. But since you have more than one use of UIAlertView, You'd need several subclasses. That's very inconvenient.
Now let's say you use a library that subclasses UIAlertView, giving more functionality. That's trouble, because now you need to subclass this subclass instead of UIAlertView.
Now let's say that library uses different subclasses of UIAlertview, depending on whether you run on iOS 7 or 8, and UIAlertview unchanged on iOS 6. You're in trouble. Your subclassing pattern breaks down.
Instead, you create a delegate doing all the things specific to one UIAlertview. That delegate will work with the library just fine. Instead of subclassing a huge and complicated class, you write a very simple class. Most likely the code using the UIAlertview knows exactly what the delegate should be doing, so you can keep that code together.

iOS: class instances connection and architecture with multiple UIViewControllers

I have a theoretical-practical question. I can't understand how I must do. I have a class let's call them DataManager that manage all plist writing-reading things and I need to get access to plist (i.e. work with that DataManager class) from different UIViewControllers.
I also have one class, I call it ModelManager, that is work with all kind of "utilities classes", include my DataManager. ModelManager works only with one complex UIViewController right now, let's call it MainUIViewController for clearness. And for now, I thought that all calls from UIViewControllers will be comes to ModelManager and from it to end-call classes. But now I'm confused.
Here is an illustration of my architecture:
I'm see different approaches and don't know how to decide and if there is some rules or guides for that. So, here is my choices:
1) I add some interface to ModelManager and from my another UIViewController (not a MainUIViewController) allocate and initialise it.
2) I add some interface to ModelManager and create a property with reference to ModelManager in another UIViewController and when segues performs set this property from MainUIViewController.
3) Work with DataManager itself and allocate and initialise it from another UIViewController
4) Work with DataManager itself and create a property with reference to DataManager in another UIViewController and when segues performs set this property from MainUIViewController.
Which approach is correct?
I know that this is some kind of depends from developer which approach to choose, but I never read and didn't find any tutorial or guide of how to develop multi-class architecture.
Ask me about any circumstance that you want to know.
You can use a singleton or you can instantiate one instance of the class in your app delegate and pass it around to all your view controllers via #propertys on each controller. There's no right answer, it's mostly a matter of preference. I prefer to make my ModelManager/DataManager type classes singletons, but a lot of people are rabidly opposed to singletons. However, if you work with Cocoa for any length of time you'll find that it's full of them (NSUserDefaults, NSFileManager, UIDevice, probably some others I'm forgetting).
Here's a good example on how to create singletons: http://www.galloway.me.uk/tutorials/singleton-classes/
BTW: Once you have your singleton, learn how to use KVO to make your view controllers respond to changes in the model. It's pretty fantastic once you get the hang of it. http://nshipster.com/key-value-observing/

Need some advice on object oriented design for an iOS project

I have a few questions about code design. This might be long. I'll shorten it whereever possible.
Q1) Dependant or Independant?
Creating a class and adding required functionality so as to allow the object to change its own state vs state being changed by a controller (aka viewcontroller)
I find code examples are best when trying to communicate:
Note: I reduced some lines of code. Original code from http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming.
Anyways if I had to set the Account balance for an account it is suggesting I do this:
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
#end
// Implementation Section Starts Here
#implementation BankAccount
-(void) setAccountBalance: (double) x
{
accountBalance = x;
}
-(double) getAccountBalance
{
return accountBalance;
}
#end
//usage
BankAccount *account1 = [BankAccount alloc] init];
[account1 setAccountBalance: 1500.53];
----HOWEVER I believe I would have wrote it in a controller like this:------
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
import "BankAccount.h"
#interface MeViewController : UIViewController
-(void)setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc;
#end
#implementation myViewController
-(void) setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc
{
tempBankAcc.accountBalance = x;
}
//USAGE
BankAccount *account1 = [BankAccount alloc] init];
[self setAccountBalance(Account1,1500.53)]
#end
because I believe it is Me (meViewController) setting the AccountBalance, not the account itself as an account is just an account.
Is this a very bad idea? I can see with their example that the object can look after itself (independent) meaning changing its own state whereas my approach says that the BankAccount can only be modified through/with the controller (dependant)
???
Q2) What should/should not be in a controller?
I have also read somewhere that code written inside the controller should be only for:
Responding to user interaction & Updating the views
so does this means I should never do the following in the controllers:
READ or WRITE to and from NSUserDefaults. Since its a singleton, I thought it would be easier to write to it regardless of which controller is currently active? bad idea?
I understand that I should save data (includes NSUserDefaults) in applicationDidEnterBackground and in applicationWillTerminate so does that its a bad idea to save elsewhere (eg. in another controller).
Q3) Which design patterns do you most commonly use and which ones do you abuse wrongly?
Singletons:
My understanding is that [UIApplication sharedApplication],[NSNotification defaultCenter] and other singletons are accessible via all controllers, how about NSObject subclasses? or UIView subclasses?
And apparently you can use NSNotification to notify other controllers when the model has been updated.
Can someone tell me an example of when to use and how to use that?
Maybe when you import some data, that has different attributes, than was originally intended, then the observers could be notified of an upgraded data model, is that an example of when you would within your data model notify a controller?
Thats enough questions for now.
Sorry but I had to get them all out of my head:-)
Ben
First things first: don't use this
#interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
#end
Here, the accountBalance ivar is public, while it should be private.
Instead, use a #property:
#interface BankAccount: NSObject
#property (assign, nonatomic) double accountBalance;
#end
That'll define a setter:
- (void)setAccountBalance:(double)accountBalance { ... }
and a getter:
- (double)accountBalance { ... }
and a private instance variable (ivar) named _accountBalance.
You can then, in your implementation, use:
#synthesize accountBalance;
which will automatically create the setter/getter like this:
- (void)setAccountBalance:(double)accountBalance {
_accountBalance = accountBalance;
}
- (double)accountBalance {
return _accountBalance;
}
Q1
If you take away all the business logic from the object itself, it's nothing more than a shallow container object. Further more, you need to replicate that logic in every controller you use. Business logic goes into business objects.
To your concrete example, the method of the controller does nothing but delegates the call down to the very object itself (infact, calling the same method if you use properties here). So you gained nothing at all. It may be fine to have that method in the controller, if the controller does more than just calling down on the object, maybe update some more data. One of the good hints here is that the controller does not use any of its own instance variables. It could easily be a class method. It's a code smell.
Q2
Basically, you have three choices for accessing NSUserDefaults: application level, view controller level, or view level.
Worst case is view level - a view should work in any context and should be configurable any way you like, and it certainly should not depend on some magic outside things. This would make reusability (not only for other apps, but also within the same app) a pain.
Accessing the defaults on the view controller level is often ok, especially if they take some singleton role. I.e. if you only ever have one playing screen and one setting screen, each of them might easily talk to the defaults. If there's the chance that you may have several instances of the same class differently configured, this gets a pain and bad smelling work arounds to "individualize" those.
This is where you want to place the access of the defaults outside of the view controllers, which is the most elegant and flexible approcach, but sometimes just not necessary.
Reusability may come earlier than expected, i.e. opening up a second text editor window (which might or might not show a different font), a second settings screen (i.e. a popover), a second playing screen for board games, etc.
Q3
I don't think Singletons are bad per se. They do come with a hefty price tag, though. They come convenient at early stages, just like global variables do.
They get very expensive, soon. There's no ownership, everything is shared, no chance to change a single bit without effecting the other users of that object. Reusability for objects depending on singletons is poor, as you always need those singletons as well. I tend to avoid them most of the time. And whenever I had one of them in my code, getting rid of them was a good decision.
As for the notifications: they are really designed for communicating on a system level. They shouldn't be abused for normal application logic and communication. It's a broadcast for system level events. If you use them as a substitute for object communication, this is a sure way to hell. This takes every logic out of the code, and there's no way build up responsible code.
Q1) Model-layer objects, especially ones that will be interacted with and mutated, should be responsible for their own internal representation as well as representing the knowledge of the rules of the interactions. For a bank account, I think both the approaches you present are wrong. The second in particular because it is actually taking even the responsibility of updating the state away from the account. But the first also because it only provides a setBalance method, which doesn't make sense in the real world. Whoever uses that account has to now handle all the logic of transfers, withdrawals, deposits, interest, and so on. Really, a bank account should have the methods deposit withdraw balance and so on, that way it can represent the rules and logic by which these interactions happen. In this case drawing from how this would work in real life can be helpful.
Q2) A lot of this depends on how your app is set up. A simple app's model layer may be just a plist or NSUserDefaults and some NSDictionary instances. In that case you might not want to have a view controller interact with it, but maybe a data controller object. But you can probably get away with having view controllers talk to that kind of model. When things get more complex though, you definitely need to separate concerns, and have controller objects closer to the data model or have more sophisticated models providing the rules of their interactions. Personally I'd avoid having all the view controllers loading NSUserDefaults, you could just make a single data controller class that could handle that and instantiate it as needed.
Q3) I see two questions here. Not sure what you mean by "accessible to all controllers". But NSNotification is incredibly useful when used right. Say you have 3 view controllers, all coordinating a different view of the bank account - one is a ledger, one is a pie chart, one is a budget calculator. When the app makes a request to refresh the bank account's information from the internet, when that request comes back it can notify all three of these view controllers at once and they can refresh their views accordingly. It's really used any time you have more than one object interested in knowing that something happened.
Hope this helps and let me know if you have any questions.
Read Stanford's lecture about MVC. I think you will find many answers there http://www.stanford.edu/class/cs193p/cgi-bin/drupal/node/205

Resources