How do I share a method between two classes? - iphone

I have an iPhone app that uses a Tab Bar Controller with 3 tabs. Each tab is a separate class. There are several methods that are identical in each class. Instead of having three copies of the same method, I'd like to share the method between the classes. However, I have not figured out how to do this.
Thanks.

This is a classical case of inheritance. Create a base class, and put all things that are common across the classes you are trying to build, into it, both functions and data members. Then, derive your three classes for your tabs from this class (inherit from it, or make it the parent class, lots of overlapping terms here that people generally throw around). Make sure your methods in the parent class are NOT defined as private methods. That would make them inaccessible to your child classes. Hope that helps!

Here you can make a new class and define that method inside that class which you want to share between more than one class.
Now whenever you want to access that method, just import the class and you can use the same method in multiple classes.
Let me know if you need more help.

Related

ViewModels talking to each other

I've just created my first c# / XAML application using mvvmlight and I've tried to implement the MVVM pattern as best I can (WP8 app). However, I've slowly morphed my code in to a certain style and I don't think its correctly implementing the pattern! Any advice on how things are supposed to be would help enormously.
For example, using mvvmlight I am making heavy use of the ViewModelLocator. Some of my viewmodels get created right away, like the SettingsViewModel (there is a SettingsView).
SimpleIoc.Default.Register<SettingsViewModel>(true);
And then elsewhere in my project, my other viewmodels will directly access this viewmodel for occasional information via a property or a method... like this;
mySetting = ViewModelLocator.SettingsStatic.GetSomeSetting(var);
My concern is that my viewmodels are talking to each other in this way more and more. The issue with this is that they probably can't be tested independently now because they require or assume the existence of other viewmodels.
Any pointers here would be great!
EDIT: Another example is having a PersonView, and the PersonViewModel has some helper methods for UI display. In some cases I have other views that need to display this info.... and I use the viewmodellocator to get to them, rather than writing the helper methods again in the current viewmodel.
You are right in thinking that viewmodels being dependent on viewmodels is going to cause trouble. When I need to have access to "global" settings in my app, I use an interface that can be injected in the constructor of the view model. So, You can create an ISettingsService that contains the properties and methods you need. You also create a design time setting service that mimics or fakes the data/properties of the ISettingsService Interface
then in your view model locator you use this:
if (ViewModelBase.IsInDesignModeStatic) {
SimpleIoc.Default.Register<ISettingsService, DesignSettingService>();
} else {
SimpleIoc.Default.Register<ISettingService, SettingService>();
}
Create the DesignSettingService and SettingService which both implement the ISettingsService.
As for you vewmodels, the SimpleIOC will resolve/inject the required elements passed into the constructor of the class. If you have a class/viewmodel called MyViewModel and it wanted to use the settingsservice then you would define the constructor like this:
private ISettingsService _SettingsAccess;
public New(ISettingsService SettingsService)
{
_SettingsAccess = SettingsService;
SettingProperty= _SettingsAccess.GetProperty;
}
This keeps the viewmodels decoupled as this service is resolved in the constructor, that way you can change the implementation of your ISettingsService without breaking every viewmodel that uses it.
I use a INavigationService to handle all the navigation events in my app, this allows me to cancel navigation based on another viewmodels properties without needing the other viewmodel to be directly called/referenced by the current one.
One view model should never directly call another view model. Using this method you can pass as many "services" as are needed to the viewmodel. Every viewmodel I use gets a dataservice that connects to my model in addition to the navigationservice. Ie. A viewmodel that deals with people gets an IPeopleDataService where this service contains all the CRUD operations that affect the database. That way I can change the people objects in the database and service functions without having to change the people viewmodel as well.
I hope this helps.

Using Objective-C category to avoid compilation error

