0

I'm getting started to use User Defaults on Cocoa and I'm getting an [NSConcreteData alphaComponent]: unrecognized selector sent to instance 0x100123660 error. Here is the source code :

AppDelegate.m file :

- (void)awakeFromNib{
NSColor *myColor = [NSColor greenColor];
[PreferencesController setDefaultColor:myColor];
NSColor *color = (NSColor *)[PreferencesController defaultColor];
NSLog(@"Default color : %@ - %@",(NSColor *)color, [NSColor greenColor]);
[tableView setBackgroundColor:color];
[colorWell setColor:color];
}

PreferencesController.m file :

+ (NSColor *)defaultColor{
NSColor * aColor;
NSData *theData=[[NSUserDefaults standardUserDefaults]      valueForKey:TableViewBackgroundColorKey];
if (theData != nil)
    aColor = (NSColor *)[NSUnarchiver unarchiveObjectWithData:theData];
return aColor;
}

+ (void)setDefaultColor:(NSColor *)color{
NSData *theData=[NSArchiver archivedDataWithRootObject:[NSArchiver archivedDataWithRootObject:color]];
[[NSUserDefaults standardUserDefaults] setObject:theData  forKey:TableViewBackgroundColorKey];
}

The return value of the NSLog is :

<040b7374 7265616d 74797065 6481e803 84014084 8484074e 53436f6c 6f720084 84084e53
4f626a65 63740085 84016301 84046666 66660001 000186> - NSCalibratedRGBColorSpace 0 1 0 1

So the value returned by + (NSColor *)defaultColor is not an NSColor, and certainly not [NSColor greeenColor].

I'm also getting the error -[NSConcreteData alphaComponent]: unrecognized selector sent to instance 0x100184050, which I think must be caused by not returning an NSColor for the method mentioned.

Please help me to debug.

Thanks.

  • what is PreferencesController ? – Anoop Vaidya Jan 04 '13 at 17:43
  • How did you set the value for `MDCTableViewBgKey` in `NSUserDefaults` in the first place? You are unarchiving an NSData instead of an NSColor, so the problem probably comes from when you archived it and set it. – Kurt Revis Jan 04 '13 at 18:15
  • Well PreferencesController is my custom class of NSWindowController and MDCTableViewBgKey is set as an extern string : NSString * const MDCTableViewBgKey = @"TableViewBackgroundColor". But I don't get what you mean by saying "You are unarchiving an NSData instead of an NSColor". –  Jan 05 '13 at 19:22
  • The set method is : `+ (void)setDefaultColor:(NSColor *)color{ NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color]; [[NSUserDefaults standardUserDefaults] setObject:colorData forKey:MDCTableViewBgKey]; }` –  Jan 05 '13 at 19:30

1 Answers1

0

You'll have to handle NSColor in a special way, when storing it in user defaults. NSColor is not an object that can be represented in an property list; see Storing NSColor in User Defaults for code examples.

