Reputation: 2041
Is it possible to pass a unknown type of parameter to a objective-C
method?
In C#
you can write <T>
to achieve this, but I know that objective-C
doesn't have generics so are there some other way to make this possible in objective-C
?
I need this because I want to create a method that changes the text color of different objects like placeholder text of a UITextField
and UIButton
. So my plan was to create one method called textWhite
and then inside this method to check for the kind of object and then run matching code to make the text color white.
Upvotes: 7
Views: 7466
Reputation: 28776
It sounds as though you need duck-typing, which is supported in Objective-C in the following ways:
Common Approach:
For very loosely defined protocols, approach number four is common: We declare a method as follows:
- (void)saveToInventory:(id)inventoryItem
{
if ([inventoryItem respondsToSelector:@selector(sendToWarehouse])
{
id<Warehouseable> warehouseable = (id<Warehouseable>) inventoryItem;
[warehouseable sendToWarehouse];
}
}
. . . while this approach works, it doesn't have a great deal of rigor. Its better to define a stricter protocol.
Rigorous Approach: Replace 'isKindOfClass/respondsToSelector' with polymorphism:
In general its good practice to replace 'isKindOfClass' with polymorphism. Rather than check for a given type, define an interface contract and let a given instance handle this as required. This leads to cleaner, more maintainable code.
In objective-C, the dynamic method dispatch system, makes mix-ins very easy where in C# or Java they require sophisticated libraries. Therefore, even classes that come from a 3rd party, and for which you don't have the source can be extended to all conform to a given protocol. Just define a category method on each class to perform the work. Be sure to use a method name that won't lead to a namespace collision. Example:
@protocol Themeable
-(void)setTheme:(Theme*)theme
@end
UITextField(ThemeAdditions)<MyAppThemeable>
- (void)setTheme:(Theme*)theme
{
//Now your text field can respond to this interface
}
Generics in Objective-C:
You mentioned generic-types in your example above. Its not clear how this fits in. In any case its not explicitly supported in Objective-C, although it can be retro-fitted with some caveats. Here's a library that does this: https://github.com/tomersh/Objective-C-Generics
Note that even without generics, its generally not necessary to explicitly cast in Objective-C: NSArray, NSSet, etc all use id as the type being stored. . . this of course doesn't give you compile-time checking. We generally live without this, although if its badly needed something like the library above could help.
Upvotes: 2
Reputation: 77651
One thing to add to the current answers.
You could use a protocol
for this kind of thing. That way you can inform the method that the object being passed in conforms to a certain protocol and the method will know about the properties
and methods
declared in that protocol.
For instance...
MyProtocol.h
@protocol MyProtocol <NSObject>
@property (nonatomic, strong) NSString *someString;
@property (nonatomic, strong) Person *person; //some custom class
- (void)doSomething;
@end
Then in your method you can declare it like the following...
- (void)foo:(id <MyProtocol>)protocolObject
{
NSLog(@"%@", protocolObject.someString);
Person *person = protocolObject.person;
[protocolObject doSomething];
}
This way you can use any object type without having to do if...else
for all the different possibilities. You just need to include the protocol declaration and you know it works.
Just to add a nice summary to this...
In order to interact with an object you just need to know HOW it works. You don't need to know WHAT it is. By doing this with a protocol you are allowing yourself to interact in this way.
Upvotes: 2
Reputation: 1447
Yes, it is possible to pass unknown type of parameter. See below example.
-(void) fooMethod:(id)unknownTypeParameter {
if( [unknownTypeParameter isKindOfClass:[Animal Class]]) {
Animal *referanceObj = (Animal *) unknownTypeParameter;
referanceObj.noOfLegs = 4;
}
}
Refer link for use id object as parameter Using (id) in Objective-C
Upvotes: 7
Reputation: 8147
You can use the anonymous type id
for that. Don't forget to include a check if the object responds to the selectors you're going to use.
Upvotes: 2