How should CategoryA override categoryB method - ios

In AFNetworking 2.0, in UIImageView+AFNetworking there is a method:
+ (id <AFImageCache>)sharedImageCache
I want to override it and return here my custom object. I'd like also to override all the methods in AFImageCache, so basically I'd make a new protocol here. I've thought about method swizzling, however because lack of experience I'm not sure if it works ok with 2 categories. What if my category loads before AFNetworking category, will it still be working?
At all, is this approach a good one? I want to add disc caching to the memory one and I wonder which way is the cleanest one in terms of code quality.

Do not use Categories to override a method. Per the documentation
"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. "
refer to the documentation at "Avoid Category Method Name Clashes" -->
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/ProgrammingWithObjectiveC.pdf
Subclass and override the method instead and use the subclass?
Analyzing your scenario, It make sense to do method swizzling.
Note: Make sure yourCache will behave the same way as sharedImageCache, else it will result in crash.
#implementation UIImageView (Swizzling)
+ (void)load {
static dispatch_once_t token;
dispatch_once(&token, ^{
Class myClass = [self class];
Method originalMethod = class_getInstanceMethod(myClass, #selector(sharedImageCache));
Method newMethod = class_getInstanceMethod(myClass, #selector(NewSharedImageCache:));
method_exchangeImplementations(originalMethod, newMethod);
});
}
//This is just for sample. you can create your buffer in your own way
static id <yourCache> yourBuffer;
+ (id <yourCache>)NewSharedImageCache
{
return yourBuffer;
}
#end

Related

Objective-C and the self keyword [duplicate]

What does self mean in Objective-C? When and where should I use it?
Is it similar to this in Java?
self refers to the instance of the current class that you are working in, and yes, it is analagous to this in Java.
You use it if you want to perform an operation on the current instance of that class. For example, if you are writing an instance method on a class, and you want to call a method on that same instance to do something or retrieve some data, you would use self:
int value = [self returnSomeInteger];
This is also often used for accessor methods on an instance (i.e. setters and getters) especially with setter methods, if they implement extra functionality rather than just setting the value of an instance variable, so that you do not have to repeat that code over and over when you want to set the value of that variable, for example:
[self setSomeVariable:newValue];
One of the most common uses of self is during initialization of a class. Sample code might look like:
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
This invokes the superclass's (via super) initializer, which is how chained initialization occurs up the class hierarchy. The returned value is then set to self, however, because the superclass's initializer could return a different object than the superclass.
self is an implied argument to all Obj-C methods that contains a pointer to the current object in instance methods, and a pointer to the current class in class methods.
Another implied argument is _cmd, which is the selector that was sent to the method.
Please be aware that you only get self and _cmd in Obj-C methods. If you declare a C(++) method, for instance as a callback from some C library, you won't get self or cmd.
For more information, see the Using Hidden Arguments section of the Objective-C Runtime Programming guide.
Yes, it's exactly the same as "this" in Java - it points to the "current" object.
Two important notes:
The class itself, e.g. UIView (I'm NOT talking about a UIView object) is itself an object, and there is a self associated with it. So for example, you can reference self in a class method like this:
// This works
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Class method!
+(void) makeTheMostOfYourself { }
Note that the compiler does NOT raise any warnings or errors, even if the self you mean to reference is an object and not a class. It is VERY easy to cause crashes this way, for example:
// This will crash!
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Object method!
-(void) makeTheMostOfYourself { }
// This will crash too!
-(void) showYourself2 { [self performSelector: #selector(makeTheMostOfYourself2)]; }
// Class method!
+(void) makeTheMostOfYourself2 { }
Sadly, this makes class methods a bit harder to use, which is unfortunate because they are a valuable tool for encapsulation through information hiding. Just be careful.
Wow, that many half-correct answers and misleading hints. This let me answer the Q even there is a accepted answer for years:
First of all: It is really hard to compare a concept of messaging/calling in the context of an early binding, static typing language as Java with a late binding, dynamically typing languages as Objective-C. At one point this will break. I would say: No, this is not similiar, since the typing and dispatching concepts of both language are fundamental different so nothing can be similar to the other one. However, …
Then we should differ between the "two sides" of self.
A. Using self
When you use it in a message, it is simply an object reference as any other:
[self doSomething];
[anotherObject doSomething];
Technically both lines works identically (accept of having a different receiver, of course). This especially means, that the first line does not lead to an execution of a method inside the class of self, because self does not necessarily refer to "that class". As every message inside Objective-C (single exception: messages to super)this can lead to the execution of a method in a subclass:
#interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
#end
#implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
- (void)doAnotherThing
{
NSLog( #"B" );
}
In a code like this
B *b = [B new;]
[b doSomething];
The line
[self doAnotherThing];
in class A will lead to the execution of -doAnotherThing (B), because messages to self are late bound as every other message. The result on the console will b "B", not "A". Using self as a receiver you should not think of a single special rule. There is completely none.
(And the above example is a very good example for using self in class methods, because the same situation can occur on class methods. Using the class itself breaks polymorphism, what is one of the worst idea at all in OOP. DO use self in class methods, too.)
B. Getting self
What is self pointing to? It points to the object to whom the message is sent that caused the execution of the current method.
Having …
…[someObject doSomething]… // some object is a reference to an instance object
… as a message, a method is called, in the most simple case …
- (void)doSomething
{ … }
In such a case, self can point to an instance of the class, the method belongs to. And it can point to an instance of a subclass, the method belongs to, too. You don't know. (And this information is preserved using self to send a message as explained above.)
If the message is sent to a class object, self points to the class object, that was the receiver of the message. This is completely analogous. Therefore it is possible that self points to a subclass object:
#interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
#end
#implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
+ (void)doAnotherThing
{
NSLog( #"B" );
}
Having this classes
…[A doSomething]…
self inside -doSomething (A) points to the class object of B. Therefore [self doAnotherThing] of B(!) is executed. This is clearly different from
+ (void)doSomething
{
[A doAntoherThing];
}
The latter version causes relevant harm to the principles of OOP.
As a side note it is possible that self inside a class method of a root class points to an instance object of the root class or any subclass. You have to keep this in mind, when writing categories on NSObject.
self is an object pointer to the current instances dispatch table. It is an implicit first argument to every member function of an object, and is assigned when that function is called.
In functions like init, you need to be careful that when you call the super class init you reassign self to be the return value as the super class init may redefine what self points to.
super is similar to self except it points to the superclass dispatch table.

Override UIColor's isEqual: method within Category

I am trying to override the UIColor isEqual: method. I am doing so within a category method, however it does not seem to get called, either from NSArray's containsObject:, or even when called directly, as shown below.
It has been exposed as a method in the category's header file and I have also checked that the category has been imported to the implementation file I am working on.
Where it is being called directly:
UIColor *col = [UIColor eightBitColorWithRed:pxl.red green:pxl.green blue:pxl.blue];
int index = -1;
for (int i = 0; i < self.colorArrayM.count; i++) {
if ([col isEqual:((UIColor*)self.colorArrayM[i])]) {
index = i;
break;
}
}
And the category methods:
-(BOOL) isEqual:(id)otherColor {
if (otherColor == self)
return YES;
if (!otherColor || ![otherColor isKindOfClass:[self class]])
return NO;
return [self isEqualToColor:otherColor];
}
-(BOOL) isEqualToColor:(UIColor*)otherColor {
if (self == otherColor)
return YES;
unsigned char r0, r1, g0, g1, b0, b1;
[self eightBitRed:&r0 green:&g0 blue:&b0];
[otherColor eightBitRed:&r1 green:&g1 blue:&b1];
return r0 == r1 && g0 == g1 && b0 == b1;
}
The short answer is that categories are not intended to override existing methods:
Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:
When a category overrides an inherited
method, the method in the category
can, as usual, invoke the inherited
implementation via a message to super.
However, if a category overrides a
method that exists in the category's
class, there is no way to invoke the
original implementation.
A category cannot reliably override methods declared in another category of the same class.
This issue is of particular significance because many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.
The very presence of some category methods may cause behavior changes across all frameworks. For example, if you override the windowWillClose: delegate method in a category on NSObject, all window delegates in your program then respond using the category method; the behavior of all your instances of NSWindow may change. Categories you add on a framework class may cause mysterious changes in behavior and lead to crashes.
You will need to swizzle the original isEqual: method to use your own implementation. There is a great NSHipster article on swizzling that should get you started.

Method signature return value "Class of type or subclass class"

When you have a signature like this:
- (UIView *)fooView;
You can return any subclass of UIView * (e.g UIScrollView)
And when you have:
- (Class)anyClass;
You can return any class (not an instance, the class itself) but is there a way to only allow classes of a certain class or subclass? E.g in psuedo code:
- ([UIView class])bazClass;
So here it should only be able to return a class UIView of any of its subclasses.
As specified by other users, you can't.
If your goal is to instruct other programmers about what to return from a method in your code (overriden or delegate method), you can:
write in the comment (of course...)
create a typedef like this
.
typedef Class ClassOfKindUIView;
-(ClassOfKindUIView)class
{
return [super class];
}
This won't block anything, but it can be a "talking method", an escamotage, to make the programmers stop and think "what is this??", then cmd-click and read the docs :-)
What you're looking for is a sort of type bound on the return type.
Unfortunately this is not possible in Objective-C, so I'm afraid you're out of luck.

How to override method of

There is a class alpha which has method -(void)doSomething. There is also a class beta which I've created and can modify as I need. Instance of alpha can only be created by calling [gamma createAlpha].
What I need is to make class beta to inherit alpha and override doSomething while I still have to create instances of alpha via calling [gamma createAlpha].
Is there any way to implement this?
I hope my question makes sense.
Thank you!
Yes. You can use method swizzling. You will need to create category with following code:
#implementation alpha (newDoSomething)
// This is called when the category is being added
+ (void) load {
Method method1 = class_getInstanceMethod(self, #selector(doSomething));
Method method2 = class_getInstanceMethod(self, #selector(swizzleddoSomething));
// this is what switches the two methods
method_exchangeImplementations(method1, method2);
}
- (void)swizzleddoSomething
{
... your code
//You can call super implementation here with following line
//[self swizzleddoSomething];
}
#end
You will still have class alpha. It will be successfully created by [gamma createAlpha], but it will have your implementation of doSomething method.

How to explicitely pass self as a super class to a method and being called back instead of subclass?

I have 3 classes
One base class : MyBaseClass
That implements a method :
- (void) aSuperMethod {
[[UtilClass sharedUtil] doThisAndSendAnswerToMe:self]
}
- (void) answerReader:(bla bla)someParams {}
One subclass of MyBaseClass : MySubClass
That also implements these kind of methods :
- (void) anotherMethod {
[[UtilClass sharedUtil] doThisAndSendAnswerToMe:self]
[self aSuperMethod];
}
- (void) answerReader:(bla bla)someParams {}
And of course a utility class : UtilClass
That implements this kind of method :
- (void) doThisAndSendAnswerToMe:(id)listener {
do some stuff
[listener answerReader:someAnswerParams];
}
In debug mode, of course, the listener received in both calls by the doThisAndSendAnswerToMe method is of MySubClass class.
How may I do to point either on MySubClass or MyBaseClass depending on the call origin ?
You can't. The subclass's method implementation always overrides the superclass implementation.
One solution is to use a different method name in the superclass and the subclass, and pass the name of the callback method to UtilClass. UtilClass then uses -[NSObject performSelector:withObject:] to call that method.
-(void)baseClassAnswerReader:(id)someAnswerParams { ... }
[[UtilClass sharedUtil] doSomethingAndSendAnswerToMe:self
selector:#selector(baseClassAnswerReader:)];
Another solution is to pass a completion block object to UtilClass. UtilClass then calls the block object when it is done.
[[UtilClass sharedUtil] doSomethingWithCompletionBlock:^(id someAnswerParams){ ... }];
You use an instance of the base class if you want to use the base class, and you use an instance of the subclass if you want to use the subclass.
If you don't want the subclass method to override the superclass one, then make it a different method instead of overriding.

Resources