If two different Categories having same method, then which one will be invoked by Objective C runtime system? - objective-c

If two different Categories having same method, then which one will be invoked by objective C runtime system ??
for example:
#interface ClassA (MathOps)
-(void)CategoryMethod;
#end
#interface ClassA (MathOps1)
-(void)CategoryMethod;
#end
#implementation ClassA(MathOps1)
- (void) CategoryMethod{
NSLog(#"Inside Category Method 2");
}
#end
#implementation ClassA(MathOps)
- (void) CategoryMethod{
NSLog(#"Inside Category Method 1");
}
#end
Now if i am calling, [ObjClassA CategoryMethod];, Then which one called ? Why ?

It's undefined. It depends on which category gets loaded first by the runtime, are there's no documented order in which that happens.
Bottom line: don't do this. :)

As #Dave DeLong states, the behavior is undefined. One of the methods will "win", and there's just no way to know which one. If any other code depends on the loosing method, you'll find yourself debugging some potentially weird errors. Best to avoid the situation all together. This is a particular problem when implementing "obvious" helper methods. If those methods get added in a future framework version, your category will either override the new method in the class (if it's in the main class body) or may override the method if its added in a category. Eek.
Many Cocoa frameworks that provide categories for existing (e.g. Cocoa) classes follow a pattern whereby they prepend their class prefix to the method in order to minimize the chance of name collision. So, for example, you would create categories like:
#interface NSObject (MyCategory)
- (void)myprefix_categoryMethod;
#end

Related

Objective-C : Accessing fields in implementation

Is it possible to fields defined only in implementation but not in interface definition ?
#interface MyInterface .... #end --> dict not defined here!!!
#implementation MyInterface
...
NSDictionary *dict;
...
#end
In this case if somewhere I somehow accessed to this class, can I access to the dict or should I create a getter just like in Java ?
Edit after #Rob's answer
Thanks for the answer Rob, I wish I have the implementation of these interface and classes. Instead I am trying to bind two different libraries ( I know it is reallllly bad as architectural point of view but this is where I end up).
Basically, I am in react-native world. And we are using react-native-video as our player layer. But since AVPlayer does not support some subtitle types our head company sent us a library that needs a player instance and a view instance to draw subtitle on the view. I believe they will bind to events of the player and draw sub titles based on player states.
So react-native-video is in this github repo with the interface and implementation.
I find the UIView that includes the properties and casted it to the object itself RTCVideo in this case). But now I am stuck. I can go and change some stuff as per your suggestion in the "Development Pods" to be able to access but this is my last bullet :) I prefer to convince these two libraries in a friendly way :)
Yes, but the above syntax isn't what you want. The modern way to do this is with a class extension.
Your header file is the same:
#interface MyInterface
#end
But in your .m file, you create an extension by appending ():
#interface MyInterface ()
#property (nonatomic, readwrite) NSDictionary *dict;
#end
Now, inside your .m file, you can access self.dict normally, but outside of your .m file it won't appear available.
For full details, see Programming with Objective-C: Class Extensions Extend the Internal Implementation.
The syntax you've written actually creates a static (global) variable called dict that isn't tied to any instance.
It is possible to create raw instance variables using a {...} syntax, either on the extension or on the implementation, but this isn't used that often today, except for managing raw buffers that you don't want accessors for. The syntax is either:
#interface MyInterface () {
NSDictionary *_dict;
}
...
#end
or on the implementation:
#implementation MyInterface {
NSDictionary *_dict;
}
...
#end
But I recommend simple extensions with properties any time you can. And if you are considering creating an accessor for it, you definitely want to use #property and let the system do it for you.
If I understand your edits correctly, you're trying to read the internal ivars of an object that doesn't expose them with an accessor, correct? I believe specifically you want to access _player.
There's several common ways to do that. The key feature you want is Key-Value Coding.
The simplest approach for this problem is -valueForKey:
AVPlayer *player = [view valueForKey:#"player"];
The first thing -valueForKey: looks for is _<key>, and if it's just an object pointer (as in this case), it just returns it.
(This can be broken if a class return false for +accessInstanceVariablesDirectly, but the default is true, and it's unusual to override this.)
Another very common approach is to just declare any methods you know exist as a category. (This won't work for _player, since it's not a method, but in case you need similar things.) Imagine you wanted to call the "private" method -removePlayerTimeObserver. In your .m file, just say you know about it using a category:
#interface RCTVideo (PrivateMethods)
- (void)removePlayerTimeObserver;
#end
And since you know about it, you can call it:
[video removePlayerTimeObserver];
If you're wrong, and that method doesn't really exist, then the program will crash. In Objective-C, almost all rules are advisory. You can break them if you want to. ObjC programmers tend to be big rule-followers because otherwise the program crashes and ObjC has very clear rules that are pretty easy to follow. It's not because the system forces us to.

Do delegate methods inherit from method in protocol class?

In a category I got from a book, there is a protocol specified. It requires one method and declares that method in the category as well.
If I implement the protocol in another object (a table view cell), my understanding is that I MUST include the required method. However, other than the title of the method being the same as the one in the category, do I inherit any of the code from the category version? That code is meaningful because only after that code completes do I want to do something.
category: .m
#protocol DownloadHelperDelegate <NSObject>
-(void)didCompleteDownloadForURL:(NSString *)url withData:(NSMutableData *)data;
#end
- (void)didCompleteDownloadForURL:(NSString *)url withData:(NSMutableData *)data{
// doThis
// doThat
// readyToDoSomethingElsewhere
}
In tableviewCell: .h
#import "category.h";
#protocol category
.m
-(void)didCompleteDownloadForURL:url withData:data;
{
// Did doThis happen?
// Did doThat happen?
// If so, I want to do Something
}
Since the category is a category on UIImageView, it only adds methods to that class.
Since your class is derived from UITableViewCell and that does not derive, directly or indirectly, from UIImageView, it does not inherit an implementation of -didCompleteDownloadForURL:withData: from the category.
I'm guessing the category's method would not be an appropriate implementation of the protocol method, anyway. It has the same signature, but I suspect it has a different purpose. In particular, I suspect the category method's purpose is, at least in part, to forward the call along to a delegate which implements the protocol. So, it wouldn't make sense for the delegate itself to inherit that implementation.
It's just a coincidence that the category method and the protocol method have the same signature. In fact, I would suggest that the category method be changed to start with a unique prefix so that there's no chance that it collides with a method on UIImageView, which might be private to Apple or added in a future version of UIKit.

Can we not declare methods in the header files?

I am watching the Stanford University iPad and iPhone application Developments course video. The instructor says in the video we can control-drag an UI object to the implementation files to create an action. But in this way the method will not declare in the header file. Does this mean it is ok to implement methods in the .m file but not declare in the .h file?
Depends on how you define "ok" :-)
Objective-C uses dynamic method lookup and does not really enforce access ("private", "public", etc.) specifiers. So you don't need to declare any method in a header file.
However you will end up fighting the compiler as it does do a fair amount of type-checking unless you persuade it not to, and you'll lose by doing so.
You are not required to declare in the header file all methods in the implementation. But if not in the header file obviously you cannot reference them by literal name in another file, nor can you "forward reference" them in the implementation file.
(Note that this is not that different from regular C, but is different from methods of a class in C++.)
It's "OK" to not declare methods in the header yes, under certain circumstances. For instance, if using ARC then the compiler generally needs to know the method signature so it can do the right thing. But basically all it means is that wherever you're using the method, it must already know about the method you're calling.
Since you're talking about Interface Builder, that's slightly different in that it will know about all methods since it can "see" the whole context of your header and implementation files and know that a method exists. i.e. in my terminology above, the method has been defined before it's used.
With regard to defining before use, the general accepted approach is to either:
Define a method in the interface file (.h). e.g.:
MyClass.h
#interface MyClass : NSObject
- (void)someMethod;
#end
MyClass.m
#implementation MyClass
- (void)someMethod {
// do something
}
#end
Define a method in a class continuation category. e.g.:
MyClass.h
#interface MyClass : NSObject
#end
MyClass.m
#interface MyClass ()
- (void)someMethod;
#end
#implementation MyClass
- (void)someMethod {
// do something
}
#end

What's the difference between adding pseudo-private ivars in a class extension or in the #implementation block?

What's the difference between putting pseudo-private instance variables in a class extension inside the .m file, or putting them in the newly introduced #implementation brackets like shown below?
Are there consequences, pros, cons over one or the other way? Is internal2 treated differently than internal3 in a way a programmer must care of? (of course there is a difference McKay would say but the question is if you care in practice or not).
// MyClass.m
#interface MyClass () {
id internal2;
}
#end
#implementation MyClass {
id internal3;
}
- (void)internalMethod {
NSLog(#"%# %#", internal2, internal3);
}
#end
source: http://www.mcubedsw.com/blog/index.php/site/comments/new_objective-c_features/
The main difference between the two approaches is that you can include the class extension in a separate header, whereas the #implementation ivars obviously have to go with the #implementation block in the .m file (and there can only be one #implementation for a given class (extensions not included)). The practical result of this is that you can have multiple levels of "private" ivars:
MyClass.h: public ivars
MyClass+Private.h: semi-private ivars
MyClass.m: really private ivars
As a hypothetical example, pretend that MyClass is UIView. In that case, UIView.h is the header that we can all access, UIView+Private.h is the "private" header than only Apple can access, and UIView.m has stuff that only the people specifically responsible for UIView need to know about.
Personally, I prefer to put my ivars in a single class extension in the implementation file, I think it's cleaner that way. I don't think there are any performance advantages or consequences to using one or the other, it's more about being able to code the way you want to.

How do I define a category that adds methods to classes which implement a particular protocol?

I want to add some methods to subclasses of NSManagedObject that implement the SOManagedObject protocol. I've tried defining it like this:
#interface NSManagedObject <SOManagedObject> (MyExtensionMethods)
...
#end
...but that doesn't seem to be valid. How do I define a category that adds methods to classes which implement a particular protocol?
Defining such a category on all such classes in general is not easily solvable. But your actual problem seems simpler: How does one add a category method to NSManagedObject for use only with subclasses that implement <SOManagedObject>? This is solvable.
What you want to do is add the method to NSManagedObject, then check that the instance you're working with can handle the messages you want to send it from <SOManagedObject>.
Let us suppose that we are given:
/* SOManagedObject.h */
#protocol SOManagedObject
- (void)frobble_so;
- (void)bobble_so;
#end
Now let's add a category method to all NSManagedObject subclasses that implement SOManagedObject:
/* NSManagedObject+SOConvenience.h */
#interface NSManagedObject (SOConvience)
/* Frobbles and bobbles - no effect on non-<SOManagedObject>-conforming
* instances. */
- (void)frobbleAndBobble_so;
#end
To do so, we implement the method like so:
/* NSManagedObject+SOConvenience.m */
#implementation NSManagedObject (SOConvenience)
- (void)frobbleAndBobble_so
{
if (![self conformsToProtocol:#protocol(SOManagedObject)]) return;
NSLog(#"%s: Thunderbirds are GO! Let's frobble and bobble!", __func__);
[self frobble_so];
[self bobble_so];
}
#end
You could optionally assert to ensure you are not sending the method to the wrong objects, or you could use respondsToSelector: instead of checking for protocol conformance. Whatever floats your boat, but this general tack should take you where you want to go.
I don't think it is possible. A similar question to this was answered earlier:
Defining categories for protocols in Objective-C?
Edit: I misread the question; I don't think it's possible to do what you're trying to do without messing with the Objective-C runtime. See Dave's comment below for why my answer is incorrect.
You should be able to do this if you swap the protocol and category notation like so:
#interface NSManagedObject (MyExtensionMethods) <SOManagedObject>
...
#end
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
Defining the methods you want to add as #optional on a protocol.
Making the objects you want to extend conform to that protocol.
Copying those methods into those objects at runtime.
Check out the link for the full details.