Finding out isMemberOf equivalent with Objc run-time Class type - objective-c

When I have a reference to Objc run-time's Class type, how can I find out if this class refers to an NSObject?
Class aClass = [NSArray class];
Class aSuperClass = class_getSuperclass(aClass); // Points to NSObject
// What's the best way to test at runtime whether aSuperClass is pointing
// to an NSObject type?
BOOL isNSObjectClass = [aSuperClass isMemberOfClass:[NSObject class]]; // This returns NO

You're confusing classes and metaclasses.
Boiling it down, this:
[[NSObject class] isMemberOfClass:[NSObject class]]
... correctly returns NO because the metaclass that contains information about NSObject is not itself an instance of NSObject. Conversely, this:
[[NSObject new] isMemberOfClass:[NSObject class]]
... would return YES because you've created an instance of NSObject rather than inspecting the metaclass. The metaclass descends from NSObject but is not itself an instance of NSObject.
So what exactly is it that you're trying to test? Whether a class descends from NSObject, without having an instance of that class? If so you probably need manually to walk the isa chain. E.g.
- (BOOL)class:(Class)someClass isSubclassOf:(Class)class
{
while(someClass)
{
if(someClass == class) break;
someClass = class_getSuperclass(someClass);
}
return !!someClass;
}
You should see:
[self class:[NSObject class] isSubclassOf:[NSObject class]] // YES
[self class:[NSProxy class] isSubclassOf:[NSObject class]] // NO
If you don't mind the namespace implications, possibly even:
#interface NSObject (ObjectIndicator)
#end
#implementation NSObject (ObjectIndicator)
+ (void)someOldMethodOrOther {};
#end
And then:
[NSProxy respondsToSelector:#selector(someOldMethodOrOther)];

You can compare the Class instances:
BOOL isNSObjectClass = aSuperClass == [NSObject class];

Related

Where exactly does the "description" method get overriden?

The description method is a class method of the NSObject class. I guess it's a class method, because NSObject cannot be initialized.
When I do this:
NSLog(#"%#", [NSObject description]);
It prints out:
NSObject
But when I create a class that directly inherits from NSObject, and do this:
MyNewClass *obj = [[MyNewClass alloc] init];
NSLog(#"%#", obj);
This prints out something like:
<MyNewClass: 0x4b234a0>
I didn't specifically override the description method, how did it get overriden by my new class?
That is because NSObject has two methods:
+ (NSString *)description; // Class method
- (NSString *)description; // Instance method
Former is defined in NSObject class and later one in in NSObject Protocol.

Converting a String to a "Method" - To be used in a Class Method call

I'm familiar with NSSelectorFromString function with which we can create a new SEL from a string.
The problem is that I cannot use it to perform a Class Method call since the performSelector method works only with instances as its receiver.
I need something that may function like this:
NSString* colorName = colorsArray[num];
NSString* methodName = [NSString stringWithFormat:#"%#Color", colorName]; //will create blueColor or redColor, etc...
SEL colorMethod = NSSelectorFromString(methodName);
self.view.backgroundColor = [UIColor performSelector:colorMethod]; //this is not valid... since NSObject only has performSelector as an Instance method...
Is there another way to hold an on-the-run variable representing a Method that can function as a Class Method and can be created from an NSString?
Or a way to message a Class with a selector?
The problem is that I cannot use it to perform a Class Method call
since the performSelector method works only with instances as its
receiver.
This is wrong. What makes you think that the UIColor class object is not an "instance"? Class objects are objects, which means they are "instances" of some class. Class objects are instances of (some subclass of) their root class, which in the case of UIColor is NSObject. (In other words, the UIColor class objects is also an NSObject and supports all NSObject instance methods.)
If you want to understand how this works, every class object is an instance of a metaclass. Every class has its own metaclass, and metaclasses have inheritance following their classes (i.e. if A is superclass of B, then A's metaclass is superclass of B's metaclass). At the end, the metaclass of the root class inherits from the root class itself (so NSObject's metaclass inherits from NSObject). What this means is that class methods are inherited, and furthermore that the root class (in this case NSObject)'s instance methods are inherited as class methods by all classes with that root class.
just call performSelector on the class
#import <Foundation/Foundation.h>
#interface T : NSObject
+ (NSString*)foo;
+ (NSString*)redColor;
#end
#implementation T
+ (NSString*)foo {
return #"bar";
}
+ (NSString*)redColor {
return #"RED";
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
id tclass = [T class];
NSLog(#"%#", [tclass performSelector:#selector(foo)]);
NSLog(#"%#", [tclass performSelector:#selector(redColor)]);
SEL sel = NSSelectorFromString(#"redColor");
NSLog(#"%#", [tclass performSelector:sel]);
}
}
You can also use NSInvocation:
SEL sel = NSSelectorFromString(#"whiteColor");
NSMethodSignature *sig = [UIColor methodSignatureForSelector:sel];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setSelector:sel];
[invocation setTarget:[UIColor class]];
CFTypeRef retVal;
[invocation invoke];
[invocation getReturnValue:&retVal];
NSLog(#"retVal: %#", retVal);
From Cocoa Fundamentals Guide (obsolete but this part is still valid):
The runtime system treats methods defined in the root class in a
special way. Instance methods defined in a root class can be performed
both by instances and by class objects. Therefore, all class objects
have access to the instance methods defined in the root class.
The Foundation framework provides two root classes: NSObject and NSProxy. NSObject has a method documented as – performSelector:, but because it is a root class, any subclass is able to use it as a class method. For example: both +[UIColor performSelector:] and -[UIColor performSelector:] work. The explanation at a runtime level is in newacct's answer.
One calls the class method and the other calls the instance method. Example:
#import <Foundation/Foundation.h>
#interface A : NSObject
#end
#implementation A
+(void) x { NSLog(#"class method"); }
-(void) x { NSLog(#"instance method"); }
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
[A performSelector:#selector(x)];
[[A new] performSelector:#selector(x)];
}
}
Prints
class method
instance method

Objective-C: What is the difference between + and - in getters and setters?

What is the difference of using:
+ (id) myMethod;
// Rather than
- (id) myMethod;
Using a + declares the method as a class method, or a method that can be called directly on the class, where the class is the object. So when you have this:
#implementation Foo
+(NSString*)method1 {
return #"Foo";
}
-(NSString*)method2 {
return #"Foo";
}
#end
The methods are called in different ways:
[Foo method1]; //=> #"Foo"
Foo* f=[[Foo alloc] init];
[f method2]; //=> #"Foo"
One other thing to note is that class methods don't have access to an instance, which means they can't access any kind of instance variables.
#Linuxios pretty much summed up the concept of class and instance method. However, since you mentioned getters and setters in your title, I want to point out that in Objective-C you can use properties instead of writing your own accessor methods. For example,
In the header file, you will have something like this:
#interface MyObject : NSObject
#property (nonatomic,retain) NSSet* mySet;
#end
In the m file, you wil have something like this:
#implement MyObject
#synthesize mySet;
#end
To access the set in another class you can do it like this:
myObject.mySet; // assuming myObject is an instance of the MyObject class
The top one is a class method (no instance required)
The second one is a instance variable (attached to a specific instance).
This answer explains the methods quite well:
Method Syntax in Objective C
[MyObject myMethod]; // did not have to create an instance
MyObject* myNewObject = [[MyObject alloc] init] autorelease];
[myNewObject myMethod]; // had to create an instance

About moving few methods to the superclass

I need to move the same method from 4 different classes to the superclass.
Such methods are exactly the same except for the type of a variable declared in them:
For example, in the method in the first class I have
FirstClass var = [[FirstClass alloc] init]
in the second class
SecondClass var = [[SecondClass alloc] init]
and so on.
What's the best way to implement this variation in the superclass ?
Should I use NSClassFromString in the superclass and get each string from each method in the subclasses?
thanks
I'm not 100% sure I get what you mean. So I could be answering the wrong question
If inside your class you need to use an object (I've called it worker below) to do your work, but the class of this object is not known til later, you can use dependency injection (DI).
MyClass.h
#interface MyClass : NSObject
#property (nonatomic, retain) id<WorkerInterface> worker;
#end
MyClass.m
#implementation MyClass
#synthesize worker = _worker;
- (void)myMethod;
{
[self.worker doSomething];
}
// You could also provide a default class to use if one is not passed in
//
// - (id<WorkerInterface)worker;
// {
// if (!_worker) {
// _worker = [[DefaultWorker alloc] init];
// }
// return _worker;
// }
#end
Now whenever I instantiate this class I can simply pass in the appropriate object to be used e.g:
MyWorkerClass *worker = [[MyWorkerClass alloc] init]; // <- Conforms to #protocol(WorkerInterface)
MyClass *instance = [[MyClass alloc] init];
instance.worker = worker;
[instance doSomething];
If all the different types of iVar's you intend on initializing in the subclasses are descended from a common class, then I'd store that class in the super, or else just store it as an id. Then, setup a property accessor in each of your subclasses the casts the iVar as you need it.
#interface superClass : NSObject{
id _superIvar;
}
#end
#implementation superClass : NSObject
....super's code....
#end
Now in the implementation of the subclass declare a property in a category, shown below (or in the interface, if you want it public)
#interface subClass (private)
#property (strong) ClassType *superIvar;
#end;
#implementation
- (void) setSuperIvar:(ClassType *)superIvar{
_superIvar = superIvar;
}
- (ClassType *) superIvar{
return (ClassType *) _superIvar;
}
- (void) someMethodThatUsesSuperIvar{
[self.superIvar doSomething];
}
#end
Alternatively, if you don't want to open your _superIvar to direct access, you can set a property on the superclass and access through the property on the subclass. But in this way you can easily access super's ivars cast to the appropriate type.

Dynamically invoke a class method in Objective C

Suppose I have Objective C interface SomeClass which has a class method called someMethod:
#interface SomeClass : NSObject {
}
+ (id)someMethod;
#end
In some other interface I want to have a helper method that would dynamically invoke someMethod on a class like this:
[someOtherObject invokeSelector:#selector(someMethod) forClass:[SomeClass class];
What should be the implementation for invokeSelector? Is it possible at all?
- (void)invokeSelector:(SEL)aSelector forClass:(Class)aClass {
// ???
}
Instead of:
[someOtherObject invokeSelector:#selector(someMethod) forClass:[SomeClass class];
call:
[[SomeClass class] performSelector:#selector(someMethod)];
Example (using GNUstep ...)
file A.h
#import <Foundation/Foundation.h>
#interface A : NSObject {}
- (NSString *)description;
+ (NSString *)action;
#end
file A.m
#import <Foundation/Foundation.h>
#import "A.h"
#implementation A
- (NSString *)description
{
return [NSString stringWithString: #"A"];
}
+ (NSString *)action
{
return [NSString stringWithString:#"A::action"];
}
#end
Somewhere else:
A *a = [[A class] performSelector:#selector(action)];
NSLog(#"%#",a);
Output:
2009-11-22 23:32:41.974 abc[3200] A::action
nice explanation from http://www.cocoabuilder.com/archive/cocoa/197631-how-do-classes-respond-to-performselector.html:
"In Objective-C, a class object gets all the instance methods of the
root class for its hierarchy. This means that every class object
that descends from NSObject gets all of NSObject's instance methods -
including performSelector:."
In Objective-C, classes are objects as well. The class objects are treated differently, however, as they can call the instance methods of their root class (NSObject or NSProxy in Cocoa).
So it's possible to use all the instance methods defined in NSObject on class objects as well and the right way to dynamically invoke a class method is:
[aClass performSelector:#selector(aSelector)];
The apple docs are a bit more specific.
You shouldn't implement this yourself.
The NSObject Protocol has a performSelector: method that does exactly this.
Is this built-in method what you want?
id objc_msgSend(id theReceiver, SEL theSelector, ...)
(See the runtime reference docs for this function.)