Question

I'm trying to implement saving of user preferences in my OS X app. I have an NSTableView which stores its data to my .plist file, but I have troubles loading same data back to my NSTableView.

My model object:

#import <Foundation/Foundation.h>

@interface UserKeys : NSObject <NSCoding>

@property (nonatomic, copy) NSString *userKeyName;
@property (nonatomic, copy) NSString *userApi;
@property (nonatomic, copy) NSString *userCode;

@end

and its implementation:

#import "UserKeys.h"

@implementation UserKeys

- (id)init
{
    self = [super init];
    if (self) {
        //
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        self.userKeyName = [aDecoder decodeObjectForKey:@"userKeyName"];
        self.userApi = [aDecoder decodeObjectForKey:@"userApi"];
        self.userCode = [aDecoder decodeObjectForKey:@"userCode"];
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)enCoder {
    [enCoder encodeObject:self.userKeyName forKey:@"userKeyName"];
    [enCoder encodeObject:self.userApi forKey:@"userApi"];
    [enCoder encodeObject:self.userCode forKey:@"userCode"];

}

@end

My preferences view controller header:

#import <Cocoa/Cocoa.h>
#import "MASPreferencesViewController.h"
#import "UserKeys.h"

@interface PreferencesApiKeysViewController : NSViewController <MASPreferencesViewController>

@property (strong) NSMutableArray *allKeys;

@end

and its implementation:

#import "PreferencesApiKeysViewController.h"
#import "UserKeys.h"

@interface PreferencesApiKeysViewController ()

@property (weak) IBOutlet NSTableView *keysTableView;

@end

@implementation PreferencesApiKeysViewController

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle {
    if ((self = [super initWithNibName:nibName bundle:bundle])) {
        self.allKeys = [NSMutableArray array];
    }
    return self;
}

// delegating....
//

- (void)viewWillAppear {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [defaults objectForKey:@"UserKeys"];
    if (data != nil) {
        NSArray *oldArray = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        if (oldArray != nil) {
            self.allKeys = [[NSMutableArray alloc] initWithArray:oldArray];
        } else {
            self.allKeys = [NSMutableArray array];
        }
    }
}

- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    // some code...
    return cellView;
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
    return [self.allKeys count];
}

The error I'm getting is:

-[UserKeys count]: unrecognized selector sent to instance 0x100534df0

When I put a breakpoint in - (void)viewWillAppear, I can see that data has around 250 bytes, but this oldArray seems to be empty. I understand that I'm doing some major mistake here with self.allKeys so that my table is not aware how many rows it should create, but after lots of attempts to get proper data, I'm really out of ideas why is this happening.

So, how to properly unarchive my data and present it in NSTableView?
(I'm using Xcode 4.6)

Was it helpful?

Solution

It is because the object you appear to be dearchiving is a pointer to an object of class UserKeys, rather than an object that is or descends from NSArray. When -initWithAray: hits your oldArray pointer to UserKeys, it doesn't know, or doesn't care what class it is, it simply sends it a -count message so as to ascertain the size it must grow to.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top