Objective-C dynamic_cast? - objective-c

Is there an Objective-C equivalent of C++'s dynamic_cast?
It can be faked using this:
MyClass *safeObject = [object isKindOfClass: [MyClass class]]
? (MyClass *)originalObject : nil;
But this is a lot of code to type, even if I don't need to type it often.
I am a bit rusty so this might not be quite right, but I believe the equivalent in C++ would be:
MyClass safeObject = dynamic_cast<MyClass>(orginalObject);
The context here is a block where the parameter is defined as a type of a more generic class, but in this block I "know" it's a specific subclass. Nevertheless, I don't want to just cast it blindly with (MyClass *)originalObject and ignore a theoretically possible error.
To be clear, while I'd love a dynamic_cast, I'd be happy with an alternate approach to safely handle this case as well.

If you're willing to use Objective-C++, you can write this pretty easily:
template<typename T> inline T* objc_cast(id from) {
if ([from isKindOfClass:[T class]]) {
return static_cast<T*>(from);
}
return nil;
}
This should behave exactly as dynamic_cast<> except for obj-c objects.
If you want to stick with vanilla Obj-C you can get similar behavior with a class method on NSObject:
#interface NSObject (Cast)
+ (instancetype)cast:(id)from;
#end
#implementation NSObject (Cast)
+ (instancetype)cast:(id)from {
if ([from isKindOfClass:self]) {
return from;
}
return nil;
}
#end
This version just isn't as nice to use since you have to say something like
UIButton *button = [UIButton cast:someView];
In both versions the resulting value is nil if the cast fails.

