My object's isKindOfClass executed with unexpected answer - objective-c

I've been trying to get this script print out the one of the two types of object that was inserted. However, it always prints both types while only one thing is inserted. There are two classes, VKJItem and VKJBox. VKJBox is a subclass of VKJItem.
This is the main.m:
VKJBox *box1 = [[VKJBox alloc] init];
VKJBox *box2 = [[VKJBox alloc] init];
[box1 addItem:box2];
and this is the implementation of my VKJBox's addItem method:
if ([item isKindOfClass:[VKJBox class]]) {
NSLog(#"BOX");
}
if ([item isKindOfClass:[VKJItem class]]) {
NSLog(#"ITEM");
}
The problem is that the script prints both BOX and ITEM to the console.

VKJBox is a subclass of of VKJItem and therefore VKJBox is a kind of VKJItem and a kind of VKJBox.
-isKindOfClass: is used to determine whether an object is an instance of a class or an instance of a class which inherits from the class.
For example:
isKindOfClass[UIView class] will be true for UIImageView, UILabel, etc.
Use the -isMemberOfClass: to check if the object is an instance of the specified class exactly.

On of your Classes must be a subclass of Other.
isKindClass:
Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class.
isMemberOfClass:
Returns a Boolean value that indicates whether the receiver is an instance of a given class.
You need to use isMemberOfClass
Source

Related

Get data type of variable

#interface testing
#property NSString *email;
#property NSString *password;
#end
In another class , how to get data type of email, or password without defined the email and password.
NSArray *keys=[[NSArray alloc] init];
[keys addObject:#"email"];
testing *detail=[[testing alloc]init];
if([[detail valueForKey:keys[0]] isKindOfClass:[NSString class]])
{ NSLog("This is string class variable"); }
but it not enter the if condition
All you need to do to obtain the class of a property is
[email class];
[password class];
There are ways to test the object class as well using isKindOfClass: and isMemberOfClass: and even isSubclassOfClass:
You can use these in if statements like
if([email isKindOfClass:[NSString class]])
and/or
if([password isMemberOfClass:[NSString class]])
and/or
if([[email class] isSubclassOfClass:[NSString class]])
For a description of each these please read the Apple Documentation on NSObject class reference. and Apple Documentation on NSObject protocol reference
isSubclassOfClass:
Returns a Boolean value that indicates whether the receiving class is a subclass of, or identical to, a given class.
+ (BOOL)isSubclassOfClass:(Class)aClass
Parameters
aClass
A class object.
Return Value
YES if the receiving class is a subclass of—or identical to—aClass, otherwise NO.
Availability
Available in iOS 2.0 and later.
Declared In
objc/NSObject.h
isKindOfClass:
Returns a Boolean value that indicates whether the receiver is an instance of given class or an instance of any class that inherits from that class. (required)
- (BOOL)isKindOfClass:(Class)aClass
Parameters
aClass
A class object representing the Objective-C class to be tested.
Return Value
YES if the receiver is an instance of aClass or an instance of any class that inherits from aClass, otherwise NO.
Discussion
For example, in this code, isKindOfClass: would return YES because, in Foundation, the NSArchiver class inherits from NSCoder:
NSMutableData *myData = [NSMutableData dataWithCapacity:30];
id anArchiver = [[NSArchiver alloc] initForWritingWithMutableData:myData];
if ( [anArchiver isKindOfClass:[NSCoder class]] )
...
Be careful when using this method on objects represented by a class cluster. Because of the nature of class clusters, the object you get back may not always be the type you expected. If you call a method that returns a class cluster, the exact type returned by the method is the best indicator of what you can do with that object. For example, if a method returns a pointer to an NSArray object, you should not use this method to see if the array is mutable, as shown in the following code:
// DO NOT DO THIS!
if ([myArray isKindOfClass:[NSMutableArray class]])
{
// Modify the object
}
If you use such constructs in your code, you might think it is alright to modify an object that in reality should not be modified. Doing so might then create problems for other code that expected the object to remain unchanged.
If the receiver is a class object, this method returns YES if aClass is a Class object of the same type, NO otherwise.
Availability
Available in OS X v10.0 and later.
See Also
– isMemberOfClass:
Related Sample Code
QuickLookSketch
Sketch
Sketch+Accessibility
Declared In
objc/NSObject.h
isMemberOfClass:
Returns a Boolean value that indicates whether the receiver is an instance of a given class. (required)
- (BOOL)isMemberOfClass:(Class)aClass
Parameters
aClass
A class object representing the Objective-C class to be tested.
Return Value
YES if the receiver is an instance of aClass, otherwise NO.
Discussion
For example, in this code, isMemberOfClass: would return NO:
NSMutableData *myData = [NSMutableData dataWithCapacity:30];
id anArchiver = [[NSArchiver alloc] initForWritingWithMutableData:myData];
if ([anArchiver isMemberOfClass:[NSCoder class]])
...
Class objects may be compiler-created objects but they still support the concept of membership. Thus, you can use this method to verify that the receiver is a specific Class object.
Availability
Available in OS X v10.0 and later.
See Also
– isKindOfClass:
Declared In
objc/NSObject.h
EDIT
When trying to access these properties in another class (Which isn't what you are asking in your question) do the following.
Testing *testingClassIVar = [[Testing alloc] init];
[testingClassIVar email];
[testingClassIVar password];
// to get the class type of these
[[testingClassIVar email] class];
[[testingClassIVar password] class];
EDIT 2
OMG just NO I don't even know what you are trying to do but it seems very wrong. NSArray doesn't respond to addObject: so this will crash your code. If you want to use addObject: then change the NSArray to NSMutableArray but unless you plan on using that array in a loop (If you are please specify I will not assume) then just access the property by using [detail email]
Change to this
testing *detail= [[testing alloc] init];
if([[detail email] isKindOfClass:[NSString class]]) {
NSLog("This is string class variable");
}

How to get the class that the method is defined, not that of the instance that the method is called?

[self class] returns the Class of the instance of the method being called, but is there a way to get the Class that the method is defined? Suppose Class B extends A, and b is an instance of B, I want a method in A that returns A not B, even when called from b.
edited:
I trying to create a NSObject category that has -(void)releaseProperties method, which fetches all properties defined in that class and set nil for the non-readonly object properties.
- (void)releaseProperties {
unsigned int c = 0;
objc_property_t *properties = class_copyPropertyList([self class], &c);
for(unsigned int i = 0; i < c; i++) {
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
NSString *propertyType = [NSString stringWithUTF8String:property_getAttributes(property)];
if([propertyType hasPrefix:#"T#"] // is an object
&& [propertyType rangeOfString:#",R,"].location == NSNotFound // not readonly
) {
[self setValue:nil forKey:propertyName];
NSLog(#"%#.%# = %#", NSStringFromClass(cls), propertyName, [self valueForKey:propertyName]);
}
}
free(properties);
}
I want to use this method in the dealloc method, but class_copyPropertyList([self class], &c) will not return properties defined in it's superclass, so the super-dealloc chain doesn't work well. So, instead of passing [self class], I wanted to pass the class that the specific dealloc method is being called.
I don't think there's a direct way of doing this, but you can call class_getMethodImplementation_stret with the current class to get the function pointer for the method that would be called. Then walk your superclasses, calling the same function with them until it returns something different. The previous superclass will be the one that is providing the implementation for your class.
Edit: Sorry, I may have misread the question. If you are looking for the first superclass in the hierarchy that defines a method with that signature, then you can just walk the superclasses calling respondsToSelector: until one of them doesn't. The method I describe above is to find the superclass providing the implementation that is inherited, not the definition.
For example, class A could define foo:, then class B (which is a subclass of A) could override it, then class C (which is a subclass of B) could ask where foo: comes from. If you want the class that provides the definition, you want A, and should use the second approach I describe. If you want the class that provides the implementation, you want B and should use the first approach I describe.
I have a feeling that [super class] might work for you.
And if you call "[super ..." (fill in the blank with whatever you want to call) within B, you'll be calling into a method that lives in A.
Class A can just provide a method like:
- (Class) classA
{
return [A class];
}
That's not generalizable, but your question insists on a non-generalizable answer.
It's a pretty bizarre thing to want. It suggests a problem with your design. May I ask why you want it? What problem are you trying to solve?

Objective-C pattern for class instance variables?

What would be a nice pattern in Objective-C for class variables that can be "overridden" by subclasses?
Regular Class variables are usually simulated in Objective-C using a file-local static variables together with exposed accessors defined as Class methods.
However, this, as any Class variables, means the value is shared between the class and all its subclasses. Sometimes, it's interesting for the subclass to change the value for itself only. This is typically the case when Class variables are used for configuration.
Here is an example: in some iOS App, I have many objects of a given common abstract superclass (Annotation) that come in a number of concrete variations (subclasses). All annotations are represented graphically with a label, and the label color must reflect the specific kind (subclass) of its annotation. So all Foo annotations must have a green label, and all Bar annotations must have a blue label. Storing the label color in each instance would be wasteful (and in reality, perhaps impossible as I have many objects, and actual configuration data - common to each instance - is far larger than a single color).
At runtime, the user could decide that all Foo annotations now will have a red label. And so on.
Since in Objective-C, Classes are actual objects, this calls for storing the Foo label color in the Foo class object. But is that even possible? What would be a good pattern for this kind of things? Of course, it's possible to define some sort of global dictionary mapping the class to its configuration value, but that would be kind of ugly.
Of course, it's possible to define some sort of global dictionary mapping the class to its configuration value, but that would be kind of ugly.
Why do you think this would be ugly? It is a very simple approach since you can use [self className] as the key in the dictionary. It is also easy to make it persistent since you can simply store the dictionary in NSUserDefaults (as long as it contains only property-list objects). You could also have each class default to its superclass's values by calling the superclass method until you find a class with a value.
+ (id)classConfigurationForKey:(NSString *)key {
if(_configurationDict == nil) [self loadConfigurations]; // Gets stored values
Class c = [self class];
id value = nil;
while(value == nil) {
NSDictionary *classConfig = [_configurationDict objectForKey:[c className]];
if(classConfig) {
value = [classConfig objectForKey:key];
}
c = [c superclass];
}
return value;
}
+ (void)setClassConfiguration:(id)value forKey:(NSString *)key {
if(_configurationDict == nil) [self loadConfigurations]; // Gets stored values
NSMutableDictionary *classConfig = [_configurationDict objectForKey:[self className]];
if(classConfig == nil) {
classConfig = [NSMutableDictionary dictionary];
[_configurationDict setObject:classConfig forKey:[self className]];
}
[classConfig setObject:value forKey:key];
}
This implementation provides no checking to make sure you don't go over the top superclass, so you will need to ensure that there is a value for that class to avoid an infinite loop.
If you want to store objects which can't be stored in a property list, you can use a method to convert back and forth when you access the dictionary. Here is an example for accessing the labelColor property, which is a UIColor object.
+ (UIColor *)classLabelColor {
NSData *data = [self classConfigurationForKey:#"labelColor"];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
+ (void)setClassLabelColor:(UIColor *)color {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:color];
[self setClassConfiguration:data forKey:#"labelColor"];
}
my answer here may help:
What is the recommended method of styling an iOS app?
in that case, your annotation just holds a reference to a style (e.g. you need only one per style), and the size of a pointer for an entire style is not bad. either way, that post may give you some ideas.
Update
Jean-Denis Muys: That addresses the sample use case of my question, but not my question itself (a pattern to simulate class instance variables).
you're right, i didn't know how closely your example modeled your problem and i considered commenting on that.
for a more general and reusable solution, i'd probably just write a threadsafe global dictionary if your global data is nontrivial (as you mentioned in your OP). you could either populate it in +initialize or lazily by introducing a class method. then you could add a few categories to NSObject to access and mutate the static data -- do this for syntactical ease.
i suppose the good thing about that approach is that you can reuse it in any program (even though it may appear ugly or complex to write). if that's too much locking, then you may want to divide dictionaries by prefixes or create a simple thread safe dictionary which your class holds a reference to -- you can then synthesize an instance variable via the objc runtime to store it and declare an instance method to access it. the class method would still have to use the global data interface directly.

Objective C - determine class type at runtime

In the interface I have this:
Animal* myPet;
At runtime I may want myPet to be a cat or a dog, which are subclasses of Animal:
id newPet;
if(someCondition) {
newPet = [[Cat alloc] initWithNibName:#"Cat" bundle:nil];
} else {
newPet = [[Dog alloc] initWithNibName:#"Dog" bundle:nil];
}
self.myPet = newPet;
Obviously this is incorrect, but I hope it's enough to show what I'm trying to do. What is the best practice for doing this?
isKindOfClass is your friend:
[newPet isKindOfClass:Dog.class] == NO
Strongly type newPet as Animal * instead of id. id can hold a reference to an instance of any class, but properties cannot be used with it (the dot syntax requires a strongly typed lvalue.) Since both Cat and Dog inherit from Animal, this will be perfectly correct and valid.
If you're using two classes that don't share a common ancestor (past NSObject), then you should take a step back and rethink your design--why would instances of those two classes need to occupy the same variable?
NSString *className = #"Cat";
Animal *myPet = [[NSClassFromString(className) alloc] init];
It's unclear what you are after, but if you want to create an instance of a class named by a string, this should do it.
For anyone arriving from Google based on the title: "Determine class type at runtime", here are some useful things to know:
You can call the class method on an NSObject* at run time to get a reference to its class.
[myObject class];
Take a look at these methods too:
isKindOfClass: - check if an object belongs to a class anywhere in its hierarchy.
isMemberOfClass: - check if an object belongs to a specific class.

Objective-C subclass and base class casting

I'm going to create a base class that implements very similar functions for all of the subclasses. This was answered in a different question. But what I need to know now is if/how I can cast various functions (in the base class) to return the subclass object. This is both for a given function but also a function call in it.
(I'm working with CoreData by the way)
As a function within the base class (this is from a class that is going to become my subclass)
+(Structure *)fetchStructureByID:(NSNumber *)structureID inContext:(NSManagedObjectContext *)managedObjectContext {...}
And as a function call within a given function:
Structure *newStructure = [Structure fetchStructureByID:[currentDictionary objectForKey:#"myId"]];
inContext:managedObjectContext];
Structure is one of my subclasses, so I need to rewrite both of these so that they are "generic" and can be applied to other subclasses (whoever is calling the function).
How do I do that?
Update: I just realized that in the second part there are actually two issues. You can't change [Structure fetch...] to [self fetch...] because it is a class method, not an instance method. How do I get around that too?
If I understand your question correctly I believe the key is the [self class] idiom.
As far as your update goes requesting a way to call a class method on the current class you can use [self class]. As in:
Structure *newStructure = [[self class] fetchStructureByID:[currentDictionary
objectForKey:#"myId"]];
inContext:managedObjectContext];
EDIT: I redid this to return id per #rpetrich's comment -- much cleaner and avoids the need for -isKindOfClass: as long as you're sure of the type of the instance you're calling -createConfiguredObject on.
As for the first part, you could just return an id (pointer to any object) and document that it will return an instance of the same class it's called upon. Then in the code you need to use [self class] anywhere you instantiate a new object in a method.
e.g. if you have a -createConfiguredObject method which returns an instance of the same class it's called on, it would be implemented as follows:
// Returns an instance of the same class as the instance it was called on.
// This is true even if the method was declared in a base class.
-(id) createConfiguredObject {
Structure *newObject = [[[self class] alloc] init];
// When this method is called on a subclass newObject is actually
// an instance of that subclass
// Configure newObject
return newObject;
}
You can then use this in code as follows:
StructureSubclass *subclass = [[[StructureSubclass alloc] init] autorelease];
subclass.name = #"subclass";
// No need to cast or use isKindOfClass: here because returned object is of type id
// and documented to return instance of the same type.
StructureSubclass *configuredSubclass = [[subclass createConfiguredObject] autorelease];
configuredSubclass.name = #"configuredSubclass";
For reference, what I was referring to with -isKindOfClass: and casting to the proper subclass is as follows:
Structure *structure;
// Do stuff
// I believe structure is now pointing to an object of type StructureSubclass
// and I want to call a method only present on StructureSubclass.
if ([structure isKindOfClass:[StrucutreSubclass class]]) {
// It is indeed of type StructureSubclass (or a subclass of same)
// so cast the pointer to StructureSubclass *
StructureSubclass *subclass = (StructureSubclass *)structure;
// the name property is only available on StructureSubclass.
subclass.name = #"myname";
} else {
NSLog(#"structure was not an instance of StructureSubclass when it was expected it would be.");
// Handle error
}