I did something a little bit nasty today.
All of our view controllers inherit from two different parent view controllers, let's say XXXViewController and YYYViewController. XXXViewController in turn inherits from TrackedUIViewController, which is a class provided in the Google Analytics SDK so all your view controllers can inherit from it and easily track them.
YYYViewController however, inherits from a different type of view controller. Ah, and it's an open sourced piece of code that I really don't want to change.
What's the problem here? We cannot track any of the YYYViewController children because we can't access the methods provided in TrackedViewController, since they are private.
I don't want to modify the source provided in the Google Analytics SDK. So what did I do? Create a category that exposes those methods, just to avoid the compilation error.
The obvious downside to this is that the GA source code changes it may break, but it will be fairly easy to detect.
I was wondering what other problems I could be facing by doing this, and if you guys can think of a better approach.
Thank you
You can go up in the inheritance chain of YYYViewController, see in turn what class it inherits from. If it's UIViewController, simply change that particular superclass to TrackedUIViewController in the source and you're fine to go.
Example for better understanding: suppose YYYViewController inherits from ZZZViewController, which in turn inherits from UIViewController. Now you can change the superclass of ZZZViewController from UIViewController to TrackedUIViewController - since TrackedUIViewController inherits from UIViewController, no functionality will be lost, but magically your whole YYYViewController class will become trackable.
Hope this helps :-)
You already mentioned the biggest risk of using undocumented APIs: Changes to the API are beyond your control and may break your logic, for example if methods are removed/renamed, or their behavior stops matching your expectations.
From the purely technical point of view, I can see no further problems, since in Objective-C all methods are public. As long as they continue to exist, you may continue to call them.
I would say the root problem is excessive subclassing. Keep view controller hierarchies shallow. Use composition instead of subclassing. If you must subclass ensure that functionality that a class provides can be turned on & off by it's subclasses.

Dynamic include classes OR Instantiate objects without including class

Basically I have a load of classes which are all subviews of UIView.
The app is a (sort of) slideshow application. I want to be able to make lists of potential "routes" that the slides could take in plists.
As such I may have 100s of classes and I don't want to have to include all of them in the potential that I may use one of them once.
So is there a way around this? Can I instantiate a class without including it somehow?
Or am I going to have to include every potential class I'm going to use?
Is there a "global include" like include all... clutching at straws here. :p
Thanks
Tom
Why would you have hundreds of classes? It sounds like you have roughly one custom class, which would represent a slide.
Your comment on the question helps. Consider separating the slide from its content. You could have a single slide class which provides the functionality common to all slides, including the ability to manage one or more content objects. Then you'd create a bunch of different content classes: spreadsheet, animatable graph, checklist, whatever. A slide would look at its data to figure out which content class to instantiate.
If you have a common base class for all your content classes, the slide class only needs to know about the base class. The content base class could act as the manager for all the content classes. You could give it a factory method like -contentForData:(NSData*)data that returns an appropriate content object for the given data. The slide class doesn't need to know about anything more than the content base class then, so this sort of accomplishes your goal of instantiating your content classes without having to include all their headers in your slide class. The content base class would, of course, still have to know about all the content classes.
It gets a little tricky with the base class needing to know about its subclasses but the subclasses being derived from the base class. I think you can get around this by using a forward #class declaration in the content subclasses.
If you're using the class, you must know what set of messages it responds to. Factor out that information into either a common superclass or a protocol, and then you only need to use that.
Can I instantiate a class without including it somehow?
I guess this is not possible because compiler should definitely see class definition in the current scope before using a variable of class type.
IF I understand your question correctly, you want a single place to put your #include directives so that every class in your project has access to them. You can do this in the ProjectName_Prefix.pch file. Any #include or #import statements there will be included in every source code file.

Adding Extra method to interface

I have a tricky question on interface. Please try to give me a solution for it.
Scenario:
I have written an interface with five methods. Also I have implemented more than 100 classes using this interface. Now, I need to add one more method to the interface. Consequently, I will need to define the same method in all classes. How can I avoid this???
Please reply...
Thanks,
Akif
Could you avoid adding a method to the interface by instead creating a new interface which inherits from that first interface and then only changing the classes you need that new method on? Hence, if foo didn't need the new method, leave it alone but if bar did, change it to the new interface.
Java 8 has default method which you could add to an interface
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
All the subclasses which do not override this method will resort to the default implementation in the interface

Is it possible to share code betwee classes that does not have the same parent?

I have two classes that are already subclasses of a different parent (due to an external library I cannot change this). However I want to share some common code between them, say for example, code that handles an action after a popup dialog etc. How do I do this?
Refactor the shared code into its own class, and include an instance of that class as a field/property within your other two classes.
You can re-factor the appropriate code into a utilities class, and then have the two classes call it. As for the iPhoneSDK, you can probably have the utility method be the delegate method itself.
You could write a category on a common ancestor class. Then both classes could import that Category and call the common code.