I have a singleton that manages preferences which are loaded from a plist. I use it multiple apps. It contains methods like -(BOOL)boolForKey:(NSString *)key defaultValue:(BOOL)def
So I can get use the class in two different apps, just by supplying different keys, such as in one app: [PreferenceManager boolForKey:#"UseAlternateColors" defaultValue:NO];
But it would be easier to have a method like -(BOOL)useAlternateColors (which just returns the value from the above line) just in that app. So should I add this method to PreferenceManager using a category (and only have the category in the one app) or create subclass like OneAppPreferenceManager?
In this specific example, is it better to subclass or use a category?
Subclassing would have been a better option if you needed to add new data members to the derived PreferenceManager. However, since the backing storage always remains the same, I think that using a category would be preferable in this specific case.
Using a category would let your keep the singleton PreferenceManager unchanged, along with the piece of code that sets it up. If you were to subclass PreferenceManager, you would need to make an additional change to the code that instantiates the singleton, so that it uses the PreferenceManagerSubclass instead of the raw PreferenceManager. With a category, this change would be unnecessary.
Related
In Swift, I am trying to build a simple app that runs the card game war. There are two view controllers, one for normal gameplay and one in case of a tie. So, in my code, I have two different classes, one called mainScene and one called tieScene. To store which cards the player has and which cards the enemy has, I use two arrays named playerArray and enemy Array. If a tie occurs, I segue from mainScene to tieScene. How do I incorporate the information for playerArray and enemyArray from class mainScene, and use these values in class tieScene?
One thing I tried was subclassing tieScene as part of mainScene as follows:
class tieScene: mainScene {...}
This allowed me to use the playerArray and enemyArray in class tieScene. However, the option to connect tieScene to my second view controller in Interface Builder was not there when I subclassed tieScene.
So, I have two questions:
Did I subclass tieScene wrong and is that why I couldn't connect tieScene in my interface builder?
Besides subclassing, how can I use the information from one class in another class?
This is OOP 101 stuff.
Subclassing does not share information.
Cars and trucks are both motor vehicles
Sedans and coupes are both subclasses of car. Say both have a radio with a radio station property.
If I change the radio station in my sedan instance, that does not mean you can query the radio station in your coupe and find out what station I'm listening to.
Separate objects are completely separate from each other, and have their own instance variables.
You can either set up a link between your two objects and define a protocol to communicate between them, or if you want to save global app state information then maybe you need a data container singleton. See this thread I created for a discussion of the different options:
How do you share data between view controllers and other objects in Swift?
I don't think you're understanding what a subclass is.. If you're subclassing, then that just means that the child class has the same properties as the super class, so it will have the arrays but they are not persisted.
There are a couple of things you can use, the easiest would be to simply create the arrays in your tie view, then when you create a new tie view, set the arrays. Or create a method to setup the tie view with the arrays(initWithEnemyArray.....)
You should not be using subclassing like this, subclassing is not used to share information, that is a misuse of what object orientation is about. It would not work because when your program runs you will have a separate instance of type tieScene and another instance of mainScene. Therefore you will have two separate instances of the data, not one instance which is shared. You should consider making a model class and storing your data there. Read about MVC.
Regarding OOP and inheritance, make sure you understand the difference between a class and an instance of a class. You are mixed up thinking an instance and a class are the same thing, they are not.
I need to write some methods in a non ARC project in Xcode. I have to implement a NSXMutableDictionary class, a mutable dictionary that can contain up to four key-value pairs. The methods I have to implement are following:
- (void)setObject:(NSObject *)theObject forKey:(NSObject *)theKey;
- (void)removeObjectForKey:(NSObject *)theKey;
I have no clue how to do it, any help would be highly appreciated.
Thanks.
It's not a lot to go on.
But with what you provided, it's best to subclass NSObject and have a private property that is an NSMutableDictionary.
That allows you to implement all of the same methods of NSMutableDictionary just by declaring them, then in your implementation of each you just call the same method on your actual dictionary property.
The difference you add is a check to see if you already have 4 KVPs or not. And any additional methods you need or want.
This is the design pattern of Composition.
I agree with #uchuugaka. Create an object that has an NSMutableDictionary inside it. (This is a "has-a" relationship rather than an "is-a" relationship)
The NSDictionary family is what's known as a "class cluster". A class cluster is a public interface that's actually implemented by a set of private classes that you don't see.
Subclassing a class that is part of a class cluster is tricky, and not for beginners. There are a whole set of primitive methods you have to implement in order to create a subclass of a class cluster. Plus, your custom subclass will likely not preform as well as the original class because you won't adapt to different use-cases like the class cluster does.
These two questions are quite common when we search it but yet I need to get a satisfying answer about both.When ever we search a difference between say subclass and a category we actually get definition of both not the difference.I went to an interview to a very good MNC working on iOS and I was encountered with these two questions and I gave almost all the answers I have read here but the interviewer was not satisfied.He stuck to his questions and was that-
Why do we needed category when we can use a subclass?
Why we needed blocks when we can use functions?
So please explain me what specific qualities blocks and category add in objective C that their counter part can't do.
First...
Just reading the documentation "Subclassing Notes" for NSString shows why creating categories is sometimes better than subclassing.
If you wanted to add a function -(void)reverseString (for instance) to NSString then subclassing it is going to be a massive pain in comparison to categories.
Second...
Blocks are useful for capturing scope and context. They can also be passed around. So you can pass a block into an asynchronous call which then may be passed elsewhere. TBH you don't care where the block is passed or where it is finally called from. The scope captured at the time of creating the block is captured too.
Yes, you can use methods too. But they both have different uses.
Your questions are a bit odd. It's like asking...
Why do hammers exist when we can just use wrenches?
You can't use subclassing when someone else is creating the objects. For instance, NSString is returned from hundreds of system APIs, and you can't change them to return MyImprovedString.
Functions split up the logic; blocks allow you to write it closer together. Like:
[thing doSomethingAndWhenFinishedDo: ^{ some_other_thing; }];
the same code written with functions would put the second part of the logic several lines away in the file. If you have a few nested scopes in your logic then blocks can really clean it up.
Why do we needed category when we can use a subclass?
Categories let you expand the API of existing classes without changing their type. Subclassing does the same thing but introduces a new type. Additionally subclassing lets you add state.
Why we needed blocks when we can use functions?
Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed.
You can use blocks to compose function expressions that can be passed to API, optionally stored, and used by multiple threads. Blocks are particularly useful as a callback because the block carries both the code to be executed on callback and the data needed during that execution
Category : It is used if we want to add any method on a given class whose source is not known. This is basically used when we want to alter the behaviour of any Class.
For example : If we want to add a method on NSString to reverse a string we can go for categories.
Subclassing : If we want to modify state as well as behaviour of any class or override any methods to alter the behaviour of the parent class then we go for subclassing.
For example : We subclass UIView to alter its state and behaviour in our iOS code.
Reference :
When to use categories and when to use subclassing?
What is the difference between inheritance and Categories in Objective-C
We need new method but we don't need new class so we need category.
We need function but we don't need named function so we need block.
I have class called ViewController. How to make this class is a sub-class of "metaiosdkViewController" and "JWslideViewController". Help me with syntax.
i have written like this
#interface ViewController : MetaioSDKViewController,JWslideViewController
but this giving me error
objective-c doesn't support multiple inheritance,but if you want to add some extra behaviour you can achieve it through delegates..
yes objective-c doesnt support multiple inheritance but you can give one parent so
#interface ViewController : MetaioSDKViewController
and
#interface MetaioSDKViewController : JWslideViewController
this is just an idea I know you can implement well as per your need
What is it that you want to achieve with multiple inheritance?
Do you want to override methods from each of these super classes?
Note that objective c provides 2 mechanisms for extensibility:
1) Implementing a Protocol and make your object the delegate:
#interface ViewController : <MetaioSDKViewController,JWslideViewController>
This enforces ViewController to implement certain methods as defined in contract by 2 delegates, and at some point in processing, they get called. If you don't implement them, they may simply not be called but you may not get desired functionality.
Example: UITableViewDataSource protocol that defines many methods that UITableViewController subclass implements. cellForRowAtindexPath is very famous example of a delegate method that your own table view subclass must implement to draw your own custom cells.
Note that this is not the type of extensibility that subclasses provide in general sense. Your class does not extend any functionality here. Rather it becomes what it says - a delegate - someone who is assigned to do some task. Like you do:
yourTableView.delegate = self; //tell self to be the delegate of yourTableview
Library code does it's stuff and in some point in processing it calls [delegate someMethod]. If your own class implements it, it calls it, otherwise delegate will be nil, and it may just be NO-OP and you don't get desired functionality. Again, this is implementation-dependent. Maybe the protocol defines that the method is compulsory, in which case your class MUST implement this method in order to compile.
2) Implement a category:
This is sort of a shortcut way to extend library classes. They act like an extra stub which, when your code runs, attaches itself to the already existing memory layout of the library objects and provides extra functionality.
You can define a category on any of the in-built classes as well. In fact that is the primary objective it is used for. For example, here is an NSString category which provides HTML conversion. There are hundreds of categories implemented as open source and they provide enormous benefits where library code falls short. Discussing their suitability in entirety is however out of scope for this discussion.
One thing to note however is: You do not override anything using a category. Rather you are supplying something in extra. For example if you want some custom drawing across all your app views, you can define a category on UIView in your project and then all your views could simply include the category header file. You don't even have to inherit from this category, you simply inherit from the base type.
e.g. in the NSString category example above, you do not have to define your NSString to be of type NSString+HTML. Instead you just include the responsible NSString+HTML.h file wherever you want those extra methods like stringByConvertingHTMLToPlainText and so on. The changes remain limited to your project - to the files where you include this category.
Categories do not provide for extra data members - and that is something that only inheritance can provide. Yet, multiple inheritance among viewcontrollers is something you should definitely reconsider hundred times - you will see that what you are looking for is not multiple inheritance.
I got a app that uses navigation controller and tableViews and I want to create a class to do some simple storage of information that stays persistent while navigating through the different views without saving to disk.
I can either create an singleton with only class methods, but in this case I´d need to create
the collection class holding the data as an instance variable (as #properties don´t work with class methods). I only ever see objects declared in properties in iOS, so is this frowned upon?
The class would look something like this
header:
+ (BOOL) addObject: (id) object;
+ (BOOL) removeObject: (id) object;
+ (NSInteger) count;
and privately I´ll have an NSArray for storage
NSArray *cache;
But is this a good way of achieving the task? or would it be possible to have a non-singelton class with instance methods and use that same instance of the class in the different table views? if so, how would I do that?
First, ALL readwrite properties auto-synthesize instance variables (unless you implement BOTH setter AND getter).
Second, if that information is global to the entire (or most of the) App, a singleton is just what you need. You don't need to keep it as a property (or an ivar). It's a singleton, it keeps its own pointer.
If you still want to go with a property, you will have to pass it some how to every VC in your App (prepareForSegue:sender: probably if you're using storyboards).
First figure out what global information you need. Then figure out what objects you already have that have a lifetime consistent with that global information, and which are logically associated with the info. Eg, if you need an array of info to "back up" a UITableView, store the pointer to that array in the table view data source instance.
It is rarely necessary to create a "singleton", and having lots of singletons is usually a sign of poor programming.