Objective C: several categories on one class - ios

I must have misunderstood Categories I made a category on a class to extend it with some methods, and make some methods abstract following the OOP guidelines. But I thought that only when I #import and use the category will those methods in the category be called. Instead I find when I #import and use the base class, that this class will automatically call that method but in the Category on the class, not itself.
What I wanted was if the user tried to use this method in the class without a category a exception would get trowed. And this way I could make different categories on the same class
with slightly different internal behavior.
Am I just misunderstanding Categories ?

Categories add methods to a class without condition or other means of picking and choosing.
Once the methods are added to the class, there is no removal short of mucking with the runtime directly.
Subclasses inherit the additional methods.
It doesn't matter if you #import the method declarations or not.
If you want different versions of a class, declare different subclasses.

Related

Class Extension vs Primary Interface vs Category

I am fairly new to realm of iOS. Coming from Java and Android background i am facing few challenges while learning objective C.
My question: I understand how the above three are different from each other but I fail to understand their use cases in practice.
Do we need a Class Extension for every class with private functions? What is the use of Category, when we can extend a Cocoa/Cocoa-touch class in interface and add custom functions? Please do provide some example from your experience.
Categories are a way to split a single class definition into multiple files.A category can be declared for any class, even if you don't have the original implementation source code.At runtime, there's no difference between a method added by a category and one that is implemented by the original class.
example for categories:
NSString+UrlString.h
#import <UIKit/UIKit.h>
#interface NSString(Additions)
+(void)urlMethod;
#end
NSString+UrlString.m//implmentation
#import "NSString+Additions.h"
#implementation NSString (Additions)
+(void)urlMethod
{
}
#end
The primary interface for a class is used to define the way that other classes are expected to interact with it. In other words, it’s the public interface to the class.
Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself.
Class extensions are used to declare private methods in objective C
For example, to define a property as readonly in the interface, but as readwrite in a class extension declared above the implementation, in order that the internal methods of the class can change the property value directly.
The methods declared by a class extension are implemented in the implementation block for the original class, so you can't, for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString..
The syntax to declare a extension uses the #interface keyword, just like a standard Objective-C
#interface ClassName ()
#end
you may find that you wish to extend an existing class by adding behavior that is useful only in certain situations. Please refer this
Category is adding methods to a class in the runtime. As far as the runtime is concerned, the methods that are implemented in a class extension, ARE the methods that are available for the class itself. Category in Objective-C is a fancy name for Monkey Patching in other programming languages like C#. You can read about it here.
With that said, you can create a category for UIColor with some method if you want every UIColor to have that behaviour throughout that module. This isn't the case with subclassing. Only the subclassed (theoretically speaking) UIColor object will get those behaviour since there is a distinct difference in the type of the object.
Example:
UIColor has built in methods that give you different colors; you can call UIColor.greenColor() to get the green color; UIColor.blackColor() to get black color and so on...
Suppose you want your own to be called in a similar fashion, you create a category (example in swift) like so
extension UIColor {
static func yourColor() -> UIColor {
return UIColor(red:220/225,green:222/225,blue:223/225)
}
}
This way, it is valid for you to call UIColor.yourColor(). Every UIColor that you would use has this method available. Convenient than subclassing, isn't it?
Creating a subclass has polymorphic implications; categories don't. You subclass only when you need refinement of an existing class and treat it both as a parent and the child when required. As a Java developer you would know when it makes sense to subclass.
An extension is best for private methods which you would like to declare in your .m file. Think of extension as a category private to the .m file.
Class Extesions: If you mean by Extension Methods like in .Net, then it called as Category in Objective-C.
Categories: These are nothing but the Extension Methods, it allows to add methods in existing classes from iOS SDK (like NSString, NSURL, etc.)
For more details: Apple Doc: Category
Primary Interface: Writing a class (Interface in terms of Objective-C) definition inside its implementation file called primary interface.
//ClassName.mm #interface ClassName() {
Declarations;
}
- Methods;
+ Methods;
#end
#implementation ClassName
#end
So, Categories are also one type of primary interfaces.

Programming methods in a non ARC Xcode project

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.

What happens if I accidentally override Apple's private APIs?

Say that Apple has an API defined in a private header file:
// Can't see this at all
#interface NSThing
- (void)secretMethod;
#end
and I have a category:
#interface NSThing (Helpers)
- (void)secretMethod;
#end
Does this override Apple's implementation and will their other private methods start calling into my implementation?
From "Avoid Category Method Name Clashes":
If the name of a method declared in a category is the same as a method
in the original class, or a method in another category on the same
class (or even a superclass), the behavior is undefined as to which
method implementation is used at runtime. This is less likely to be an
issue if you’re using categories with your own classes, but can cause
problems when using categories to add methods to standard Cocoa or
Cocoa Touch classes.
So if you "accidentally" implement a category method with the same name as
an existing method (private or not), the behaviour is undefined.
You should therefore prefix your category methods with a prefix that makes
name clashes unlikely.

How to create a class which is sub class of two classes

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.

ios: Is it possible to choose one out of two defined categories of same class at runtime

I have two categories defined for the same class and have same function but different definition. I want to choose a particular function of a category at runtime on some condition.
Does obj c compiler maintain some book keeping for categories.
I was thinking in terms of C++ (virtual function/Vtable) where these can be achieved using polymorphism. How can I solve such scenario in objective C.
Class MyClass;
File:Myclass+category1.h
#interface MyClass (CategoryOne)
-(void) printCategory()
#end
File:Myclass+category2.h
#interface MyClass (CategoryTwo)
-(void) printCategory()
#end
Now I included both the header files in MyClass.m. Is there any possibility of liberty of choosing the particular definition of "printCategory()" at some runtime condition?
No. If two categories implement the same method, it is undefined which one is executed.
From the docs:
There’s no limit to the number of categories that you can add to a class, but each category name must be different, and each should declare and define a different set of methods.

Resources