#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");
}
Related
This question already has answers here:
Would it be beneficial to begin using instancetype instead of id?
(5 answers)
Closed 7 years ago.
I've just been reading and learning about instancetype and how in most cases it should be used instead of id in modern objective-c. Can I just ask when, then, would it be advisable to actually use id and not instancetype?
Thanks.
id
id is the generic type variable. Id doesn't warn us at compile time but it will crash if there is any problem.
Instancetype
instancetype does type checking for us at compile time to warn us of problems.
eg:
Animal.h
#interface Animal : NSObject
+ (id)giveMeAnimalA;
+ (instancetype)giveMeAnimalB;
+ (Animal *)giveMeAnimalC;
#end
Animal.m
#implementation Animal
+ (id)giveMeAnimalA {
return [[[self class] alloc] init];
}
+ (instancetype)giveMeAnimalB {
return [[[self class] alloc] init];
}
+ (Animal *)giveMeAnimalC {
return [[[self class] alloc] init];
}
#end
Suppose if we use [[Animal giveMeAnimalA] count];
The compiler will warn us of nothing, but we will crash at runtime with an exception because Animal doesn't have a count method.
And If we use [[Animal giveMeAnimalB] count];
The compiler would immediately warn us that Animal does not have a count method, and we could avoid crashing at runtime. But wouldn't it be simpler just to make our return type Animal* ?
Imagine we have a Dog subclass of Animal:
#interface Dog : Animal
- (void)makeSound;
#end
Now if we tried to call
[[Dog giveMeAnimalC] makeSound];
This wouldn't work because we would have been returned an Animal that doesn't have a makeSound method.
For complete last answer, i suggest you an example when Id is supported. It's on the ForIn Loop (fast enumeration)
Imagine, you have an array with three different objects like below :
NSArray *anotherArray = #[#"One element of Another Array",#"Second Element of Another Array"];
NSArray *array = #[#"First",#[anotherArray],#(12)];
for (id item in array)
{
if ([item isKindOfClass:[NSString class]])
{
NSLog(#"Im a NSString");
}
if ([item isKindOfClass:[NSArray class]])
{
NSLog(#"Im a NSArray");
}
if ([item isKindOfClass:[NSNumber class]])
{
NSLog(#"Im a NSNumber");
}
}
The id is a generic data type which can hold any type of data like nsstring,uiimage,nsarray and remaining all,so if you are having the requirements like returning the objects dynamically from a method you better use the return type of that method as id,hope you will get it
You can not use instancetype as return type when the type of the value that is returned is not known beforehand. If a method might return either an NSButton or an NSString depending on context, you can only use id.
instancetype is just a placeholder for the class that it is being used in; if a method of class Foo is like
- (instancetype) getMeFoo
then it is equivalent to
- (Foo *) getMeFoo
It can not return an NSString; the compiler would complain. However,
- (id) getMeFoo
can return any class type.
You could theoretically use a common superclass of the possibly returned types (for example, NSObject); but then you would need to typecast it when assigning to a concrete variable, or the compiler would bug you with warnings.
- (NSObject *) getMeFoo {
return #"foo!";
}
NSString *myString = (NSString *)[self getMeFoo];
The id type is "automatically" cast:
- (id) getMeFoo {
return #"foo!";
}
NSString *myString = [self getMeFoo];
But never forget to check if you really got the expected type:
NSString *myString = [self getMeFoo];
if (![myString isKindOfClass:[NSString class]]) {
// Danger, Will Robinson!
}
"I've just been reading and learning about instancetype and how in most cases it should be used instead of id in modern objective-c. Can I just ask when, then, would it be advisable to actually use id and not instancetype? Thanks."
You learned wrong. Kind of. The problem is that a language like Objective-C is complicated, and every rule will come with a long list of "do this IF a and b and c"... which you have to understand.
instancetype is used in one very particular situation: As the return type of init methods. You can't use for example UIButton* because an init method of UIButton could be used by a subclass, so the init method doesn't actually a UIButton but some subclass. That's why "id" was used which means "some object but I have no idea which object actually". "instancetype" on the other hand tells the compiler "you are clever, you figure it out. So with [[UIButton alloc] init] the compiler knows it returns UIButton*. [[MyButtonSubclass alloc] init] the compiler knows it returns MyButtonSubclass*.
In no other situation would you use instancetype.
Always give the compiler as much information as you can. If you have an object declared as UIButton* the compiler knows it's a UIButton or a subclass. If you have an object declared as id the compiler knows nothing. That means the compiler can't tell you if you do something stupid (like assigning a UIButton* to an NSString*, or calling the length method on a UIButton).
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
I'm not really experienced with Objective-C. Here is a problem I encountered.
When I want to define a pointer for a particular instance of a class, I can
NSString* foo;
But is it possible to define pointers for instances of classes like this?
x* hotdog; //"x" is the type of pointer hotdog is
hotdog = NSString; //now points to NSString
hotdog* foo; //an instance of NSString is created
hotdog = UIView; //now points to UIView
hotdog* foo; //an instance of UIView is created
How to define the class-pointer hotdog? (what should I replace x with?)
what should I replace x with?
You should replace x with the name of the most specific common ancestor of the classes that you are planning to use with this pointer. In your example, that would be NSObject, because both NSString and UIView inherit it, and there are no other common ancestors. In the worst case, the common ancestor is id.
In general, tricks like that should be avoided in most situations, because reusing a pointer for something really different is bad for readability.
If you want a pointer to an object of a type that's not yet known at compile-time (similar to dynamic in C#), use id:
id hotdog;
hotdog = [[NSString alloc] init];
hotdog = [[NSArray alloc] init];
Only do this when you really need it. If you use it everywhere, your code can easily become a mess since you'll lose track of the type of the variable.
At first I misunderstood your question. I'll leave my old answer here just in case future visitors need it.
The type of pointers to classes is Class and to get an object of that type use +[NSObject class].
Class hotdog = [NSString class]; // now points to NSString
NSString *myString = [[hotdog alloc] init]; // create instance of NSString
hotdog = [NSArray class]; // now points to NSArray
NSArray *myArray = [[hotdog alloc] init]; // create instance of NSArray
You can use either NSObject* or id as the pointer type. NSObject* will accept any subclass of NSObject, while id will accept other Objective-C objects as well.
Note that, to avoid compiler warning messages, you must cast the pointer type back to the (presumably known) actual type before applying any sort of dereferencing operation (other than methods of NSObject).
You can, to be sure you have the expected type of object, use isKindOfClass to check the type:
if ([genericPointer isKindOfClass:[NSArray class]]) {
NSString* arrayElement = [(NSArray)genericPointer objectAtIndex:x];
}
But is it possible to define pointers for instances of classes like this?
I suppose you're asking for the equivalent of C++ templates.
You can't do it and you don't need it, just use the id type:
id foo= #"some text";
If you are working on an instance class the pointer to the class itself is simply self.
If you are working on a class pointer you could just use the id type since it is a generic type. Make sure then the object you are working on is of the expected type by using the isKindOfClass method if you want to invoke some methods of this class.
I have a problem with classes. This is my code:
self.shapeClass = [HWRectangle class];
if ([_shapeClass isKindOfClass:[HWRectangle class]]) {
NSLog(#"Class created as: %s", [_shapeClass description]);
}
I thought that the program will do the logging in this case, but it doesn't. Do you have any idea why not?
because: if ([_shapeClass isKindOfClass:[HWRectangle class]])
_shapeClass should be an instance of the class you are testing, unless you are really testing for class comparisons. So, this method is instance to class comparison, not class to class comparison.
For bonus points, your format string should be: NSLog(#"Class created as: %#", [_shapeClass description])
(unless you have overridden the NSObject method (which you should not do))
isKindOfClass checks the class of a variable. You say that shapeCalls = [HWRectangle class]. The result of [HWRectangle class] is of the class "Class". So if you compare this with the class of HWRectangle you will find that the two are not the same.
I have seen a lot of talk about dynamic typing in objective-c. But i haven't seen any examples of what i think it is supposed to be.
lets say I have a generic function that is supposed to juggle two objects (one gets allocated and the other gets freed) and the calling object attaches it self to the newly alloced object. Both are inherited from class0
Please feel free to interpret this however you want if you think it will explain something!!
If the class is picked at runtime, how do i deal with the arguments list (? is a placeholder for now)
How do i alloc a object who's class is not defined until runtime?
-(void) juggle:(?*)objclass1:(?*)objclass2{
? temp = [? alloc] init];
objclass1 = temp;
[temp release];
[objclass2.view removefromsuperview];
[self.handle insertsubview:objclass1.view];
}
I have no idea what the code you have there is trying to do, it is not syntactically valid, and manipulating views has nothing to do with your questions. Anyway, if you really don't know the type you generally use "id" which is type cast to a "void *" for codegen. It has the special property that it is assumed to receive any message, so it does not trigger compiler warnings for unknown messages.
In order to instantiate a class you just need to be holding the "Class" object for it. In Objective C all instances of a class refer to a Class object (the isa pointer in the legacy runtime), which also responds to methods. So in other words, in the following code:
NSArray *myObject = [[NSArray alloc] init];
NSArray is actually an object. So this will generate equivalent code results:
Class myClass = [NSArray class];
NSArray *myObject = [[myClass alloc] init];
or even
Class myClass = NSClassFromString(#"NSArray");
NSArray *myObject = [[myClass alloc] init];
Which uses the function NSClassFromString which walks into the runtime and finds a class with the name you pass in.
All objects return their class if use the class getter, so to instantiate an object that is the same class as an existing object like this:
- (void) leakObjectWithSameClassAs:(id)object {
[[[object class] alloc] init];
}
This is what i have now
- (void)flipfromv1tov2:(UIViewController*)v1:(NSString*)nib1:(UIViewController*)v2{
if(v1 == nil)
{
UIViewController *newview = [[[v1 class] alloc] initWithNibName:nib1 bundle:nil];
v1 = newview;
[newview release];
}
[v2.view removeFromSuperview];
[self.view insertSubview:v1.view atIndex:0];
}
I cannot verify it yet because I have a linking problem...I added this func to my root controller but for some reason I get a warning that the function is implicitly declared. And the build fails because the function call never get linked to anything