Redefine nil in smalltalk to respond any message - smalltalk

I want to redefine smalltalk's nil to work like the one in objective-c. So when nil receives a message that it can't handle, it returns nil. Now I know that nil is just a shortcut for UndefinedObject but is there anything like method_missing in Ruby so I can redefine it in UndefinedObject to always return nil?

The method you are looking for is called doesNotUnderstand: in Smalltalk. You can indeed implement:
UndefinedObject>>doesNotUnderstand: aMessage
^ nil
However, keep in mind that this affects the complete system and might have subtle side effects or introduce bugs in other parts of the system.
Also note that UndefinedObject is not a primitive type, but a normal class inheriting from Object. Therefor nil already understands a large number of messages and might not behave as you would expect coming from Objective-C.

Consider creating your own Null singleton class that implements #doesNotUnderstand: so that you don't modify nil. Make the super class nil (like Object).
Answer something like '^Null instance' instead of '^nil' in cases where you want it.
Null instance badMethod --> nil

If you're the only person who will ever work on this code, I say go for it.
On the other hand, if this is a product owned by some company which is not a synonym for "you", and someone else may at some time have to maintain this, I strongly recommend that you NOT do this. Modifying classes at the heart of Smalltalk is one of THE classic ways to blow your toes off. (I knew a guy once who did this. He was not happy...and always limped a bit after that. Funny old thing, life...).
Share and enjoy.

Related

Overhead/risks of passing messages to nil

I wonder if there are any risks about relying on the fact that passing messages to nil objects does nothing in objective C.
In my code I have a lot of weak references to UIKit and other objects that could be niled anytime. Since I came from C++ and languages where referencing NULL is the quickest way how to crash the program I always tend to be cautious and write defensive codelike this:
if (view)
[view removeFromSuperview];
Is there actually any point of checking if the view is not nil before passing messages to it? I know that in this case (removing a subview from superview it is safe), but are there any situation where this could be a problem?
How about performance implications? Is the passing a message to nil actually free and really does nothing? What if I let's say do it thousand times in a loop?
Method calls in Objective-C are handled by translating them into calls to objc_msgSend(), which first checks to see if the receiver is nil, and then it translates this to a method call to a special "nil" object. (See blog post: Nil). The method call is designed to return 0 for all types. See Working with Objects:
Note: If you expect a return value from a message sent to nil, the return value will be nil for object return types, 0 for numeric types, and NO for BOOL types. Returned structures have all members initialized to zero.
So it is always safe. Unless you support legacy systems...
For legacy coders...
It used to be that objc_msgSend() would only return 0 in the usual register for scalar function returns. The ABI on PowerPC specified that r3 would be used for integer and pointer returns, and sometimes for the first field of a structure if the structure was packed into registers. However, different registers were used for floating point numbers, and these would not get initialized, and structs would not always get initialized.
This was an extremely rare problem, but it has been solved anyway.
Passing messages to nil is quite normal and expected in Objective-C. You generally should not protect against it. Keep in mind, however, that passing nil to some methods (addObject: for instance) will crash, so you do need to think about when a variable can and cannot be nil.
objc_msgSend is highly optimized to handle messaging nil. Greg Parker has done a nice job laying out the different versions that have existed since 10.0. The very first assembly instruction in objc_msgSend is a test for nil and an immediate return.
EDIT:
See Dietrich Epp's answer regarding how this works for non-object returns. He makes a great point that you do need to be careful in that case.
According to Apple Documentation
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html
A nil value is the safest way to initialize an object pointer if you don’t have another value to use, because it’s perfectly acceptable in Objective-C to send a message to nil. If you do send a message to nil, obviously nothing happens.
This means that You can send what you want to nil objects and nothing will happen
Greg Parker, Apple's runtime guy, wrote a blog post on the subject here: http://sealiesoftware.com/blog/archive/2012/2/29/objc_explain_return_value_of_message_to_nil.html
I consider this even more definitive than an Apple link would be, since it's also dated.
Messaging nil will return 0 for any integer up to 64-bits, floating point up to long double, pointer, struct or _Complex. Note that calling objc_msgSend_stret directly does not have the same behaviour in all cases.
Since the runtime needs to look up the class to dispatch the message correctly, I imagine it discovers the instance is nil fairly early.

Is it kosher to use NSNull category trick in order to avoid [NSNull performSelector:...] problems?