Try this macro:
#define objc_dynamic_cast(obj, cls) \
([obj isKindOfClass:(Class)objc_getClass(#cls)] ? (cls *)obj : NULL)
And also don't forget to
#include <objc/runtime.h>
Use it like:
MyClass *safeObject = objc_dynamic_cast(originalObject, MyClass);

I don't think there is.
I think the space for a bug is quite small here.
But if you insist, a macro will do fine?

Related

Auto conversion type - Objective C

I am new to Objective-C and I would like to know if there is any way to implicitly convert an object.
By implicitly, I mean, for example, writing something like this :
MyColorClass *color = [[MyColorClass alloc] init];
SomeStuffUsingUIColor(color);
Instead of this :
MyColorClass *color = [[MyColorClass alloc] init];
SomeStuffUsingUIColor([color toUIColor]);
I know that there is no way to overload casting operators (in Objective-C), but maybe there is a specific solution for this problem.
There's often no need to convert the object to a new type. Just implement the same methods that UIColor does, so that MyColorClass responds to the same messages. This isn't always enough -- for example, if MyColorClass isn't a UIColor subclass, it won't get any methods added to UIColor via a category. If you need that, it's best to derive MyColorClass from UIColor so that every instance of the former is an instance of the latter.
Usually, you want to create a category for this kind of things, e.g.
#interface UIColor (MyExtensions)
- (void)doSomethingUsingColor
#end
#implementation UIColor (MyExtensions)
- (void)doSomethingUsingColor {
//do something
}
#end
You can see some examples in NSString+UIStringDrawing.h category.
Also note that if you want to do something with a C struct, you would usually declare a function, e.g.
typedef struct {
int x;
int y;
} MyPoint;
void doSomethingWithPoint(MyPoint point) {
//do something
}
You can see examples in the API, for example: NSStringFromCGPoint.

Does Objective-C have an equivalent to java annotations?

Does Objective-C have an equivalent to java annotations?
What's I'm trying to do is create a property and be able to somehow access some metadata about it.
I want to be able to determine what type of classes should go in my array so I'd like to annotate it somehow to say so. Then later be able to access that annotation via something like the runtime library where I can access lists of properties and their names.
//Put some sort of annotation giving a class name.
#property (strong) NSArray *myArray;
You said:
I want to be able to determine what type of classes should go in my array so I'd like to annotate it somehow to say so. Then later be able to access that annotation via something like the runtime library where I can access lists of properties and their names.
There are a few ways to do this sort of thing in Objective-C. Apple's frameworks do this sort of thing by adding a class method that returns the required information. Examples: dependent keys in KVO, +[CALayer needsDisplayForKey:] and related methods.
So, let's create a class method that returns an array of classes that can go into your container property, given the property name. First, we'll add a category to NSObject to implement a generic version of the method:
#interface NSObject (allowedClassesForContainerProperty)
+ (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name;
#end
#implementation NSObject (allowedClassesForContainerProperty)
+ (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name {
if (class_getProperty(self, name.UTF8String)) {
return #[ [NSObject class] ];
} else {
[NSException raise:NSInvalidArgumentException
format:#"%s called for non-existent property %#", __func__, name];
abort();
}
}
#end
As you can see, this default version of the method doesn't do anything particularly useful. But adding it to NSObject means we can send the message to any class without worrying about whether that class implements the method.
To make the message return something useful, we override it in our own classes. For example:
#implementation MyViewController
+ (NSArray *)allowedClassesForContainerPropertyWithName:(NSString *)name {
if ([name isEqualToString:#"myArray"]) {
return #[ [UIButton class], [UIImageView class] ];
} else {
return [super allowedClassesForContainerPropertyWithName:name];
}
}
...
We can use it like this:
SomeViewController *vc = ...;
SomeObject *object = ...;
if ([[vc.class allowedClassesForContainerPropertyWithName:#"bucket"] containsObject:object.class]) {
[vc.bucket addObject:object];
} else {
// oops, not supposed to put object in vc.bucket
}
There is no native support of this functionality, but you may to take a look at following solution — https://github.com/epam/lib-obj-c-attr/ It is compile time implementation of attributes. Definition of attributes based on defines but not on comments as in other solutions like ObjectiveCAnnotate.
Objective C does not support generics like in Java but ofcourse the language is very flexible that you can accomplish almost anything with simple tricks and knowledge. To implement a generic like feature you could create a category on NSArray class and create your own method to initialize the array and then check to see if the object is really the type of the object you want.
I would write a simple category on NSArray to have such functionality. Say suppose, I want my array to hold objects of class MyClass only then my category would look like,
#interface NSArray(MyCategory)
#end
#implementation NSArray(MyCategory)
-(NSArray*)arrayWithMyClasses:(NSArray*)classes{
if([classes count] > 0){
NSMutableArray *array = [[NSMutableArray alloc] init];
for(id anObj in classes){
NSAssert([anObj isKindOfClass:[MyClass class]], #"My array supports only objetcts of type MyClass");
[array addObject:anObj];
}
return array;
}
return nil;
}
#end
Of course, there is some limitations to it. Since you have created your own category, you should use your own method to initialize and create your own array.
No, Objective-C has no annotation or generics support.
A way to implement such a thing would be to hack Clang to read comments and associate a metadata object to the original object. But, you would be tied to your hacked compiler.
NSString *v1 = [[NSString alloc] init];
// associate
static char key;
NSString *v2 = [[NSString alloc] init];
objc_setAssociatedObject (
v1,
&key,
v2,
OBJC_ASSOCIATION_RETAIN
);
// retrieve
NSString *associate = (NSString *)objc_getAssociatedObject(v1, &key);
Qualifying with a protocol wouldn't be much trouble, and you could test if the collection implements it, but along the way you would need to create a category for each type on the same collection. This would require a different collection at compile time using macros. Overly complicated.
#interface Tomato:NSObject #end
#implementation Tomato #end
#protocol TomatoNSArray <NSObject>
- (Tomato*)objectAtIndexedSubscript:(NSUInteger)index;
- (void)setObject:(Tomato*)tomato atIndexedSubscript:(NSUInteger)index;
#end
// here is the problem, you would need to create one of this for each type
#interface NSMutableArray (TomatoNSArray) <TomatoNSArray>
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
NSMutableArray<TomatoNSArray> *tomatoes = [[NSMutableArray alloc] initWithCapacity:2];
tomatoes[0] = [Tomato new];
tomatoes[1] = [NSObject new]; // warning: incompatible pointer types
}
}
Does Objective-C have an equivalent to java annotations?
Not exactly an equivalent, but there is, and it's better. In Objective-C, the compiler has to store some type and name information in the compiled code (because the language is highly dynamic, a lot of things happen at runtime as opposed to compile time), for example method names ("selectors"), method type signatures, data about properties, protocols, etc. The Objective-C runtime library then has access to this data. For example, you can get the list of properties an object has by writing
id object = // obtain an object somehow
unsigned count;
objc_property_t *props = class_copyPropertyList([object class], &count);
Or you can check what class an object belongs to:
if ([object isKindOfClass:[NSArray class]]) {
// do stuff
}
(Yes, part of the runtime library is itself wrapped into some methods of NSObject for convenience, others only have C function APIs.)
If you specifically want to store custom metadata about an object or a class, you can do that using associated references.
I expect it should be clear now, the answer is NO, not at the moment.
Some people found some alternatives which seem to work in their specific use cases.
But in general there is no comparable feature yet in objective-c. IMHO clang metadata seems to provide a good foundations for this, but as long as there is not support from Apple this will not help, as far as i understood it.
Btw. I guess it should be clear, but just to repeat for all: two changes are required to support annotations as provided in java.
The language need an extension the annotate e.g. methodes, properites, classes, ... in the source code.
A standard interface is required to access the annotated information. This can only provide by apple.
Most alternativ soltuions move the annotation information into runtime and define their own interface. The objective-c runtime provide a standard interface but only with some trick you can annotate properties and still the isse of runtime population.
The typical use case for suche a feature is an IOC container (in Java e.g. Spring) which use the annotated information to inject other objects.
I would suggest to open an feature requrest for Apple to support this.
The answer to your question is that Objective-C does not have a direct equivalent of annotations as found in Java/C#, and though as some have suggested you might be able to engineer something along the same lines it probably is either far too much work or won't pass muster.
To address your particular need see this answer which shows how to construct an array which holds objects of only one type; enforcement is dynamic and not static as with parametric types/generics, but that is what you'd be getting with your annotation so it probably matches your particular need in this case. HTH.
What you need maybe a metadata parser for Objective-C. I have used ObjectiveCAnnotate (compile time retrievable) and ROAnnotation(runtime retrievable).

Is there a way to wrap protocol buffers into Objective-C and still take advantage of inheritance?

I want to use Protocol Buffers in an iOS project. I'm trying to avoid making the whole project into an Objective-C++ fiasco, so I want to wrap the C++ protobuf classes into Objective-C ones. I have several dozen protobuf messages, and while I have done this successfully one class at a time, ideally I would like to use inheritance to minimize the repeated code. I'm new to Objective-C and I haven't used what little I knew of C++ in 10 years, so this has mostly been an exercise in frustration. Below is an example of how I have wrapped a single message.
Code
.proto:
message MessageA {
optional string value = 1;
}
MessageAWrapper.h:
#import <Foundation/Foundation.h>
#interface MessageAWrapper : NSObject
#property (nonatomic) NSString *value;
+ (id)fromString:(NSString *)string;
- (NSString *)serialize;
#end
MessageAWrapper.mm:
#import "MessageA.h"
#import "message.pb.h"
#interface MessageAWrapper ()
#property (nonatomic) MessageA *message;
#end
#implementation MessageAWrapper
- (id)init
{
self = [super init];
if (self) {
self.message = new MessageA();
}
return self;
}
- (void)dealloc {
delete self.message;
self.message = NULL;
}
- (NSString *)value {
return [NSString stringWithUTF8String:self.message->value().c_str()];
}
- (void)setValue:(NSString *)value {
self.message->set_value([value UTF8String]);
}
- (NSString *)serialize {
std::string output;
self.message->SerializeToString(&output);
return [NSString stringWithUTF8String:output.c_str()];
}
+ (id)fromString:(NSString *)string {
MessageA *message = new MessageA();
message->ParseFromString([string UTF8String]);
MessageAWrapper *wrapper = [[MessageAWrapper alloc] init];
wrapper.message = message;
return wrapper;
}
#end
Goal
There is a lot of code here that will be repeated dozens of times in which the only variation is the wrapped class type (init, dealloc, serialize, fromString), so ideally I would like to put it on a parent ProtobufMesssage class instead. Unfortunately I've had no success in making this work because I can't find a way for the parent class to know the class its children are using, which is required for example in init and fromString.
Things I've attempted
struct
template class
void*
Obstacles I've encountered
can't find a way to store a reference to a class/type
can't have any C++ headers or code in the .h file (as this requires the whole project to be Objective-C++)
difficulty keeping references to the protobuf message parents (Message or MessageLite) because they are abstract
As I said I have very little understanding of C++ or Objective-C; most of my experience is with much higher level languages like Python and Java (though I do mostly understand basic C things like pointers).
Is this perhaps not even possible? Am I approaching it wrong or missing something obvious? Any help would be much appreciated. Thanks.
I don't know much about C++ at all, but can't you declare the Objective-C property to be a Message *?
You've already separated the C++ code from the header by declaring the property in the .mm file, the problem you will have is with instance methods named by the compiler (value() and set_value()) and only being valid methods for the subclass. It might help to use the Reflection class to get and set fields by their name. Here is an excerpt from Google's message.h showing this:
Message* foo = new Foo;
const Descriptor* descriptor = foo->GetDescriptor();
const FieldDescriptor* text_field = descriptor->FindFieldByName("text");
assert(text_field != NULL);
assert(text_field->type() == FieldDescriptor::TYPE_STRING);
assert(text_field->label() == FieldDescriptor::LABEL_OPTIONAL);
const Reflection* reflection = foo->GetReflection();
assert(reflection->GetString(foo, text_field) == "Hello World!");
You could create Objective-C -objectForKey: and -setObject:forKey: instance methods that typecheck and get or set the value (confusingly, the key in the case of MessageAWrapper would be #"value"). Your subclasses would not even need to be aware of the C++ code.
You can also separate the creator function in -init and +fromString: method into something like, +_createNewInstance;
+(Message*)_createNewInstance{ return new MessageA(); }
allowing your subclasses of MessageWrapper to reuse all code except for creating the C++ object.
While Objective C has very powerful instrospection capabilities, C++ is more limited. You do have RTTI (Run time type information), but it's not even as powerful as the Objective C counterpart.
However, it might be enough for you. Within your Objective C++ class, you might find the type of you message object with the typeid operator:
if( (typeid(self.message) == typed(foo)){
//doSomething
else if( (typeid(self.message) == typed(bar)){
// doSomething else
}
Maybe the best option is to add another indirection level. Make an Objective C class hierarchy that wraps all your protocol buffer C++ classes and then create another Objective C that uses those classes (as delegates maybe). I believe this might be a better option. Use C++ only for those unavoidable cases.
Good luck!

Objective-c categories

I'm learning Objective-C and now I'm stuck with categories. Here is the code
#import <Foundation/Foundation.h>
#interface NSMutableArray (NSMutableArrayCategory)
-(NSMutableArray *)removeLastObject;
#end
#import "NSMutableArrayCategory.h"
#implementation NSMutableArray (NSMutableArrayCategory)
-(NSMutableArray *)removeLastObject
{
return [self removeObjectAtIndex:[self count] - 1];
}
#end
The problem is that I get
Returning void from a function with incompatible result type 'NSMutableArray' *
What is wrong here ?
You probably want to declare removeLastObject as returning void, not NSMutableArray.
#interface NSMutableArray (NSMutableArrayCategory)
- (void)removeLastObject;
#end
Then the implementation will look like this:
- (void)removeLastObject
{
[self removeObjectAtIndex:[self count] - 1];
}
This matches the other mutation methods on NSMutableArray.
The underlying problem is that removeLastObject is already defined and does what you want (so people don't recreate it). Some of the answers here are a little confusing, however, in that they suggest it's ok to use a category to override an existing method (or at least don't explicitly state that you must not do this). You must not do this. It is poorly defined behavior, and in some cases it is completely undefined behavior. You generally should subclass to override a method.
There is an advanced technique called swizzling that will allow you to do this without a subclass, but it is a very specialized and sometimes fragile technique, not for general use.
But in no case should you use a category to override an existing method.
Im not familiar with objective c. but i imagine that removeObjectAtIndex returns void. so I would try
[self removeObjectAtIndex:[self count] -1];
return self;
return self after removing item..

Objective-C equivalent to Ruby's #define_method?

Is it possible to dynamically define methods in Objective-C like we would in Ruby?
[:failure, :error, :success].each do |method|
define_method method do
self.state = method
end
end
Actually it is possible to do this, although it's not supported by the obj-c syntax, the obj-c runtime provides functions that can do it. The one you want is class_addMethod, but off the top of my head i cannot remember the exact specifics of how. All the runtime methods are documented at developer.apple.com
For the hell of it I banged up a very simple example
#import <objc/objc-class.h>
#interface MyClass : NSObject {
}
#end
#implementation MyClass
#end
id myMethod(id self, SEL cmd, NSString* message)
{
NSLog(message);
return nil;
}
int main(int argc, char *argv[])
{
class_addMethod([MyClass class], #selector(newMethod:), (IMP)myMethod, "v#:#");
[[[MyClass alloc] init] newMethod:#"Hello World"];
return 0;
}
Now strictly speaking i think myMethod should be varargs, and it just happens to be okay to do it the way i am on x86, and may fail on ppc -- but then i could be wrong.
Oh here's the awful type encoding docs
I don't beleive it's possible, because Objective C is, after all, a compiled language. Your "define method" which have to add methods to the table and have a way to compile the method at run time.