Type Casting in Objective C - objective-c

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];
}

Related

How to specify the type of a Class type

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
}

Syntax to return a on Objective-C class reference from a method?

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.

Polymorphic methods in Objective C

In Java you can put in multiple constructors to a class that are called depending on the types and/or number of parameters that are used when an instance is constructed.
I assume that there is the equivalent in Objective C.
Can I have a polymorphic method?
I would like to build a method that acts slightly differently according to whether a string is passed or a double?
Does that sound bonkers or is it easy?
You're thinking of overloaded methods. Due to the way dynamic dispatch is implemented in Objective-C, it isn't currently possible to pass two unrelated types as arguments to the same (or same-named) method and have it understand.
In Objective-C, there are two related but distinct approaches to handling multiple kinds of input. Let's use your example of a string or a double as possible inputs. In Java, you might have:
void applyWidget(String s);
void applyWidget(double d);
And that's great, but not Objective-C. In Objective-C, you instead would use two different method names:
- (void)applyWidgetWithName: (NSString *)name;
- (void)applyWidgetWithValue: (double)value;
The same logic is in each method as in the Java version, but the distinct names let the compiler treat them as distinct methods (which they are, even in Java.) The code also becomes self-documenting: by reading it, you get an idea of what's happening even without comments. Alternatively, if you simply must have one method name, you change the parameter type to id and accept any object:
- (void)applyWidget: (id)widget;
Then pass either an NSString or an NSNumber wrapping your double. Then, in the implementation of the method, use Objective-C's introspection methods to determine how to proceed:
if ([widget isKindOfClass: [NSString class]]) {
...
} else if ([widget isKindOfClass: [NSNumber class]]) {
double d = [widget doubleValue];
...
}
This approach essentially tells callers "send anything--I'll handle it appropriately." It can be difficult to determine the behaviour of such a method without extensive documentation.
Absolutely easy:
- (id)initWithSomeObject:(id)object
{
if ([object isKindOfClass:[ClassOne class]) {
// do something
} else if ([object isKindOfClass:[ClassTwo class]) {
// do something else
} // etc.
return self;
}
yes, but objc does not have proper overloading.
so you see things like initWithDouble:, initWithBool: and so on. that's part of the reason it's a bit 'wordy' for some people's taste.
to use your example:
#interface MONClass
- (id)initWithString:(NSString *)pString;
- (id)initWithDouble:(double)pDouble;
...
but the following is an error:
- (id)initWith:(NSString *)pString;
- (id)initWith:(double)pDouble;
because the selector is the same -- the parameter/return types are omitted from the selector.
Basically Objective C does't have proper method overloading. It will support overriding only.
Suppose if you write functions like in same class,
(void) showMethod;
(void) showMethod:(int) aNumber;
This will support in Objective C.
Suppose if you write functions like,
(void) showMethod:(NSString*) aString;
(void) showMethod:(int) aNumber;
In this way the compiler gives Error because there conflicting parameter types in implementation of showMethod.

Objective c return type switch

I want to use the return type of a selector to determine how it is used in my code is there a way to differentiate the return types in objective c I'll give you an example.
SEL selectors[]=
{#selector(method1),
... //each method returns a different type
#selector(methodn);}
for (SEL sel in selectors)
{
switch [[self performSelector:sel]/*idk something here maybe?*/]
{
case int:
//do some stuff
...
case NSString *:
//do some other stuff
}
}
Thanks in advance I couldn't find anything anywhere on this that talked about objective c
you can do this via method_copyReturnType in objc runtime.
however, objc types for return and parameters are all the same (last i checked), such that the runtime will not return the type with the description "NSArray" -- it will just be the identifier for an objc type. nevertheless, that level of detail is descriptive enough for your int or NSString case, and you can use an NSObject instance's class or isKindOfClass: (etc.) instance methods to determine its type once you have a handle on it.
You can get the NSMethodSignature of the method using -methodSignatureForSelector:. And then you can get the return type with the -methodReturnType from the NSMethodSignature object. Don't mess with the runtime if you don't have to.

Invoke selector with scalar argument

I currently use objc_msgSend to invoke such selector on collection of object. Is there any better way to do that? Here is my code:
#protocol ADelegateProtocol {
-(void) timeToEventOneDidChange:(NSInterval) event1;
-(void) timeToEventTwoDidChange:(NSInterval) event1;
}
- (void) delegatesPerformSelector:(SEL) selector withTimeIntervalAsFristParameter:(NSTimeinterval) timeInterval {
for (id<ADelegateProtocol> delegate in delegates) {
if([delegate respondsToSelector:selector]) {
objc_msgSend(delegate, selector, timeInterval);
}
}
}
The selector is passed in as a parameter, timeInterval is a non-object value.
Note: I don't want to use KVO.
If you are going to use objc_msgSend() you must create a correctly typecast function pointer to do so. Relying on varargs to map to non-varargs doesn't work in all cases.
I.e. You'd want:
void (*myMessage)(id, SEL, NSTimeInterval) = objc_msgSend;
myMessage(delegate, aSelector, aTimeInterval);
(typed into SO -- consider the syntax an approximation. :)
What you can use beside objc_msgSend (which of course works), is NSInvocation. Personally I prefer the objc_msgSend way as its the most overhead free way to do this. Its also the more faster way, but this shouldn't matter in a normal App (it does matter in games).
Well, the choice is yours, both ways work and there is nothing bad with objc_msgSend or NSInvocation (beside that C code looks wrong in an ObjC method).
If delegates is an NSArray: what about using NSArray's makeObjectsPerformSelector:(SEL)aSelector.
If you need to pass an object along as a parameter, you can use makeObjectsPerformSelector:(SEL)aSelector withObject:(id)anObject.