This nil-swallowing behaviour works really well with the "out error parameter" pattern of Cocoa methods. In short, methods that can fail have a signature like:
- (id)thingThatSometimesWorks:(NSError *)error;
You can chain these to your heart's content. The one that fails sets the error and returns nil; following messages are sent to nil which does nothing and a particular characteristic of doing nothing is that it doesn't overwrite the error that was set. So you still get to see the error when the workflow finishes.
As an objective-C programmer, I also have a tool in my toolbox which gives NSNull the same message-swallowing behaviour as nil.
I mean this with love, this extension to NSNull gives me a brain aneurism. If I had this in my codebase I wouldn't be able to trust anything in a collection.
You might want to return NSNull instead of nil (easy to do: in fact I extracted this from an object in which the nil-return value is configurable but simplified it for the post), in which case it becomes map-safe because NSNull->NSNull on map.
I use this pattern because then I can trust _everything_ in a collection. If an object, even an object that represents emptiness, receives a message, it will handle it and do something, even where that something represents emptiness.
You're better off having an operator in your language that explicitly chains together methods returning Result<T,E>s. That way, you can easily get this behavior if that's what you want, but it's clear from reading the code that it's intentionally not quite a simple chain of method calls.
- (id)thingThatSometimesWorks:(NSError *)error;
You can chain these to your heart's content. The one that fails sets the error and returns nil; following messages are sent to nil which does nothing and a particular characteristic of doing nothing is that it doesn't overwrite the error that was set. So you still get to see the error when the workflow finishes.
As an objective-C programmer, I also have a tool in my toolbox which gives NSNull the same message-swallowing behaviour as nil.
@implementation NSNull(GJLNilReceiver)
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { return [super methodSignatureForSelector:aSelector] ?: [NSMethodSignature signatureWithObjCTypes:"@@:"]; }
- (void)forwardInvocation:(NSInvocation *)anInvocation { [anInvocation invokeWithTarget:nil]; }
@end