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.

beakr
  • 5,709
  • 11
  • 42
  • 66

3 Answers3

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.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • @justin: `dictionaryWithObjects:forKeys:count:` doesn't use `NSArray`s. It uses C arrays. – Lily Ballard Feb 26 '13 at 23:56
  • 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. – justin Feb 27 '13 at 00:04
  • @justin: An `NSDictionary` literal does not construct intermediate `NSArray`s. So unless `-setTitleTextAttributes:` is doing something funky, that's not the case. – Lily Ballard Feb 27 '13 at 00:22
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.

justin
  • 104,054
  • 14
  • 179
  • 226
  • 12
    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. – Lily Ballard Feb 26 '13 at 22:34
  • @KevinBallard nonsense. what is returned from `[NSDictionary dictionaryWithObjectsAndKeys:@"a", @"a", nil, @"b", nil];`? it stops reading at the first nil object argument. – justin Feb 26 '13 at 22:51
  • 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]`. – Lily Ballard Feb 26 '13 at 22:54
  • @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. – justin Feb 26 '13 at 23:02
  • 7
    Most people tend to think that the `nil`-object-shortcutting behavior is actually bad because it can silently truncate your dictionary. – Lily Ballard Feb 26 '13 at 23:03
  • @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. – justin Feb 26 '13 at 23:25
  • 1
    I switched to `dictionaryWithObjectsAndKeys:`, works better than `@{}` for the time being. – beakr Feb 27 '13 at 01:49
  • 1
    Got exactly same problem and fix with dictionaryWithObjectsAndKeys: Thanks. – majorl3oat Apr 29 '14 at 04:27
  • 2
    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. – lkraider Jun 25 '15 at 23:33
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.

Andres Canella
  • 3,706
  • 1
  • 35
  • 47
  • 9
    yes, for those who come looking to confirm the [] 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" }; – robm Sep 12 '15 at 06:04
  • 1
    @robm BOOM! Nice one. – Benjohn Feb 08 '17 at 14:42