0

我在将自定义对象 (WSWCMPost) 放入 NSMutableArray 并稍后访问存储在其中的数据时遇到问题。下面是相关代码。

这是“WSWCMPost.h”

#import <Foundation/Foundation.h>

@interface WSWCMPost : NSObject
{
    NSString *postBody;
    NSString *postTitle;
    NSString *postID;
}
@property (nonatomic, retain) NSString *postBody, *postTitle, *postID;

- init;
- (id)initWithID: (NSString*)ID AndBody: (NSString*)body AndTitle: (NSString*)title;
- (NSString*)postBody;
- (NSString*)postTitle;
- (NSString*)postID;

这是“WSWCMPost.m”

#import "WSWCMPost.h"

@implementation WSWCMPost

@synthesize postBody, postTitle, postID;

- (id)init {
    self = [super init];
    if(self) {
        postID = @"none";
        postBody = @"none";
        postTitle = @"none";
    }
}

- (id)initWithID: (NSString*)ID AndBody: (NSString*)body AndTitle: (NSString*)title {
    postTitle = title;
    postID = ID;
    postBody = body;
}

@end

这是导致我的问题的“viewDidLoad”方法

    - (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.detailViewController = (WSWCMDetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];

    // getting an NSString
    NSLog(@"Pulling saved blogs...");
    NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
    NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"wswcmt1"];
    if (dataRepresentingSavedArray != nil)
    {
        NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
        if (oldSavedArray != nil)
            _objects = [[NSMutableArray alloc] initWithArray:oldSavedArray];
        else
            _objects = [[NSMutableArray alloc] init];
    }
    NSLog(@"Pulled saved blogs...");

    NSLog(!_objects ? @"Yes" : @"No");
    @try {
        NSLog(@"_objects description: %@",[_objects description]);
        NSLog(@"_objects[0] postID: %@",[[_objects objectAtIndex:0] postID]);
    }
    @catch (NSException *exception) {
        NSLog(@"Caught exception %@", exception);
        NSLog(@"Objects doesnt exist, allocating memory...");
        _objects = [[NSMutableArray alloc] init];
        WSWCMPost *testPost = [[WSWCMPost alloc] initWithID:@"noID" AndBody:@"noBody" AndTitle:@"noTitle"];

        [_objects insertObject:testPost atIndex:0];
        [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_objects] forKey:@"wswcmt1"];
    }

    if (!_objects ) {
        NSLog(@"Objects doesnt exist...");
        _objects = [[NSMutableArray alloc] init];
        WSWCMPost *testPost = [[WSWCMPost alloc] initWithID:@"dne" AndBody:@"Dne" AndTitle:@"DNe"];

        [_objects insertObject:testPost atIndex:0];
        [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_objects] forKey:@"wswcmt"];
    }
    [self refreshButton:nil];
}

最后,这是输出

2012-06-25 22:39:49.345 WSWCM[4406:907] Pulling saved blogs...
2012-06-25 22:39:49.352 WSWCM[4406:907] Pulled saved blogs...
2012-06-25 22:39:49.355 WSWCM[4406:907] Yes
2012-06-25 22:39:49.356 WSWCM[4406:907] _objects description: (null)
2012-06-25 22:39:49.358 WSWCM[4406:907] _objects[0] postID: (null)
2012-06-25 22:39:49.360 WSWCM[4406:907] Objects doesnt exist...
2012-06-25 22:39:49.363 WSWCM[4406:907] Refresh Triggered...

我认为这就是所有相关的代码。如果我忘记了什么请告诉我。这个问题困扰了我好几个小时...

4

3 回答 3

1

虽然我不肯定为什么它会给你NSStrings而不是仅仅正常爆炸,但问题似乎源于你的自定义类WSWCMPost不符合NSCoding协议的事实。如果您想将自定义对象存储在 中,请确保您的自定义对象实现了此协议NSUserDefaults,因为否则它不知道如何序列化数据。

