iOS: "attempt to insert nil object from objects[1]" when creating dictionary
Asked Answered
T

3

13

I'm creating a custom navigation bar class and customizing it's title attributes using the following code:

self.titleTextAttributes = @{ UITextAttributeFont: bariol,
                              UITextAttributeTextColor: [UIColor whiteColor]
                            };

However, when I run the code, it returns the following error message:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[1]'

I'm using Xcode 4.6 and running on a device using iOS 6.

Tiberius answered 26/2, 2013 at 21:25 Comment(0)
C
7

The parameters of the literals (values and keys of your dictionary) must not be nil.

If you prefer a constructor which is less strict, you might consider using +[NSDictionary dictionaryWithObjectsAndKeys:] instead.

Credenza answered 26/2, 2013 at 21:30 Comment(9)
That's not less strict, it just thinks the arguments have stopped if a nil is found where a key was expected. Notably, if you pass a nil object, you'll get the exact same exception.Soluk
@KevinBallard nonsense. what is returned from [NSDictionary dictionaryWithObjectsAndKeys:@"a", @"a", nil, @"b", nil];? it stops reading at the first nil object argument.Credenza
Sorry I meant object when I said key (darn flipped method). It can't distinguish between a nil object and the sentinel nil. Try using nil for a key and see what I mean: [NSDictionary dictionaryWithObjectsAndKeys:@"anObj", @"aKey", @"anotherObj", nil, nil].Soluk
@KevinBallard yes, i know what happens if a key is missing when +[NSDictionary dictionaryWithObjectsAndKeys:] is used. that does not apply to this context because if the framework constant keys UITextAttributeFont or UITextAttributeTextColor were nil... a lot of programs would break. so yes, people use +[NSDictionary dictionaryWithObjectsAndKeys:] to short circuit dictionary construction parameters where literals cannot in the presence of optional entries. Literals OTOH, forbid that entirely -- all keys and values must be valid objects.Credenza
Most people tend to think that the nil-object-shortcutting behavior is actually bad because it can silently truncate your dictionary.Soluk
@KevinBallard I'm not sure about "Most people" in this case -- never polled. You could infer hesitation/caution from my word choice in the answer. I know a lot of objc devs really like nil as a magic or optional value in system APIs and in their programs -- I think it hurts more than helps. That is to say, I very much favor the stricter semantics -- but I've met a lot of objc devs who prefer it lax.Credenza
I switched to dictionaryWithObjectsAndKeys:, works better than @{} for the time being.Tiberius
Got exactly same problem and fix with dictionaryWithObjectsAndKeys: Thanks.Ionize
This is not a good suggestion, more subtle bugs may arise from using that method, like missing data if for example you would populate a response to a server and send as is. The best action is to check data before inserting into a dict.Aftershaft
S
11

It sounds like your bariol object is nil. You can't store nil in a dictionary.

Edit:

Actually, are you sure that's the right line of code? Your error references NSPlaceholderArray, which suggests it's a problem with a @[] literal, not a @{} literal.

Soluk answered 26/2, 2013 at 22:34 Comment(3)
@justin: dictionaryWithObjects:forKeys:count: doesn't use NSArrays. It uses C arrays.Soluk
whoops - nonsense returned :) it's still possible that NSArrays are created in the process of constructing the dictionary (or calling another constructor), thus the message of the exception.Credenza
@justin: An NSDictionary literal does not construct intermediate NSArrays. So unless -setTitleTextAttributes: is doing something funky, that's not the case.Soluk
C
7

The parameters of the literals (values and keys of your dictionary) must not be nil.

If you prefer a constructor which is less strict, you might consider using +[NSDictionary dictionaryWithObjectsAndKeys:] instead.

Credenza answered 26/2, 2013 at 21:30 Comment(9)
That's not less strict, it just thinks the arguments have stopped if a nil is found where a key was expected. Notably, if you pass a nil object, you'll get the exact same exception.Soluk
@KevinBallard nonsense. what is returned from [NSDictionary dictionaryWithObjectsAndKeys:@"a", @"a", nil, @"b", nil];? it stops reading at the first nil object argument.Credenza
Sorry I meant object when I said key (darn flipped method). It can't distinguish between a nil object and the sentinel nil. Try using nil for a key and see what I mean: [NSDictionary dictionaryWithObjectsAndKeys:@"anObj", @"aKey", @"anotherObj", nil, nil].Soluk
@KevinBallard yes, i know what happens if a key is missing when +[NSDictionary dictionaryWithObjectsAndKeys:] is used. that does not apply to this context because if the framework constant keys UITextAttributeFont or UITextAttributeTextColor were nil... a lot of programs would break. so yes, people use +[NSDictionary dictionaryWithObjectsAndKeys:] to short circuit dictionary construction parameters where literals cannot in the presence of optional entries. Literals OTOH, forbid that entirely -- all keys and values must be valid objects.Credenza
Most people tend to think that the nil-object-shortcutting behavior is actually bad because it can silently truncate your dictionary.Soluk
@KevinBallard I'm not sure about "Most people" in this case -- never polled. You could infer hesitation/caution from my word choice in the answer. I know a lot of objc devs really like nil as a magic or optional value in system APIs and in their programs -- I think it hurts more than helps. That is to say, I very much favor the stricter semantics -- but I've met a lot of objc devs who prefer it lax.Credenza
I switched to dictionaryWithObjectsAndKeys:, works better than @{} for the time being.Tiberius
Got exactly same problem and fix with dictionaryWithObjectsAndKeys: Thanks.Ionize
This is not a good suggestion, more subtle bugs may arise from using that method, like missing data if for example you would populate a response to a server and send as is. The best action is to check data before inserting into a dict.Aftershaft
C
5

This error seems to be somewhere else. It's pointing to an array error at object '1'. In your case you have a dictionary and object '1' is UITextAttributeTextColor: [UIColor whiteColor] which will never be nil.

Certainty answered 4/6, 2015 at 0:33 Comment(2)
yes, for those who come looking to confirm the [<number>] on the exception message, it is the 0-indexed array offset of the failing (nil) object. Tested with: NSString *str = nil; NSDictionary *foo = @{NSFontAttributeName:str,NSForegroundColorAttributeName:@"booboo" };Froufrou
@Froufrou BOOM! Nice one.Ardys

© 2022 - 2024 — McMap. All rights reserved.