In our project, we occasionally get our iPhone app to crash when there is something on the network returns JSON with nil in it. Of course, we do have a helper class, which takes care of problems like that. However, people are error-prone and do call objectForKey on NSDictionary instead of our own stringForKey or dateForKey etc.. Now, there is a class to kill all problems like that, once and for all: https://github.com/nicklockwood/NullSafe
My question is: Is NullSafe is really safe? Because sometimes you do want your program to crash if the logic is wrong and you get NSNull. Just ignoring the problem hides it. The app probably will not crash, but, in some cases, will do something weird.
Now I am leaning towards not using this class and just making sure that our JSON NSDictionaries is filtered of all NSNulls BEFORE we try to parse get the values (It could affect performance though).
What do you guys think?
That class is safe in terms of not crashing the application when you send some message to it. It behaves much like nil value.
This class does not solve bugs! If you may get NSNull you should act as it is there and handle that case.
Once I used such class (also because of JSON), but I put NSLog (or ratcher breakpoint) into the -forwardInvocation: method to see from where and why it was called. I wouldn't use this in production.
You also asked about performance. Not sure what takes more: removing NSNulls from an array or searching all classes for their method signatures ;)

Best way to represent a maybe type in Objective C without using pointers, (a pointer to a pointer is not an object?)

What is the best way to represent a maybe type in Objective C without using pointers?
I can not simply use a pointer to a pointer to an object, because a pointer to a pointer to an object is not an object, and I need it to be an object.
I know one way to do this is to have a custom class for each object I have, which would result in classes like, MaybeEmployee, MaybeOrderStatus, and many more custom classes. This would work, but it seems kludgy, and not like a very good solution at all.
The second way to do it, having simply a Maybe class also seems wrong. The lack of type safety is just plain bad.
lef2 has the right idea. Use NSNull to represent the "maybe not" case.
The simplest way to handle it is to make your method return an object of type id, but as you say, that sacrifices type safety.
I'd suggest creating an ancestor class MaybeClass and make all your classes derive from that. Then you can create a specific subclass maybeNot that is really an NSNull.
Note that you can also just use standard objects, and return nil when the result of a method call is empty. Objective C handles nil object pointers much more cleanly than a lot of other languages. It's perfectly valid to send messages to a nil object. They just get dropped.
I'm not sure exactly what a "maybe type" means to you, but is there a reason why id isn't sufficing?
I am also unsure what you mean by a "maybe type"! Could a protocol be what you want with some classes implementing the protocol and others not. They you can check if objects implement it or not [yourObject conformsToProtocol:#protocol(yourProtocol)]. I hope this helps but if not some more clarification would be good.

How to test if a *void pointer points to NSObject in Objective C

I would like to know witch is the best practice to test if void pointer is actually an objective C object pointer (NSObject*)...
- (id)initWithExecPath:(NSString*)executePath withArgs:(NSArray*)args identifier:(NSString*)identifierString contextInfo:(void*)contextInfo {
// I would like to check here if contextInfo is an NSObject
}
Thanks...
Check out this post from the CocoaWithLove site:
In this post, I look at an approach for testing if an arbitrary
pointer is a pointer to a valid Objective-C object. The result from
the test is not absolutely accurate and can interfere with gdb
debugging if the pointer isn't a valid memory location, so this is not
something you'd want to do often (and certainly not in production
code). But it can be a handy debugging tool for when you're staring
blindly at memory you didn't allocate.
The answer is that no you can't provide a general test for "is an Objective-C object". Any such test would have to examine the internal structure of an object and is therefore fragile by definition. There is also the possibility of being handed a random piece of memory that looks like an Objective-C object but isn't. e.g. a recently deallocated object.
There is no reliable way to determine this. Also, any API that takes a context pointer shouldn't care what it is or what it points to, it shouldn't do anything with it other than pass it back to the caller as context.
Perhaps you are asking the wrong question; what exactly do you want to do once you know it is an NSObject?

Way to get return type of a method in Objective-C?

I'm writing a generic 'attribute/key editor' view class on iOS, and it checks the type of the editing key using [objectForKey isKindOfClass:[NSDate class]], for example. I just ran into a wall when I realized that will fail if objectForKey is nil. Is there a way to get the class/return type for a generic Objective-C property, even if said property is nil? I know about method_getReturnType in the Objective-C run-time, but that sounds like overkill for what I need.
You can’t. Although return type information for methods is available, the return type encoding for methods which return objects is simply #, meaning “object reference”.
What you're asking for doesn't make sense.
Remember that a name alone does not identify a method. Objects respond to those messages (or not); a method does not exist alone, only as part of an object (or class).
Having no object, you cannot tell from it what hypothetically sending a message to an object would return.
ETA: How is it that you could be editing the attributes of something, but not have the object to edit in order to examine its properties? It seems like you have a bug somewhere else.
I know about method_getReturnType in the Objective-C run-time, but that sounds like overkill for what I need.
There are two ways. If you want to support informal properties (KVC-compliant accessor methods with no #property declaration), that's exactly what you need. If you only care about formal properties (#property), use the property_getAttributes function.
Can't you just first check to make sure that objectForKey != nil, and the continue with the isKindOfClass checking? If you make sure that the object doesn't equal nil first you can easily check or safely exit without any failures.
I don't know where your data is coming from, but you might want to consider supplanting nil with NSNull and that will allow you to gain NSObject-like properties on something that is technically null
But the null check becomes more pain in the ass.
It goes from object != nil to
(NSNull *)object != [NSNull null]