After doing some reading I notice Apple pushes the use of delegates on controllers communicating with one another.
So say I have a Menu controller which needs to communicate with the help controller (and they need to share info - lol don't ask me why they would). I could do this through delegates, but why use delegates when I can pass the required information on through a help object and have the help controller pick back up this info that was changed in the previous controller.
Delegates still couples - however loosely it may be, wouldn't the use of objects be the best practice here for re usability?
Delegates are great for responses, especially if the response isn't going to be immediate.
If you're simply telling the help controller something like what information to display, passing it directly is great. If you want to know, for example, when the help controller is done displaying help for the user a delegate is clearer and usually superior.
Related
I am working on CleanSwift architecture. I see there is no direct communication between a presenter and associated scenes router in diagram,
But often there are certain scenarios where a presenter only needs to rout to another view controller. I wonder if its permitted for presenter to call a router routeToOtherView() function directly, rather calling an extra function in view controller which simply redirect.
I have also used CleanSwift in couple of projects. What I liked about this architecture is that it works in unidirectional flow. And in this flow ViewController works with Router, Interactor and Presenter. Unidirectional flow allows us to find bugs easily.
Let's take one scenario to understand this. Suppose you have a Button and click on that you want to move from ViewController1 to ViewController2. By any mistake you write ViewController3 instead of ViewController2, now it's showing ViewController3 on Button click. To solve this bug you have to look at routing mechanism. And you know that routing mechanism resides in the ViewController1, so to solve it you should just move on to ViewController1 and find the responsible function for route and solve the bug.
You are breaking the flow, if you move routing in Presenter for some of the cases when there is only need is to move from one Controller to another. Also the architecture will be dependant on you because you have to keep in mind that whether you have added routing mechanism in Presenter or in Controller. It also affects the collaborative environment, where your counter part has to search for the routing mechanism. It will also take time to solve the bug if you observe the above Scenario.
So it's better idea to don't break the flow. It's good to spend more to make it precious. Hope this answer can help.
I am creating an Obj-C application, and am working on a single view. However, within this viewful, there is enough logic that I want to separate that from the view controller itself. I decided to create a delegate, but my current problem is how these two should communicate. Two potential solutions I have been considering:
1) An instance variable of the view controller within the delegate. Then when any view updates need to happen I simply call the appropriate method on that instance variable.
2) Notifications being fired off by the delegate and add the view controller as an observer.
Is there one method that is obviously superior or does it depend on the situation? I don't know the proper way to go about this and am trying to approach this from the correct angle.
If it's non-UI related responsibilities you want to separate from the view controller, it's very natural and recommended to have another object responsible for those tasks. In this case, you can either have a singleton for those responsibilities, or simply a NSObject subclass instance strongly referenced in your view controller.
If it's pure UI related tasks you want to separate from the view controller, just to organize the source code clearer, you should instead create categories for the view controller and name the categories according to their responsibilities, for example, MyViewController(Localization), MyViewController(UserInteration), etc.
This is a broad question. However, if what you are trying to do is simply refactor existing code to make maintenance easier without changing any functionality, use instance variables. Your code execution sequence will be unchanged and your method can return status information on the execution results. Your original controller and your new refactored class are tightly coupled - know a lot about each other.
Notification logic is event-based (something interesting happens and an event is sent to registered observers). The logic is executed when the observer receives the event so there is no guarantee you can control the exact execution sequence, and the caller does not know if the observer received or successfully processed the message - the are loosely coupled.
When in doubt look at what Apple does in its framework classes like UITableView. Delegates give you fine control over when things happen.
I am creating a login app for iOS and have stumbled upon a design issue. In my app some data (e.g. current user id) has to be shared across view controllers so my initial thought was to hold that data in the AppDelegate and just call it from there whenever it was needed. This would work but it would mean that the AppDelegate would be doing work that it wasn't intended to do and hence it would be bad architecture, so I thought of creating a singleton class to hold all the shared data instead. This seems to be more focused and I have used this strategy in some of my previous apps, but googling the best practices for singleton classes, I found many results against using them, as they:
Hide dependencies
Violate the single responsibility principle
Make unit testing difficult
(taken from the top answer to this question: What is so bad about singletons?)
The alternative to the two other design patterns would then be to pass data back an forth between view controllers, but this again seems inappropriate. Take for example the current user id I would have to pass it from the login view controller to the main view controller (which is the same for all users), then from the main view controller to a more specified view controller which is customized for the user. In this case the main view controller is holding data only for the purpose of passing it to the more specific view controller and to me this also seems to violate the single responsibility principle. Would it be bad design to let the main view controller hold data it doesn't need or is there a better alternative?
There is no "magic" way of storing the model state of your model-view-controller application: you build a class, and you "anchor" it somewhere for easy access.
One common practice is using the app delegate. It is convenient, because it is a system-supplied singleton globally available to your app, but it is logically inferior, because, as you noted, app delegate was not intended for that.
Another common strategy is using a singleton. This is commonplace in app development, and it works fine in practice. You can mitigate the common grievances by limiting the access to your singleton to initializers of your view controller - this addresses the hidden dependencies and the testability issues.
Finally, you can pass the data around, in which case it is the same as "anchoring" it in one of the view controllers. Arguably, this leads to even bigger problems than singletons, because the dependencies become even harder to trace.
I would recommend storing the state in a singleton, and use it in the initialization code of your view controllers. This way the dependency on the singleton remains localized, and you could test your logic with minimal effort.
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 9 years ago.
I keep hearing two different sides to this story. I hear nsuserdefaults is the best way to pass data from one controller to another while using property is the best way. I got a bunch of answers on stackoverflow and now wondering what you guys think.
There is no best way to pass data, it really depends on the issue you are trying to solve. That being said dependency injection is the most common one, that is simply instantiating your view controller and setting the properties you need.
As a note NSUserDefaults most definitely should NOT be used to pass data between view controllers, it is meant to be used as a way to persist state between application launches. Maybe you are referring to a singleton object?.
While you certainly can use NSUserDefaults for passing information around your application, I find that it is often cleaner and more obvious to pass information explicitly whenever possible.
For example, if you have a view controller with a list of book titles and another view controller that gives you details about a selected book, this would be a straightforward way to pass information from one to the other:
BookDetailsViewController *bookDetailsViewController = [[BookDetailsViewController alloc] init...];
bookDetailsViewController.book = selectedBook;
One view controller has information, the other needs it, so the information is simply passed from where it is to where it needs to go.
If information has to go back the other way, from a presented view controller to its presenter, blocks or delegation can be utilized in a similarly straightforward way.
If information needs to be saved or used throughout an app, this is where NSUserDefaults and/or singletons can be useful. In general though, I would not put information in a place where it is not actually needed or used.
When I need to access the same data from different places in the application, I use a shared model object and use it as a singleton.
Every object that needs it holds a weak reference to it, and the object exposes an API to query its properties.
If you also need to persist the data in this shared model, make it implement the NSCoding protocol and add methods to serialize it to a file.
I'm building an application that among other things allows users to upload documents. I have the basic create/view actions working just fine, but i'd like to reuse this action in other places.
I want to know if anyone has a pointer for how to do this. There doesn't seem to be a very good way of doing this.
Here are a few ways i've considered:
Try to do a chain(). This doesn't work since chaining does a GET, and to upload you need a POST.
Break out the main business logic into the Grails "service", and make two actions that use the same code.
Use a JS modal window. I've been thinking a modal that contains an iframe to an "unskinned" version of the document upload. The trick here is to get the window to close when the upload is done.
Thanks
--Matthias
I don't care for the extending controller method. In fact, I avoid inheritance when possible. I'd rather put the common code in a service class and reuse it that way.
You can use a base controller class, and place the common functionality there. Then extend the base controller and call the method from other action methods.