In my app there are numerous view controllers which have their own purposes. However, underneath they do share some need for common maintenance work that could use the same method code instead of each having its own copy of the code, literally pasted in.
Is there a way to share the code of these common methods ? I see two possibilities:
1) either one copy of code truly shared in memory as in a special maintenance object of methods
or
2) written once in a block of code but allocated many times as needed by each view.
Which of these is the correct path or what is the correct path, and HOW would it be implemented in the most simple manner ?
Kindness pls, new coder in the room.
Thanks.
-Ric
Note: This is an old question/answer reflective of Apple practices at the time, and answered for a new coder looking for a simple solution they can understand (as requested in the question). There are better and more testable ways to achieve this, using composition.
The best way to achieve what you want is to create a common parent class for your view controllers. So instead of inheriting directly from UIViewController, each of your custom classes will inherit from SomeFeatureViewController (where SomeFeature describes the common feature provided), this class inherits from UIViewController. Now, each of your actual view controllers will inherit from SomeFeatureViewController and any common methods (also any common instance variables used by these methods) can be placed in this parent class.
#interface SomeFeatureViewController : UIViewController
{
int common_iVars;
}
- (void)commonMethods;
#end
#interface ActualViewController : SomeFeatureViewController
{
int specific_iVars;
}
- (void)specificMethods;
#end
The way I see it you should do a class with all the common methods and then subclass it. Say you have MyCommonViewController : UIViewController and then for each different view controller do MySpecificVIewController : MyCommonViewController
As well stated by jhabbott, a subclass of UIViewController is one good solution.
If that's not an option (e.g. you can't change the class hierarchy), another option is to create a category on UIViewController to add the methods and properties you need. This will make your methods available on every UIViewController, including all the standard subclasses, without any extra work on your part. With this solution you cannot directly add ivars, although you can fake it up well enough using associative references.
Well, what I ended up doing was to create a Singleton object and put all my common methods there. This meant that all my View Controllers could utilize the common methods of the Singleton. Maybe this is a bit too open if the project was being developed by a team of programmers but as it is just me I know that all the controllers have similar requirements in processing. So the Singleton approach seemed to work.
It also fit the project because at the time of the question all the View Controllers had been created and to make them a subclass of a parent class seemed to be a retrofit, though I agree that if part of an initial design, it may be a better approach. I do thank the 3 who gave the time to answer.
Related
I come from C# background, is it correct to say that delegates (not the C# version) in Swift are basically the same as interfaces in C#?
I see tutorials on using delegates in Swift, for passing data from one view controller to another view controller.
My question is this, can't one simply add a function to a swift class then have the view controller sub classed from that? Like
func ShowName(name : String)
And have the first view controller call the second controller using that
function (that is in the class that the second controller is subclassed from).
Technically, it is Swift protocols that are analogous to C# interfaces. A protocol is effectively a contract of what methods/properties a class will implement. Like C# interfaces, it can be used in delegation patterns, but it also has far broader applications.
But protocols serve a central function in delegation patterns (see Delegation discussion in The Swift Language or the Protocol or Delegation discussions in Cocoa Core Competencies), in which an object can designate another object with which it will communicate. The protocol simply outlines the precise nature of what an object requires of its delegate object, as well as what optional interfaces it supports with its delegate.
In answer to your question, when you have a delegate, you don't technically need to use a protocol, but it is best practice to do so. It makes the formal contract between the two classes very explicit, while at the same time keeping the two classes otherwise loosely coupled.
While it might take an extra two or three minutes up front to implement the protocol, it's almost always well worth the effort. It will simplify your maintenance of these classes in the future. So while you don't technically need to use protocols for your delegates and/or exchanging information between objects, I think you'll thank yourself if you do so.
You need delegates
No matter if you create some of your own you will not get around using them - they are builtin everywhere.
And yes, you could simply define a function in a viewController and call that one, but then the caller of that method has to now he is dealing with a viewController, nothing he really cares about. All he cares about is the fact that there is / has to be a function called showName.
If you are going to pass data forwards you do not have to use delegation since you know where you are going to pass the data to. But if you wan to pass data back you normally dont know where you came from -> second controller does not know and should not know he was presented by first view controller. He should work the same way no matter from where he got presented. And whoever feels responsible for him can and should assign himself as delegate which gets informed of changes or callbacks or whatever.
The subclassing you mention is basically that, but you can only subclass once, therefore if you want your class to be the delegate for a TableView, a CollectionView and your CustomView, you are going to have a bad time with only subclassing. What you are going to have to use is delegation via protocols
in my app I want to use googleAnalytics. To use it I have to extend GAITrackedViewController but the problem is I already extend GLKViewController because my view has an openGL application. So is it possible to extend the properties of both view controllers?
For a similar case, I've simply created a subclass of UIViewController (GLKViewController in your case). That subclass handles the tracking of the view. All "specific" ViewControllers extend that custom UIViewController, instead of the default one.
Then you could, for instance, track the view manually:
id<GAITracker> tracker = [[GAI sharedInstance] defaultTracker];
[tracker sendView: NSStringFromClass(self.class)];
No, there isn't multiple inheritance in Objective-C. You have write a subclass of GAITrackedViewController and a subclass of GLKViewController separately, and write a controller class that has an instance of these two classes, coordinating them.
It's not possible, objective-C doesn't support multiple inheritance. You should take a look to this question: Objective-C multiple inheritance
it is very bad to extend 2 classes even on languages that allow it,
because you can get 2 ways to your "super" and this is a way to many bugs
In the project i am currently working upon, there are lots and lots of UIViewController objects (of some UIViewController subclass) are created and used. And believe me it was creating lots of issues. And I am working upon it (kind of refactoring).
As I see, most of the (those)objects required initialization only once and used multiple times. As I will be working on this project from now (and also the project is of long duration), How can I be sure that each of the UIViewController Subclass object is only one alive at a time.
I doubt if I should make all the UIViewControllers Singleton. And if so, How should I implement that. Meaning; Should I initialize all the objects in applicationDidFinishedLaunching:WithOptions or where?
Another Question is: (As I think might not be true) Should all the UIViewController in project be singleton?
If you want to ensure that all the UIViewController objects in the project are being created only once then only way is Singleton. And you need not to intialize them in applicationDidFinishLaunching. You can intialize them any where(usually where you need them).
Go to link for creating singleton properly: http://cocoasamurai.blogspot.in/2011/04/singletons-your-doing-them-wrong.html
Source : Make UIViewController a singleton?
Well making them singleton if you want them to be only one object of each subclass is not a bad idea,
if you made them singletons, don't initialize them in applicationDidFinishedLaunching:WithOptions but initialize them as soon as you need them (read more about lazy initialization)
However i would suggest to make each webView a property of your Appdelegate, such that whenever you need them you will get them from the appDelegate
Since I started developing my app, some of my view controllers have grown and now I have a lot of code in them. I'm just wondering if I could create some kind of subclass which would inherit instance variables, so I could move out some of the code.
I'm guessing this won't be possible, without creating a new class with properties, which I'll have to provide with values.
Is there anything neat I could do to save some time ?
This is a pretty tricky and touchy subject with Objective-C coders. In general, this type of repletion is expected. You don't have any specifics in your question, but if you're only repeating some basic view setup code, that's not really an issue.
In general, creating a "base" UIViewController subclass is not common. If you're adding logic to your view controllers that's very common, like setting up a special navigation button, then you can use a category.
Basically, in Objective-C, a category can be used to add a certain behaviour to all instances of some class. In the example I linked to, they add some functions to the string class. Take a look at what you're repeating and see if a category would be a better approach to subclassing.
Can any one differentiate when do we use Delegation over category and vice versa. I am clear over this.
Thanks
Category allows to add new methods or overwrite existing methods on a class, thus allows to extend a class without subclassing. Adding methods is the most useful aim, overwriting can go really wrong if you do not know exactly what the class being extended does.
It is more a language feature not a pattern, it works on each class.
Delegate is a pattern not a language feature, the class that is supposed to used must be coded for it, otherwise it won't work.
Usually a delegate will be required to implement a protocol known by the class that is going to receive the delegate. The class will then use the delegate to do stuff it was coded for, some of the most common are sending notifications, using a part of a strategy pattern, that is asking question in certain part of code to make decisions based on the concrete delegate's implementation, letting delegate execute an action or any combination of them.
For example UIApplicationDelegate is a notification (application:didFinishLaunchingWithOptions:) and action (application:openURL:sourceApplication:annotation:) protocol, UITextFieldDelegate is notification (textFieldDidBeginEditing:) and strategy (textField:shouldChangeCharactersInRange:replacementString:).
Actually I can imagine using category to implement delegating in all this cases I stated above: sending notifications, doing actions, taking part in a strategy. But it would require you to very very good know what to extended class is doing, probably to have it code, otherwise you can very easily break the class or be broken by changed class implementation. So this usage would be in my opinion highly wrong.
category: Adds methods to an existing class.
delegate: Modifies behavior of another object by allowing some other object, the delegate, to participate in the object's operation.
Say you've got an iOS application with three tables. Even though they're configured the same way, those tables each may behave differently if they have different delegates.
You can't do that with a category because a category applies equally to all instances of the class it extends. On the other hand, if you want to extend the UITableView class to add some new capability, you need a category*. Delegates are instance-specific and limited to the role envisioned for them by the designer of the delegating class.
*or a subclass, of course.
Categories are used when you need to extend the class without creating a subclass, for example when you need to add a method named isURL to the NSString you can make use of categories as follows, here we not creating a subclass, instead we are extending the implementation.
#interface NSString (Utilities)
- (BOOL) isURL;
#end
Delegates are similar to callback functions,