0

I'm having issues placing a custom object (WSWCMPost) into an NSMutableArray and then accessing the data stored in it later. Below is the relevant code.

Here is "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;

Here is "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

And here is the "viewDidLoad" method that is causing my issues

    - (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];
}

And finally, here is the output

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...

I think that is all of the relevant code. If i forgot anything let me know please. This issue has been bothering me for hours...

4

3 に答える 3

1

なぜそれが正常に爆発するのではなく、あなたに与えているのかはっきりしていませんが、問題はカスタムクラスがプロトコルに準拠していないNSStringsという事実に起因しているようです。カスタム オブジェクトを に保存する場合は、カスタム オブジェクトがこのプロトコルを実装していることを確認してください。そうしないと、データをシリアル化する方法がわからないためです。WSWCMPostNSCodingNSUserDefaults

より正確には、これらのメソッドをクラスの実装に追加する必要があります。

- (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。これを行ったら、現在保存されているすべての情報をクリアして、それ以上s がNSUserDefaults含まれていないことを確認する必要がありますが、その後、すべてが適切に機能するはずです。NSStringもちろん、WSWCMPostオブジェクトに保存されているデータを変更する場合は、これら 2 つのメソッドを更新する必要があります。

于 2012-06-26T01:58:52.680 に答える
0

もう1つ言及すべきことは、ゲッター/セッターとそれぞれのインスタンス変数との衝突が発生していることです。したがって、実装は次のとおりです。

インターフェース

@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.postIDまたはpostIDを入力しても、コンパイラーは文句を言いません。違いは、postIDと入力すると、実際にはメンバー変数が設定され、保持されないことです。self.postIDは、現在設定されているものをすべて解放し、異なる場合は新しい値を保持します。

プロパティを新しい方法で宣言するには、setterをself.postIDとして呼び出すか、基になるインスタンス変数を_postIDとして設定する必要があります。初期のiPhoneの本の多くは、そのようにプロパティを強打していましたが、それは結局、あらゆる種類のメモリの問題を引き起こしていました。

お役に立てれば!

アップデート!!!

コンストラクターで自分自身を返すのを忘れました;)それだけだと思います

- (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 に答える
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

これらの 2 行は、NSString オブジェクトがセレクターの postID を認識しないことを示しています。このヒントは、どこを詳しく調べる必要があるかを知るのに十分なはずです。

詳細については、NSUserDefaults の NSMutableArray にカスタム オブジェクトを保存するを参照してください。

于 2012-06-26T02:10:27.760 に答える