So I'm coding up an NSTableView. All is well and fine—until my Control Flow stopped working.
For some reason an array defined as _permanentItems = #[ #[#"My", #"Permanent"], #[#"Items"] ]
isn't a kind of NSArray.
Why might this be?
For context—it does work for NSNumber Why #(NO) isn't kind of class NSNumber
The method isKindOfClass works on instances:
YES if the receiver is an instance of aClass or an instance of any class that inherits from aClass, otherwise NO.
The type of itemClass itself is a metatype, and that isn't a kind of NSArray. What you meant here was:
if ([item isKindOfClass: arrayClass]) { ... }
^^^^
If you need to work entirely in classes and don't have an instance, then you can use +isSubclassOfClass: instead:
if ([itemClass isSubclassOfClass: arrayClass])) { ... }
^^^^^^^^^^^^^^^^^^
Related
I am currently trying to define a method, that takes a Class as argument, that is a subclass of a specific type. My current implementation is:
- (void)methodThatNeedsAClassOfSpecialTypeAsInput:(Class)inClass {}
Taking NSString as an example base class, I have tried NSString.Class and [NSString class] to specify the arguments class, but
- (void)methodThatNeedsAClassOfSpecialTypeAsInput:([NSString class])inClass { }
does not compile with Parse issue: Expected a type.
So the question is: is is possible to make an Class arguments type explicit?
Or in other words: I want my methods signatures semantic to say: I can take a NSString class, an only a NSString class as argument.
EDIT:
The answer is: No.
You almost had it:
[NSString class]
EDIT (after question updated):
This is how the method is defined and declared:
- (void)methodThatNeedsAClassOfSpecialTypeAsInput:(Class)inClass { }
But it is called like this:
[someObject methodThatNeedsAClassOfSpecialTypeAsInput:[NSString class]];
You got it wrong. Method declaration was right
- (void)methodThatNeedsAClassOfSpecialTypeAsInput:(Class)inClass;
Than, in place you call it
[obj methodThatNeedsAClassOfSpecialTypeAsInput:[NSString class]];
If, in implementation you need to be guarantee, that your inClass is NSString, you can use
if([inClass isSubclassOfClass:[NSString class]]) {
//Do whatever you need
}
#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");
}
can someone please tell me whether this is the correct way of doing type casting in objective c.
I have an object "myObject" which could possibly be an instance of "DataViewController".
If so i should call the "updateView" method.
if (myObject respondsToSelector:#selector(updateView:)])
{
[(DataViewController *)myObject updateView:data];
}
You do not need a cast in this case: since you've started down the selector path, you might as well call performSelector:withObject: for consistency:
if (myObject respondsToSelector:#selector(updateView:)]) {
[myObject performSelector:#selector(updateView:) withObject:data];
}
This is a more general approach, because it lets you run updateView on objects of other types, not necessarily of DataViewController, as long as they have the appropriate method.
If you would like to use a type-based solution, you could use isKindOfClass: method, like this:
if (myObject isKindOfClass:[DataViewController class]]) {
DataViewController *ctrl = (DataViewController)myObject;
[ctrl updateView:data];
}
I did try to google this, but actually found nothing. Coming from a strong Smalltalk background, I thought the following would be fine:
#import "ValveTargetState.h"
- (id) targetStateClass {
return ValveTargetState;
}
- (void) targetIsActive:(BOOL)isActive {
self.targetState = [[[self targetStateClass] alloc] initValve: self isActive: isActive];
[self.targetState push];
}
Basically, I've added a method, so that subclasses can tune what the targetStateClass is used. It was my understanding, that like Smalltalk, classes are objects too in ObjC. But Xcode tells me
Unexpected interface name 'ValveTargetState': expected expression
(for the return ValveTargetState; expression)
I think I'm missing something obvious, but what is it?
Try this:
- (Class)targetStateClass
{
return [ValveTargetState class];
}
Assuming that ValveTargetState is a class that inherits ultimately from NSObject, either
[ValveTargetState class]
or
[ValveTargetState self]
will give you the pointer to the class object for ValveTargetState.
It would be much better to use ValveTargetState directly, but unfortunately the name of a class is not a valid expression in Objective-C.
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.