2

I have a strongly typed collection:

NSMutableArray<SupportClass *> *_items;

I need to put a null-like object into it. When you need it with a non-typed collection in ObjC - you use [NSNull null] object:

[_items replaceObjectAtIndex:index withObject:[NSNull null]];

But with the typed one, I'm getting the following warning on that line:

Incompatible pointer types sending 'NSNull * _Nonnull' to parameter of type 'SupportClass * _Nonnull'

I understand why the warning arises in this sample with the mix of the typed collection and the [NSNull null] object.

What is the proper way to have a strongly typed collection with complile time type checks and, at the same time, be able to put null-like objects into it?

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
  • strongly typed means that it only contains objects of the specified type. If you want to put in other objects, it is not strongly typed anymore. You could define it as just `NSMutableArray *`, then the warning will disappear. That would also be cleaner. Writing `NSMutableArray *` is a promise to your co-workers (or to whoever reads your code afterwards) to only ever put `SupportClass *`-objects into this collection. Nothing more, nothing less. – Michael Jun 02 '17 at 22:02
  • As I mentioned in the question, I understand **why** the warning is produced. But all programming languages known to me allows to have a typed collection with compile time type checks and at the same time being able to put null objects into it. So I'm just looking for a way to do the same with ObjC. – Alexander Abakumov Jun 02 '17 at 22:08
  • 2
    You would need to create some sort of `NullSupportClass` subclass of `SupportClass`. This could be a singleton (which is what NSNull is) so you could compare the array element against the NullSupportClass singleton to check for "null". You possibly have the wrong data structure in an array, however. – Paulw11 Jun 03 '17 at 01:57
  • You can create some predicate-like method in your SupportClass like -(BOOL) isEmpty which returns YES if instance doesn't have any properties set. – Vladimir Vodolazkiy Jun 03 '17 at 07:43
  • @AlexanderAbakumov: you may think you understand, but the compiler disagrees with you. And I agree with the compiler ;) The problem you are facing is a classical XY-problem. – Michael Jun 03 '17 at 10:52
  • @VladimirVodolazkiy: this would just turn a technical software mistake into a software design mistake – Michael Jun 03 '17 at 10:54
  • @Michael: Please stick to the question I asked. I'm not trying to find out who is right: me or the ObjC compiler. I just need to get the job done and looking for an advice of how experienced people achieve in ObjC what is never an issue in the majority of other programming languages. – Alexander Abakumov Jun 03 '17 at 19:32
  • @AlexanderAbakumov: i'm trying. there is *no* proper way to insert null-values into a strongly-typed objc-collection. It just should not be done, and for this reason you get the warning. The warning will not go away. Maybe that's not the answer you want to hear, but it's the only answer you will ever get. – Michael Jun 05 '17 at 08:54
  • @Michael: As I said multiple times, I perfectly see your point: one must NOT put `nil` or `[NSNull null]` into the strongly typed collection in ObjC and as my question says I understand why. **But there are at least 3 alternative approaches** to achieve what I'm looking for (see previous commenters for two of them and another one I have in my mind), better or worse ones. My question is: Which one is the preferred to deal with the issue from the experienced ObjC developer point of view? – Alexander Abakumov Jun 05 '17 at 16:36

1 Answers1

2

I have a strongly typed collection:

NSMutableArray<SupportClass *> *_items;

Combining two of your comments:

But [the majority of] programming languages known to me allows to have a typed collection with compile time type checks and at the same time being able to put null objects into it. So I'm just looking for a way to do the same with ObjC.

The trouble you are facing is because you are using a recent addition to Objective-C designed to improve inter-working with Swift, and Swift does not allow you to mix in nulls in this way into your "strongly typed collection".

The Swift model is generally to replace the "reference or null" model you are used to with the "non-null reference and optional" model. In Swift a reference to SomeClassType is non-null, while the type SomeClassType? is shorthand for Optional<SomeClassType>. The Optional type has two cases: .none and .some(v), and Swift allows you to test for .none by comparing to nil.

Swift did not invent this model, (like most parts of the language) it is inherited from others, like the many functional languages which are strong users of such tagged unions.

My question is: Which one is the preferred to deal with the issue from the experienced ObjC developer point of view?

Using NSNull, as you tried. This was the Apple recommended way, the very raison d'être for NSNull, but dates from before Apple introduced the lightweight generics to help bridge between Obj-C and Swift.

How do you use the "reference or null" model in the post lightweight generics world? You I think know most of the alternatives, they include:

  • Don't. Either don't use the strongly typed collections in Obj-C, or use them following the Swift model.
  • Use Swift. If you want static strong typing over runtime typing use a language based on it.
  • Use a subclass. Override every method/property to throw an illegal use of null exception. Add an isNull predicate. Etc.
  • Use a distinguished object. Don't like inheritance, then just create a unique instance of your class to act as the null case. Add appropriate methods/properties to support it.
  • Build your own Optional in Obj-C.
  • Break through the paper wall. Lightweight generics really are a paper-thin layer over the standard collections, just break through it if you must.
  • Etc.

There is no single "right way" to address your issue. Look at your design, decide whether the "reference of null" model is key, pick a solution that suits your circumstances.

HTH

Community
  • 1
  • 1
CRD
  • 52,522
  • 5
  • 70
  • 86