-2

As a logic continuing of the question: Objective-C dynamic_cast?

From there we learned we can do the following:

MyClass *safeObject = objc_dynamic_cast(originalObject, MyClass);

Lets suppose the hierarchy: A -> B, A -> C, A -> D.

The function is

-(void)someStuffWith:(A*)object;

where Object is never A, but always B,C or D.

The question is how to represent in Objective-C (on iOS particularly) the following idea:

Class class = [object class];
class *safeObject = objc_dynamic_cast(object, class);

where "class" is either B,C, or D.

Community
  • 1
  • 1
Dumoko
  • 2,614
  • 3
  • 25
  • 34

2 Answers2

2

This isn't the way you should do it. Instead you should be doing:

- (void)someStuffWith:(id<MyProtocol>)object;

And MyProtocol defines a list of all methods that must exist on object, and perhaps some optional methods as well (which you can check for with [object respondsToSelector:]).

Or perhaps there is another solution, it would help if you told us a bit more about what your actual problem is instead of how you want to solve it. Objective-C is 30 years old and you will never come across a problem that the language doesn't have a perfectly good solution for. Stop trying to invent new solutions and learn the tried and true ones. :-)

Abhi Beckert
  • 32,787
  • 12
  • 83
  • 110
  • http://stackoverflow.com/questions/20653604/activerecord-crash-on-validating-name-field . Some subclasses have a property "name". The parent class(ActiveRecord) doesn't. I am trying to see if it crash if I actually cast the ActiveRecord object to the actual class the aRecord is the instance of. Mb this way the "valueForkey" for "name" will stop crashing. That's why your solution is also not fitting my problem, but thank you for trying to help me out! Looking forward on your ideas! – Dumoko Dec 18 '13 at 10:13
  • 2
    `isRespondsToSelector` will help you – Cy-4AH Dec 18 '13 at 10:14
  • it will not. NSObject always responds to selector "valueForKey". My problem is that it crashes on doing so for a certain property. Please note, it does it SOMETIMES. The percent of reproducing is very small, around 0.01% of the times it validates a record. – Dumoko Dec 18 '13 at 10:15
  • 1
    @Dumoko I say about `[object isRespondsToSelector:@selector(name)]` – Cy-4AH Dec 18 '13 at 10:16
  • 1
    @Dumoko Casting will not help you, you don't understand how the language works. Variable types *only exist at compile time* in objective-c and are completely erased by the compiler for the actual executed code. If you want to enforce a "name" method, you need to check if it has a "name" method. Or else you have some other unrelated bug scrambling your RAM. The correct approach is define a protocol with "name" in it, but even then there is no guarantee. A variable is just a memory location, any data or perhaps random bullshit could exist in RAM at that location. You have to check. – Abhi Beckert Dec 18 '13 at 10:27
  • *please read CAPS as underlining, not shouting*. About"you don't understand how the language works." yes yes, you may be right. I understand and i know all that you wrote about RAM, compile time, etc. BUT - the bug exists. It doesn't care about knowledge, about compile time, about anything that is Objective C. It crashes by getting a NAME from a variable of a class that DOES have a NAME field, and I know that this field HAS good data. It just CRASHES while getting it. So all the talks about "you are doing it wrong" - irrelevant. I have a crazy crash on low level, and I do everything to fix. – Dumoko Dec 18 '13 at 10:34
  • id aValue = [aRecord valueForKey:aField]; all that simple. And happens only sometimes. And please, don't offtop. This discussions should be here http://stackoverflow.com/questions/20653604/activerecord-crash-on-validating-name-field – Dumoko Dec 18 '13 at 10:37
  • @Cy-4AH i tried with respondsTOselector, it always returns YES, even before crash. So it says "yeah i can respond to that", and crashes in the next row. – Dumoko Dec 18 '13 at 11:04
  • @Dumoko it doesn't have good data. If it had good data it would not crash. You need to start looking at the RAM contents when the exception is thrown. Use the debugger. https://developer.apple.com/library/ios/recipes/xcode_help-debugger/articles/viewing_memory.html – Abhi Beckert Dec 18 '13 at 11:39
  • whatever you say. I used po on it. It does has good valid data. but i will check everything that might come at least somehow useful in the link. – Dumoko Dec 18 '13 at 12:31
0

You are using too complicated stuff. All is simple:

if ([object isKindOf:[B class]])
{
    B* bObject = (B*)object;
}
Cy-4AH
  • 4,370
  • 2
  • 15
  • 22
  • I don't want to use if blocks. I have around 15 subclases, and the number is growing with the needs of the apps. hardcoding 15 and more if blocks is not a good solution. But thank for your time. – Dumoko Dec 18 '13 at 10:08
  • @Dumoko any way you need 15 different handlers for yours function `-(void)someStuffWith:(A*)object;` Try think different. In your's case you need method someStuff in A class, and subclasses should implement it. – Cy-4AH Dec 18 '13 at 10:13
  • I will not need anyway 15 different handlers for my functions. When I will find a method to declare variables of dynamic class, I will have just 2 rows: Class class = [object class]; *safeObject = objc_dynamic_cast(object, class); and not 15 handlers/functions/ifelses. I appreciate your ideas about thinking different, but please see the last 2 rows in the question, mb that way you will understand. – Dumoko Dec 18 '13 at 10:27
  • @Dumoko if you use just single * in yours handler, that why not define method as `-(void)someStuffWith:(*)object;`? – Cy-4AH Dec 18 '13 at 12:55
  • It is not single class. Please reread the question. I will edit so no more question like your will appear. – Dumoko Dec 18 '13 at 13:32