更准确地说,您必须将这些方法添加到您的类实现中:

- (id)initWithCoder:(NSCoder *)coder {
    self = [self initWithID:[coder decodeObjectForKey:@"id"] AndBody:[coder decodeObjectForKey:@"body"] AndTitle:[coder decodeObjectForKey:@"title"]];
    return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [encoder encodeObject:postID forKey:@"id"];
    [encoder encodeObject:postBody forKey:@"body"];
    [encoder encodeObject:postTitle forKey:@"title"];
}

这将允许数据被序列化NSCoder。完成此操作后,您应该清除当前存储的所有信息,NSUserDefaults以确保它不再包含任何NSStrings,然后一切都应该正常工作。当然,如果您更改WSWCMPost对象存储的数据,则必须更新这两个方法。

于 2012-06-26T01:58:52.680 回答
0

您的输出肯定显示了您的代码中有什么问题。

2012-06-25 21:51:07.691 WSWCM[4049:907] -[__NSCFString postID]: unrecognized selector sent to instance 0x1d003e80
2012-06-25 21:51:07.696 WSWCM[4049:907] Caught exception -[__NSCFString postID]: unrecognized selector sent to instance 0x1d003e80

这两行告诉你 NSString 对象不能识别选择器 postID。这个提示应该足以找出您需要深入查看的地方。

有关更多信息,请参阅将自定义对象存储在 NSUserDefaults 中的 NSMutableArray 中

于 2012-06-26T02:10:27.760 回答
0

另一件要提的事情是,您正在与您的 getter/setter 及其各自的实例变量发生冲突。所以你的实现是:

界面

@interface WSWCMPost : NSObject
{
    NSString *postBody; // don't need to do these anymore for properties
    NSString *postTitle;
    NSString *postID;
}
@property (nonatomic, retain) NSString *postBody, *postTitle, *postID;

执行

@implementation WSWCMPost

@synthesize postBody, postTitle, postID;

- (id)init {
    self = [super init];
    if(self) {
        postID = @"none";  // not prefixing your variables with 'self' so they are not getting retained
        postBody = @"none";
        postTitle = @"none";
    }
}

@结尾

以下是您应该如何写出这些内容:

界面

/** NOTE: No need to specify your instance variables here anymore, just the properties */
@interface WSWCMPost : NSObject

@property (nonatomic, retain) NSString *postID;
@property (nonatomic, retain) NSString *postTitle;
@property (nonatomic, retain) NSString *postBody;

执行

@implementation WSWCMPost

/** Now you specify the corresponding instance variable name alongside the property name */
@synthesize postBody=_postBody, postTitle=_postTitle, postID=_postID;

- (id)init {
    self = [super init];
    if(self) {
        self.postID = @"none";  //getting retained
        self.postBody = @"none";
        self.postTitle = @"none";
    }
}

这肯定会导致数据发布得太早。

所以以前的方式你可以输入self.postIDpostID并且编译器不会抱怨。不同之处在于,当您键入postID时,它实际上是在设置成员变量而不是保留它......其中self.postID将释放它当前设置的任何值,如果它不同,则保留新值。

通过以新方式声明属性,您必须将 setter 称为self.postID或将底层实例变量设置为_postID。许多早期的 iPhone 书籍都以这种方式敲击属性,最终导致各种内存问题。

希望这可以帮助!

更新!!!

你忘了在你的构造函数中返回 self ;)我打赌就是这样

- (id)init {
    self = [super init];
    if(self) {
        self.postID = @"none";  //getting retained
        self.postBody = @"none";
        self.postTitle = @"none";
    }
    return self; // THIS IS WHY, you're constructor doesn't return an instance of the class... add this please
}


- (id)initWithID: (NSString*)ID AndBody: (NSString*)body AndTitle: (NSString*)title {

    if(( self = [super init] ))
    { 
        self.postTitle = title;
        self.postID = ID;
        self.postBody = body;
    }
    return self;
}
于 2012-06-26T03:19:32.700 回答