SAE
  • 1,609
  • 2
  • 18
  • 22
  • Using the link, I've got 2 new error : `Default color : (null)` (while it should be the white color) and `*** Assertion failure in -[NSColorWell setColor:], /SourceCache/AppKit/AppKit-1187.34/AppKit.subproj/NSColorWell.m:500`. No idea what that means. –  Jan 05 '13 at 19:49
  • The code has become : `+ (NSColor *)defaultColor{ NSColor * aColor =nil; NSData *theData=[[NSUserDefaults standardUserDefaults] dataForKey:MDCTableViewBgKey]; if (theData != nil) aColor =(NSColor *)[NSUnarchiver unarchiveObjectWithData:theData]; return aColor; }` –  Jan 05 '13 at 19:50
  • and `+ (void)setDefaultColor:(NSColor *)color{ /*NSData *colorData = [NSKeyedArchiver archivedDataWithRootObject:color]; [[NSUserDefaults standardUserDefaults] setObject:colorData forKey:MDCTableViewBgKey];*/ NSData *theData=[NSArchiver archivedDataWithRootObject:MDCTableViewBgKey]; [[NSUserDefaults standardUserDefaults] setObject:theData forKey:MDCTableViewBgKey]; };` –  Jan 05 '13 at 19:52
  • In your last comment, the argument for `archivedDataWithRootObject` shouldn't be the key, but the object: `NSData *theData=[NSArchiver archivedDataWithRootObject:color];` – SAE Jan 06 '13 at 13:28
  • Okay but still, there is a little problem when it logs the color : I'm getting `<040b7374 7265616d 74797065 6481e803 84014084 8484074e 53436f6c 6f720084 84084e53 4f626a65 63740085 84016301 84046666 66660001 000186>` instead of `NSCalibratedRGBColorSpace 0 1 0 1` just after the line (added) `[PreferencesController setDefaultColor:[NSColor greenColor]]`. The first object is not an NSColor if I'm right. Why `+(NSColor *)defaultColor`doesn't return an NSColor? –  Jan 08 '13 at 12:44
  • Are sure, that setDefaultColor is correctly called? Do you have a setter method for defaultColor? Try `NSColor *myColor = [NSColor greenColor]; [PreferencesController setDefaultColor:myColor];` – SAE Jan 08 '13 at 13:13
  • Nope, nothing changed with your code. But I don't see the difference between. –  Jan 08 '13 at 13:58
  • Could you please update your post with the recent code. I lost the overview through the changes you made. – SAE Jan 08 '13 at 15:03
  • Sorry, you're right it was quite messed up. The code is updated. Thanks for your patience. –  Jan 08 '13 at 16:39
  • Add to recap, the problem is that I'm getting `<040b7374 7265616d 74797065 6481e803 84014084 8484074e 53436f6c 6f720084 84084e53 4f626a65 63740085 84016301 84046666 66660001 000186> - NSCalibratedRGBColorSpace 0 1 0 1`for the log and not `NSCalibratedRGBColorSpace 0 1 0 1 - NSCalibratedRGBColorSpace 0 1 0 1` as it should be. –  Jan 08 '13 at 16:41
  • In `setDefaultColor` you are encapsulating the NSColor twice in this line: `NSData *theData=[NSArchiver archivedDataWithRootObject:[NSArchiver archivedDataWithRootObject:color]];` - it should be `NSData *theData=[NSArchiver archivedDataWithRootObject:color];` – SAE Jan 08 '13 at 17:22
  • Okay, this was actually the problem but when I delete the lines `NSColor *myColor = [NSColor greenColor]; [PreferencesController setDefaultColor:myColor];` to use the previous saved user default, I still get the same error. –  Jan 08 '13 at 18:08
  • ??? When you don't call anywhere `setDefaultColor` how should `defaultColor` return a valid result? If it's not set in the defaults, `defaultColor` will always return `nil`. You'll have to set the default value *somewhere* initially by calling `setDefaultColor` and you can then change it later. E.g. test in `applicationDidFinishLaunching` if the value is set and set it to default if not. – SAE Jan 08 '13 at 18:21
  • I'm calling `- setDefaultColor:(NSColor *)` in the `+ (void)initilize` method : `[PreferencesController setDefaultColor:[NSColor whiteColor]]`. –  Jan 08 '13 at 19:17
  • I don't think that this method (especially with this signature) ever get's called since the init of NIB is done transparently. Put the line into `awakeFromNib`. – SAE Jan 08 '13 at 20:23
  • a) Since I answered your original question and debugged it further, I would appreciate, when you accept my answer. – SAE Jan 08 '13 at 20:35
  • b) *What* exactly doesn't work? You changed greenColor with whiteColor and it stopped working? Can't be. – SAE Jan 08 '13 at 20:38
  • I've just deleted the lines `NSColor *myColor = [NSColor greenColor]; [PreferencesController setDefaultColor:myColor];` to use the setter defaults. –  Jan 08 '13 at 21:07
  • Unfortunately we can't move this thread to a chat, since your rep is too low... Copy your complete code to a [gist](https://gist.github.com), post the link and I'll have another look. – SAE Jan 08 '13 at 22:43
  • Here is the [link](https://gist.github.com/f3f91aba81f6e7003b11). But the code in the gist is the whole code of the app. The only problem is the part dealing with user defaults. –  Jan 09 '13 at 08:15
  • I commented on the gist page. Let's move to that; this is not the right place to chat. – SAE Jan 09 '13 at 16:27