JSON 到核心数据中通过 UITableVewController 显示

发布于 2024-10-19 11:32:08 字数 15727 浏览 3 评论 0原文

NSManagedObjectModel 由以下部分组成:

#import <CoreData/CoreData.h>


@interface Event :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * summary;
@property (nonatomic, retain) NSString * content;
@property (nonatomic, retain) NSDate * updated;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSDate * created;
@property (nonatomic, retain) NSString * ID;

@end

我正在做的就是尝试将解析后的 JSON 插入到上述核心数据属性中。

在下文中,newNote 是我为 NSManagedObject 指定的名称。基本上我想要完成的是将 JSON 插入到核心数据中,以便我可以在 UITableView 中显示它。以下函数解析 JSON 并将其插入到 Core Data 中。

-(void)pullNotes {

    UIApplication *app = [UIApplication alloc];
    app.networkActivityIndicatorVisible = YES;

    NSDictionary *params = [NSDictionary dictionaryWithObject:api_key forKey:@"api_key"];   

    [[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

        if(response.status == 200) {
            NSLog(@"Pulling the users notes \n%@", [response asString]);

            // Create SBJSON object to parse JSON
            SBJSON *parser = [[SBJSON alloc] init];

            // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
            NSDictionary *object = [parser objectWithString:[response asString] error:nil];

            NSArray *notes = [object valueForKey:@"result"];
            for (NSDictionary *singleNote in notes){

                // newNote.created = [singleNote objectForKey:@"note created"]; Need to work on parsing these properly...
                // newNote.updated = [singleNote objectForKey:@"note updated"]; Need to work on parsing these properly...

                NSString *notetitle = [singleNote objectForKey:@"note title"];
                NSString *notesummary = [singleNote objectForKey:@"note summary"];
                NSString *noteid = [singleNote objectForKey:@"note id"];
                NSString *notecontent = [singleNote objectForKey:@"note content"];

                NSLog(@"Note Title: %@",notetitle);
                NSLog(@"Note Summary: %@",notesummary);
                NSLog(@"Note ID: %@",noteid);
                NSLog(@"Note Content: %@",notecontent);

                [newNote setValue:notecontent forKey:@"content"];

                NSError *error = nil;
                if (![newNote.managedObjectContext save:&error]) {
                    /*
                     Replace this implementation with code to handle the error appropriately.

                     abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                     */
                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }

                NSLog(@"Added Core Data Value: %@",[newNote valueForKey:@"content"]);

                // NSDate *createdDate = 
                // NSDate *updatedDate =

                [tableView reloadData];

                app.networkActivityIndicatorVisible = NO;

            }
        }

        if (response.status == 404) {
            NSLog(@"FAIL\n%@", [response asString]);
            app.networkActivityIndicatorVisible = NO;
        }

    }];

}

字符串的 NSLogs 返回正确的内容,所以我知道它实际上应该将它们插入到核心数据中......

所以,我的问题。

当该函数被调用时,我收到以下错误。

2011-02-26 21:37:30.797 Notacious[22570:207] Unresolved error (null), (null)

我不明白发生了什么,希望有人能够阐明我的问题。

编辑

经过几个小时的使用,我已经有了一些功能:

-(void)pullNotes {

    UIApplication *app = [UIApplication alloc];
    app.networkActivityIndicatorVisible = YES;

    NSDictionary *params = [NSDictionary dictionaryWithObject:api_key forKey:@"api_key"];   

    [[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

        if(response.status == 200) {
            NSLog(@"Pulling the users notes \n%@", [response asString]);

            // Create SBJSON object to parse JSON
            SBJSON *parser = [[SBJSON alloc] init];

            // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
            NSDictionary *object = [parser objectWithString:[response asString] error:nil];


            appDelegate =(NotaciousAppDelegate *) [[UIApplication sharedApplication] delegate];
            NSManagedObject *newNote;

            NSArray *notes = [object valueForKey:@"result"];
            for (NSDictionary *singleNote in notes){

                // newNote.created = [singleNote objectForKey:@"note created"]; Need to work on parsing these properly...
                // newNote.updated = [singleNote objectForKey:@"note updated"]; Need to work on parsing these properly...

                NSString *notetitle = [singleNote objectForKey:@"note title"];
                NSString *notesummary = [singleNote objectForKey:@"note summary"];
                NSString *noteid = [singleNote objectForKey:@"note id"];
                NSString *notecontent = [singleNote objectForKey:@"note content"];

                NSLog(@"Note Title: %@",notetitle);
                NSLog(@"Note Summary: %@",notesummary);
                NSLog(@"Note ID: %@",noteid);
                NSLog(@"Note Content: %@",notecontent);


                newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
                [newNote setValue:notecontent forKey:@"content"];
                [newNote setValue:notesummary forKey:@"summary"];
                [newNote setValue:notetitle forKey:@"title"];
                [newNote setValue:noteid forKey:@"ID"];



                NSLog(@"Added Core Data Value: %@",[newNote valueForKey:@"content"]);

                // NSDate *createdDate = 
                // NSDate *updatedDate =

                app.networkActivityIndicatorVisible = NO;

            }

            NSError *error = nil;
            if (![appDelegate.managedObjectContext save:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }

        }

        if (response.status == 404) {
            NSLog(@"FAIL\n%@", [response asString]);
            app.networkActivityIndicatorVisible = NO;
        }

    }];

}

但是,它会添加实体,无论它们之前是否存在。我想要它做的是找到如果注释已经存在,则更新它。如果没有,请创建一个新的。

编辑

目前该函数现在看起来像这样:

-(void)pullNotes {

    UIApplication *app = [UIApplication alloc];
    app.networkActivityIndicatorVisible = YES;

    NSDictionary *params = [NSDictionary dictionaryWithObject:api_key forKey:@"api_key"];   

    [[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

        if(response.status == 200) {
            NSLog(@"Pulling the users notes \n%@", [response asString]);

            // Create SBJSON object to parse JSON
            SBJSON *parser = [[SBJSON alloc] init];

            // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
            NSDictionary *object = [parser objectWithString:[response asString] error:nil];


            appDelegate =(NotaciousAppDelegate *) [[UIApplication sharedApplication] delegate];
            NSManagedObject *newNote;

            NSEntityDescription *noteEntity=[NSEntityDescription entityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
            NSFetchRequest *noteFetch;
            NSArray *fetchedNotes;

            NSArray *notes = [object valueForKey:@"result"];
            for (NSDictionary *singleNote in notes){

                noteFetch=[[NSFetchRequest alloc] init];
                [noteFetch setEntity:noteEntity];
                NSPredicate *pred=[NSPredicate predicateWithFormat:@"noteID==%@",[singleNote objectForKey:@"note id"]];
                [noteFetch setPredicate:pred];

                NSError *fetchError=nil;
                fetchedNotes=[appDelegate.managedObjectContext performFetch:&fetchError];

                if (fetchError!=nil) {
                    NSLog(@"pullNotes fetchError=%@,details=%@",fetchError,fetchError.userInfo);
                }
                if ([fetchedNotes count]==0) {

                    // newNote.created = [singleNote objectForKey:@"note created"]; Need to work on parsing these properly...
                    // newNote.updated = [singleNote objectForKey:@"note updated"]; Need to work on parsing these properly...

                    NSString *notetitle = [singleNote objectForKey:@"note title"];
                    NSString *notesummary = [singleNote objectForKey:@"note summary"];
                    NSString *noteid = [singleNote objectForKey:@"note id"];
                    NSString *notecontent = [singleNote objectForKey:@"note content"];

                    NSLog(@"Note Title: %@",notetitle);
                    NSLog(@"Note Summary: %@",notesummary);
                    NSLog(@"Note ID: %@",noteid);
                    NSLog(@"Note Content: %@",notecontent);


                    newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
                    [newNote setValue:notecontent forKey:@"content"];
                    [newNote setValue:notesummary forKey:@"summary"];
                    [newNote setValue:notetitle forKey:@"title"];
                    [newNote setValue:noteid forKey:@"ID"];

                    // NSDate *createdDate = 
                    // NSDate *updatedDate =

                    NSError *error = nil;
                    if (![appDelegate.managedObjectContext save:&error]) {
                        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                        abort();
                    }


                }

                [noteFetch release];


                app.networkActivityIndicatorVisible = NO;

            }

        }

        if (response.status == 404) {
            NSLog(@"FAIL\n%@", [response asString]);
            app.networkActivityIndicatorVisible = NO;
        }

    }];

}

但是,在调用 appDelegate.managedObjectContext 时,我似乎遇到了错误,并且它只是出错了说以下内容:

2011-03-03 12:11:01.616 Notacious[182:307] -[NSManagedObjectContext performFetch:]: unrecognized selector sent to instance 0x1474e0
2011-03-03 12:11:01.781 Notacious[182:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObjectContext performFetch:]: unrecognized selector sent to instance 0x1474e0'

我已经尝试将其设置为 appDelegate.managedObjectContext_ 但为了有效,它似乎返回一个错误,指出在 appDelegate 中找不到它并且它不是 getter 对象。然而,它在这里被明确分配: http://cl.ly/4xdX

EDIT

我想我最好编辑此内容以添加我当前的工作以及原始标题下的另一个问题。以下代码是我构建的并且工作得很好(除了编辑的字符串没有被保存,进而导致我的以下问题此处)。

-(void)syncNotes {

UIApplication *app = [UIApplication alloc];
app.networkActivityIndicatorVisible = YES;

NSDictionary *params = [NSDictionary dictionaryWithObject:authToken forKey:@"api_key"]; 

[[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

    if(response.status == 200) {
        // NSLog(@"Successful Connection \n%@", [response asString]);

        // Create SBJSON object to parse JSON
        SBJSON *parser = [[SBJSON alloc] init];

        // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
        NSDictionary *object = [parser objectWithString:[response asString] error:nil];
        [parser release];

        NSFetchRequest *noteFetch;
        NSManagedObject *newNote;

        appDelegate =(NotaciousAppDelegate *) [[UIApplication sharedApplication] delegate];

        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:appDelegate.managedObjectContext];
        NSArray *fetchedNotes;

        NSArray *notes = [object valueForKey:@"result"];
        for (NSDictionary *singleNote in notes){

            noteFetch=[[NSFetchRequest alloc] init];
            [noteFetch setEntity:entity];
            NSPredicate *pred=[NSPredicate predicateWithFormat:@"ID==%@",[singleNote objectForKey:@"note id"]];
            [noteFetch setPredicate:pred];

            NSError *fetchError=nil;
            fetchedNotes=[appDelegate.managedObjectContext executeFetchRequest:noteFetch error:&fetchError];

            if (fetchError!=nil) {
                NSLog(@"syncNotes fetchError=%@,details=%@",fetchError,fetchError.userInfo);
            }
            if ([fetchedNotes count]==0) {


                NSString *notelocked = [singleNote objectForKey:@"note locked"];

                NSString *notecreated = [singleNote objectForKey:@"note created"];
                NSString *noteupdated = [singleNote objectForKey:@"note updated"];
                NSString *notetitle = [singleNote objectForKey:@"note title"];
                NSString *notesummary = [singleNote objectForKey:@"note summary"];
                NSString *noteid = [singleNote objectForKey:@"note id"];
                NSString *notecontent = [singleNote objectForKey:@"note content"];

                NSString *formattedTitle = [NSString decodeShit:notetitle];
                NSString *formattedSummary = [NSString decodeShit:notesummary];
                NSString *formattedContent = [NSString decodeShit:notecontent];


                NSLog(@"Note Title: %@",formattedTitle);
                NSLog(@"Note Summary: %@",formattedSummary);
                NSLog(@"Note ID: %@",noteid);
                NSLog(@"Note Content: %@",formattedContent);
                NSLog(@"Note Created: %@",notecreated);
                NSLog(@"Note Updated: %@",noteupdated);
                NSLog(@"Note Locked: %@",notelocked);


                newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:appDelegate.managedObjectContext];
                [newNote setValue:formattedContent forKey:@"content"];
                [newNote setValue:formattedSummary forKey:@"summary"];
                [newNote setValue:formattedTitle forKey:@"title"];
                [newNote setValue:noteid forKey:@"ID"];
                [newNote setValue:notecreated forKey:@"created"];
                [newNote setValue:noteupdated forKey:@"updated"];
                [newNote setValue:notelocked forKey:@"locked"];

                NSError *error = nil;
                if (![appDelegate.managedObjectContext save:&error]) {
                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }


            }

            [noteFetch release];

        }

        app.networkActivityIndicatorVisible = NO;

    }

    if (response.status == 404) {
        NSLog(@"FAIL\n%@", [response asString]);
        app.networkActivityIndicatorVisible = NO;
    }

}];

}

现在,这确实有效,但是当内容字符串不同时,我想更新正确的注释。这里有人愿意详细说明如何做到这一点吗?

我知道我一直在这里问问题,但想让一切变得完美,而且似乎我对这种简单任务的了解有些不存在。任何意见将不胜感激!

编辑

啊,另一个请求。如果当前存储的笔记没有 noteID,那么是否将其从核心数据中删除?这可能吗?

The NSManagedObjectModel consists of the following:

#import <CoreData/CoreData.h>


@interface Event :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * summary;
@property (nonatomic, retain) NSString * content;
@property (nonatomic, retain) NSDate * updated;
@property (nonatomic, retain) NSString * title;
@property (nonatomic, retain) NSDate * created;
@property (nonatomic, retain) NSString * ID;

@end

What I'm doing is trying to insert parsed JSON into the above Core Data attributes.

In the following, newNote is the name I have given to the NSManagedObject. Basically what I'm trying to accomplish is inserting the JSON into the Core Data so that I can then display it in a UITableView. The following function is what parses the JSON and inserts it into Core Data.

-(void)pullNotes {

    UIApplication *app = [UIApplication alloc];
    app.networkActivityIndicatorVisible = YES;

    NSDictionary *params = [NSDictionary dictionaryWithObject:api_key forKey:@"api_key"];   

    [[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

        if(response.status == 200) {
            NSLog(@"Pulling the users notes \n%@", [response asString]);

            // Create SBJSON object to parse JSON
            SBJSON *parser = [[SBJSON alloc] init];

            // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
            NSDictionary *object = [parser objectWithString:[response asString] error:nil];

            NSArray *notes = [object valueForKey:@"result"];
            for (NSDictionary *singleNote in notes){

                // newNote.created = [singleNote objectForKey:@"note created"]; Need to work on parsing these properly...
                // newNote.updated = [singleNote objectForKey:@"note updated"]; Need to work on parsing these properly...

                NSString *notetitle = [singleNote objectForKey:@"note title"];
                NSString *notesummary = [singleNote objectForKey:@"note summary"];
                NSString *noteid = [singleNote objectForKey:@"note id"];
                NSString *notecontent = [singleNote objectForKey:@"note content"];

                NSLog(@"Note Title: %@",notetitle);
                NSLog(@"Note Summary: %@",notesummary);
                NSLog(@"Note ID: %@",noteid);
                NSLog(@"Note Content: %@",notecontent);

                [newNote setValue:notecontent forKey:@"content"];

                NSError *error = nil;
                if (![newNote.managedObjectContext save:&error]) {
                    /*
                     Replace this implementation with code to handle the error appropriately.

                     abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. If it is not possible to recover from the error, display an alert panel that instructs the user to quit the application by pressing the Home button.
                     */
                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }

                NSLog(@"Added Core Data Value: %@",[newNote valueForKey:@"content"]);

                // NSDate *createdDate = 
                // NSDate *updatedDate =

                [tableView reloadData];

                app.networkActivityIndicatorVisible = NO;

            }
        }

        if (response.status == 404) {
            NSLog(@"FAIL\n%@", [response asString]);
            app.networkActivityIndicatorVisible = NO;
        }

    }];

}

The NSLogs of the strings are returning the correct things, so I know that it should actually be inserting them into the Core Data...

So, my issue.

When that function gets called I get the following error.

2011-02-26 21:37:30.797 Notacious[22570:207] Unresolved error (null), (null)

I don't understand what is happening and hopefully someone will be able to shed some light on my issue.

EDIT

After a few hours of playing with it, I have it somewhat functioning:

-(void)pullNotes {

    UIApplication *app = [UIApplication alloc];
    app.networkActivityIndicatorVisible = YES;

    NSDictionary *params = [NSDictionary dictionaryWithObject:api_key forKey:@"api_key"];   

    [[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

        if(response.status == 200) {
            NSLog(@"Pulling the users notes \n%@", [response asString]);

            // Create SBJSON object to parse JSON
            SBJSON *parser = [[SBJSON alloc] init];

            // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
            NSDictionary *object = [parser objectWithString:[response asString] error:nil];


            appDelegate =(NotaciousAppDelegate *) [[UIApplication sharedApplication] delegate];
            NSManagedObject *newNote;

            NSArray *notes = [object valueForKey:@"result"];
            for (NSDictionary *singleNote in notes){

                // newNote.created = [singleNote objectForKey:@"note created"]; Need to work on parsing these properly...
                // newNote.updated = [singleNote objectForKey:@"note updated"]; Need to work on parsing these properly...

                NSString *notetitle = [singleNote objectForKey:@"note title"];
                NSString *notesummary = [singleNote objectForKey:@"note summary"];
                NSString *noteid = [singleNote objectForKey:@"note id"];
                NSString *notecontent = [singleNote objectForKey:@"note content"];

                NSLog(@"Note Title: %@",notetitle);
                NSLog(@"Note Summary: %@",notesummary);
                NSLog(@"Note ID: %@",noteid);
                NSLog(@"Note Content: %@",notecontent);


                newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
                [newNote setValue:notecontent forKey:@"content"];
                [newNote setValue:notesummary forKey:@"summary"];
                [newNote setValue:notetitle forKey:@"title"];
                [newNote setValue:noteid forKey:@"ID"];



                NSLog(@"Added Core Data Value: %@",[newNote valueForKey:@"content"]);

                // NSDate *createdDate = 
                // NSDate *updatedDate =

                app.networkActivityIndicatorVisible = NO;

            }

            NSError *error = nil;
            if (![appDelegate.managedObjectContext save:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }

        }

        if (response.status == 404) {
            NSLog(@"FAIL\n%@", [response asString]);
            app.networkActivityIndicatorVisible = NO;
        }

    }];

}

However, it adds entities regardless of whether or not they were there before. What I want it to do is to find that if a note is already there, update it. If not, create a new one.

EDIT

Currently the function is now looking like this:

-(void)pullNotes {

    UIApplication *app = [UIApplication alloc];
    app.networkActivityIndicatorVisible = YES;

    NSDictionary *params = [NSDictionary dictionaryWithObject:api_key forKey:@"api_key"];   

    [[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

        if(response.status == 200) {
            NSLog(@"Pulling the users notes \n%@", [response asString]);

            // Create SBJSON object to parse JSON
            SBJSON *parser = [[SBJSON alloc] init];

            // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
            NSDictionary *object = [parser objectWithString:[response asString] error:nil];


            appDelegate =(NotaciousAppDelegate *) [[UIApplication sharedApplication] delegate];
            NSManagedObject *newNote;

            NSEntityDescription *noteEntity=[NSEntityDescription entityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
            NSFetchRequest *noteFetch;
            NSArray *fetchedNotes;

            NSArray *notes = [object valueForKey:@"result"];
            for (NSDictionary *singleNote in notes){

                noteFetch=[[NSFetchRequest alloc] init];
                [noteFetch setEntity:noteEntity];
                NSPredicate *pred=[NSPredicate predicateWithFormat:@"noteID==%@",[singleNote objectForKey:@"note id"]];
                [noteFetch setPredicate:pred];

                NSError *fetchError=nil;
                fetchedNotes=[appDelegate.managedObjectContext performFetch:&fetchError];

                if (fetchError!=nil) {
                    NSLog(@"pullNotes fetchError=%@,details=%@",fetchError,fetchError.userInfo);
                }
                if ([fetchedNotes count]==0) {

                    // newNote.created = [singleNote objectForKey:@"note created"]; Need to work on parsing these properly...
                    // newNote.updated = [singleNote objectForKey:@"note updated"]; Need to work on parsing these properly...

                    NSString *notetitle = [singleNote objectForKey:@"note title"];
                    NSString *notesummary = [singleNote objectForKey:@"note summary"];
                    NSString *noteid = [singleNote objectForKey:@"note id"];
                    NSString *notecontent = [singleNote objectForKey:@"note content"];

                    NSLog(@"Note Title: %@",notetitle);
                    NSLog(@"Note Summary: %@",notesummary);
                    NSLog(@"Note ID: %@",noteid);
                    NSLog(@"Note Content: %@",notecontent);


                    newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
                    [newNote setValue:notecontent forKey:@"content"];
                    [newNote setValue:notesummary forKey:@"summary"];
                    [newNote setValue:notetitle forKey:@"title"];
                    [newNote setValue:noteid forKey:@"ID"];

                    // NSDate *createdDate = 
                    // NSDate *updatedDate =

                    NSError *error = nil;
                    if (![appDelegate.managedObjectContext save:&error]) {
                        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                        abort();
                    }


                }

                [noteFetch release];


                app.networkActivityIndicatorVisible = NO;

            }

        }

        if (response.status == 404) {
            NSLog(@"FAIL\n%@", [response asString]);
            app.networkActivityIndicatorVisible = NO;
        }

    }];

}

It seems that, however, I'm getting an error when it comes to calling the appDelegate.managedObjectContext and it just errors out saying the following:

2011-03-03 12:11:01.616 Notacious[182:307] -[NSManagedObjectContext performFetch:]: unrecognized selector sent to instance 0x1474e0
2011-03-03 12:11:01.781 Notacious[182:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSManagedObjectContext performFetch:]: unrecognized selector sent to instance 0x1474e0'

I have already tried setting it to appDelegate.managedObjectContext_ but to avail, it seems to return an error stating that it isn't found within the appDelegate and that it isn't a getter object. However, it is clearly allocated here: http://cl.ly/4xdX

EDIT

Thought I'd best edit this to add in my current work around and another question underneath the original title. The following code is what I have built and is working perfectly fine (except the Edited string isn't being saved and in turn resulting in the following question of mine here).

-(void)syncNotes {

UIApplication *app = [UIApplication alloc];
app.networkActivityIndicatorVisible = YES;

NSDictionary *params = [NSDictionary dictionaryWithObject:authToken forKey:@"api_key"]; 

[[LRResty client] get:@"http://notacio.us/api/note" parameters:params withBlock:^(LRRestyResponse *response){

    if(response.status == 200) {
        // NSLog(@"Successful Connection \n%@", [response asString]);

        // Create SBJSON object to parse JSON
        SBJSON *parser = [[SBJSON alloc] init];

        // parse the JSON string into an object - assuming [response asString] is a NSString of JSON data
        NSDictionary *object = [parser objectWithString:[response asString] error:nil];
        [parser release];

        NSFetchRequest *noteFetch;
        NSManagedObject *newNote;

        appDelegate =(NotaciousAppDelegate *) [[UIApplication sharedApplication] delegate];

        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:appDelegate.managedObjectContext];
        NSArray *fetchedNotes;

        NSArray *notes = [object valueForKey:@"result"];
        for (NSDictionary *singleNote in notes){

            noteFetch=[[NSFetchRequest alloc] init];
            [noteFetch setEntity:entity];
            NSPredicate *pred=[NSPredicate predicateWithFormat:@"ID==%@",[singleNote objectForKey:@"note id"]];
            [noteFetch setPredicate:pred];

            NSError *fetchError=nil;
            fetchedNotes=[appDelegate.managedObjectContext executeFetchRequest:noteFetch error:&fetchError];

            if (fetchError!=nil) {
                NSLog(@"syncNotes fetchError=%@,details=%@",fetchError,fetchError.userInfo);
            }
            if ([fetchedNotes count]==0) {


                NSString *notelocked = [singleNote objectForKey:@"note locked"];

                NSString *notecreated = [singleNote objectForKey:@"note created"];
                NSString *noteupdated = [singleNote objectForKey:@"note updated"];
                NSString *notetitle = [singleNote objectForKey:@"note title"];
                NSString *notesummary = [singleNote objectForKey:@"note summary"];
                NSString *noteid = [singleNote objectForKey:@"note id"];
                NSString *notecontent = [singleNote objectForKey:@"note content"];

                NSString *formattedTitle = [NSString decodeShit:notetitle];
                NSString *formattedSummary = [NSString decodeShit:notesummary];
                NSString *formattedContent = [NSString decodeShit:notecontent];


                NSLog(@"Note Title: %@",formattedTitle);
                NSLog(@"Note Summary: %@",formattedSummary);
                NSLog(@"Note ID: %@",noteid);
                NSLog(@"Note Content: %@",formattedContent);
                NSLog(@"Note Created: %@",notecreated);
                NSLog(@"Note Updated: %@",noteupdated);
                NSLog(@"Note Locked: %@",notelocked);


                newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:appDelegate.managedObjectContext];
                [newNote setValue:formattedContent forKey:@"content"];
                [newNote setValue:formattedSummary forKey:@"summary"];
                [newNote setValue:formattedTitle forKey:@"title"];
                [newNote setValue:noteid forKey:@"ID"];
                [newNote setValue:notecreated forKey:@"created"];
                [newNote setValue:noteupdated forKey:@"updated"];
                [newNote setValue:notelocked forKey:@"locked"];

                NSError *error = nil;
                if (![appDelegate.managedObjectContext save:&error]) {
                    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                    abort();
                }


            }

            [noteFetch release];

        }

        app.networkActivityIndicatorVisible = NO;

    }

    if (response.status == 404) {
        NSLog(@"FAIL\n%@", [response asString]);
        app.networkActivityIndicatorVisible = NO;
    }

}];

}

Now, sure this works, but when the content string is different, I want to update the correct note. Is there anyone on here that is willing to detail how to do this?

I know I keep asking questions on here, but want to get everything perfect and it seems my knowledge of such simple tasks is somewhat not there. Any input would be greatly appreciated!

EDIT

Ah, another request. If there is no noteID for a currently stored note, then remove that from the Core Data? Is that even possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

许久 2024-10-26 11:32:08

错误的直接根源是您将 save:error: 消息发送到不存在的托管对象上下文。反过来,托管对象上下文也不存在,因为您从未在上下文中创建或插入托管对象 newNote

我的印象是,您还没有完全理解 Core Data 是围绕对象而不是 SQL 表、列、行等构建的。Core Data 中的每一条数据都存储在一个或多个对象或它们之间的关系中。所有这些对象和关系都会创建对象图,而核心数据真正管理的是该图。

在您的例子中,每条 JSON 消息都会分解为许多字典,每个字典都包含一个注释的数据。您需要一个配置有 Event 实体的托管对象来存储每个注释。

如果您从使用 Xcode 中的模板的核心数据之一开始,您将看到您获得了托管对象上下文、托管对象模型、持久性存储协调器和持久性存储,所有这些设置都已为您设置并分配给应用程序委托的属性。在下面的代码中,我将使用模板中的属性和名称。

你需要这样的东西(我没有编译这个,所以要注意拼写错误):

-(void)pullNotes{
    //first, get the application delegate that manages the Core Data stack
    // since the app itself is a singleton, we just ask it for its delegate
    MyAppDelegateClass *appDelegate=(MyAppDelegateClass *) [[UIApplication sharedApplication] delegate];

    // ...all the JSON pulling code

    NSManagedObject *newNote; 
    NSArray *notes = [object valueForKey:@"result"];
    for (NSDictionary *singleNote in notes){
        // create another concrete instance of NSManagedObject 
        // for each logical note from JSON and insert it into
        // the appDelegate's managedObjectContext attribute
        newNote=[NSEntityDescription insertNewObjectForEntityForName:@"Event" 
                                              inManagedObjectContext:appDelegate.managedObjectContext_];
        // Assign data from the JSON note to the attributes of this specific 
        // NSManagedObject instance. 
        [newNote setValue:[singleNote objectForKey:@"note content"] forKey:@"noteContent"];
        // ... repeat for all other attributes you wish to have in the data 
    } 

    // only save after you've created all the notes. It's to slow to 
    // save after every note.   
    NSError *error = nil;
    if (![appDelegate.managedObjectContext_ save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

要点:

  1. 每条建模数据都应该有它自己的 NSManagedObject 实例。
  2. 所有管理对象实例必须配置一个实体并插入到管理对象上下文中以进行管理或保存。
  3. 核心数据堆栈的上下文和其他部分通常驻留在应用程序委托中,并且您通常一次只有一个堆栈(对于大多数应用程序)。使用 UIApplication 单例可以从应用程序中的任何位置访问应用程序委托。

更新:

但是,它无论如何都会添加实体
他们是否在那里
前。我想要它做的是
发现如果注释已经存在,
更新它。如果没有,请创建一个新的。

要检查预先存在的注释,您需要尝试获取与新数据匹配的现有注释。这是简单的实现(未编译):

// call this outside the loop so you 
// only have to call it once.
NSEntityDescription *noteEntity=[NSEntityDescription entityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
NSFetchRequest *noteFetch;
NSArray *fetchedNotes;

// inside the for loop for each new note
noteFetch=[[NSFetchRequest alloc] init];
[noteFetch setEntity:noteEntity];
NSPredicate *pred=[NSPredicate predicateWithFormat:@"noteID==%@",[singleNote objectForKey:@"note id"]];
[noteFetch setPredicate:pred];

NSError *fetchError=nil;
fetchedNotes=[appDelegate.managedObjectContext_ performFetch:&fetchError];
if (fetchError!=nil) {
    NSLog(@"pullNotes fetchError=%@,details=%@",fetchError,fetchError.userInfo);
}
if ([fetchedNotes count]==0) {
    // create new note
}
[noteFetch release];
// end loop

您可以使用 IN 测试形成一个谓词,该谓词将针对所有新的“noteID 值”的数组进行测试,并且仅执行一次获取,但这有点复杂。除非您一次处理数百个笔记,否则从用户的角度来看,这种技术看起来同样快。

The immediate source of your error is that you are sending the save:error: message to a non-existant managed object context. In turn, the managed object context doesn't exist because you never created or inserted the managed object newNote into a context to begin with.

I get the impression that you haven't quite grasp that Core Data is built around objects instead of SQL tables, columns, rows etc. Every piece of data in Core Data is stored in one or more objects or the relationships between. All those objects and relationships create and object graph and it is that graph that Core Data really manages.

In your case, every JSON message decomposes into to numerous dictionaries, each one containing the data for one note. You need one managed object configured with the Event entity, to store each note.

If you start with one of the Core Data using templates in Xcode, you will see that you get the managed object context, managed object model, persistent store coordinator and persistent stores all setup for you and assigned to attributes of the app delegate. In the following code I will use the attributes and names from the template.

You need something like this (I didn't compile this so watch for typos):

-(void)pullNotes{
    //first, get the application delegate that manages the Core Data stack
    // since the app itself is a singleton, we just ask it for its delegate
    MyAppDelegateClass *appDelegate=(MyAppDelegateClass *) [[UIApplication sharedApplication] delegate];

    // ...all the JSON pulling code

    NSManagedObject *newNote; 
    NSArray *notes = [object valueForKey:@"result"];
    for (NSDictionary *singleNote in notes){
        // create another concrete instance of NSManagedObject 
        // for each logical note from JSON and insert it into
        // the appDelegate's managedObjectContext attribute
        newNote=[NSEntityDescription insertNewObjectForEntityForName:@"Event" 
                                              inManagedObjectContext:appDelegate.managedObjectContext_];
        // Assign data from the JSON note to the attributes of this specific 
        // NSManagedObject instance. 
        [newNote setValue:[singleNote objectForKey:@"note content"] forKey:@"noteContent"];
        // ... repeat for all other attributes you wish to have in the data 
    } 

    // only save after you've created all the notes. It's to slow to 
    // save after every note.   
    NSError *error = nil;
    if (![appDelegate.managedObjectContext_ save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

Key points:

  1. Each piece of modeled data should have its own instance of a NSManagedObject.
  2. All managed object instance must be configured with an entity and inserted into a managed object context to be managed or saved.
  3. The context and other parts of the Core Data stack usually reside in the app delegate and you usually have only one stack at a time (for most apps.) Use the UIApplication singleton to access the app delegate from anywhere in the app.

Update:

However, it adds entities regardless
of whether or not they were there
before. What I want it to do is to
find that if a note is already there,
update it. If not, create a new one.

To check for a pre-existing note, you need to attempt to fetch existing notes matching the new data. Here's simple implementation (uncompiled):

// call this outside the loop so you 
// only have to call it once.
NSEntityDescription *noteEntity=[NSEntityDescription entityForName:@"Event" inManagedObjectContext:appDelegate.managedObjectContext];
NSFetchRequest *noteFetch;
NSArray *fetchedNotes;

// inside the for loop for each new note
noteFetch=[[NSFetchRequest alloc] init];
[noteFetch setEntity:noteEntity];
NSPredicate *pred=[NSPredicate predicateWithFormat:@"noteID==%@",[singleNote objectForKey:@"note id"]];
[noteFetch setPredicate:pred];

NSError *fetchError=nil;
fetchedNotes=[appDelegate.managedObjectContext_ performFetch:&fetchError];
if (fetchError!=nil) {
    NSLog(@"pullNotes fetchError=%@,details=%@",fetchError,fetchError.userInfo);
}
if ([fetchedNotes count]==0) {
    // create new note
}
[noteFetch release];
// end loop

You can form a predicate using the IN test that would test against an array of all the new ``noteID values and do just one fetch but that is a little more complex. Unless you are processing hundreds of notes at a time, this technique will look just as fast from the user's perspective.

嘿嘿嘿 2024-10-26 11:32:08

您只需调用 insertNewObjectForEntityForName ,它总是创建一个新对象。使用唯一值作为键,为该键创建一个获取请求,如果它没有返回任何内容,则创建一个新对象。

 + (Note*)NoteWithKey: (NSString*)key
{
    NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:key,@"KEY",nil];

    NSManagedObjectContext *context = appDelegate.managedObjectContext;
    NSManagedObjectModel *model = appDelegate.managedObjectModel;
    NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:@"GetKey" substitutionVariables:query];

    NSError *error;
    NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
    if (results && ([results count] > 0)) {
        return [results objectAtIndex:0];
    }
    else {
        Note *newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:context];
        if (nil != newNote) {
            [newNote setValue:key forKey:@"Key"];
        }

        return newNote;
    }
}

You're just calling insertNewObjectForEntityForName which always creates a new object. Use a unique value as the key, create a fetch request for that key, and if it returns nothing, then you create a new object.

 + (Note*)NoteWithKey: (NSString*)key
{
    NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:key,@"KEY",nil];

    NSManagedObjectContext *context = appDelegate.managedObjectContext;
    NSManagedObjectModel *model = appDelegate.managedObjectModel;
    NSFetchRequest *fetchRequest = [model fetchRequestFromTemplateWithName:@"GetKey" substitutionVariables:query];

    NSError *error;
    NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
    if (results && ([results count] > 0)) {
        return [results objectAtIndex:0];
    }
    else {
        Note *newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:context];
        if (nil != newNote) {
            [newNote setValue:key forKey:@"Key"];
        }

        return newNote;
    }
}
独享拥抱 2024-10-26 11:32:08

您的头文件 ( http://cl.ly/4rz2 ) 有一个名为 newNote 的 Event 对象的引用。但您永远不会创建一个对象来存储在该引用中。我会删除头文件中的引用,并将其保留在 JSON 解析方法中。为 json 中遇到的每个 singleNote 创建一个事件:


[..]
Event *newNote = nil;

for (NSDictionary *singleNote in notes) {
    // create a new autoreleased object
    newNote = [[[Event alloc] initWithEntity:aDescription insertIntoManagedObjectContext:aContext] autorelease];
    newNote.content = [singleNote objectForKey:@"note content"];
}

// save managedobjectcontext
[..]

不相关

[UIApplication alloc] 不是您通常想要做的事情。您可能想要使用类似以下内容的内容:[UIApplication sharedApplication].n networkActivityIndi​​catorVisible = YES;

Your header file ( http://cl.ly/4rz2 ) has a reference for an Event object, called newNote. But you never create an object to store in that reference. I would remove the reference in your header file, and keep it local in your JSON parsing method. Create one event for each singleNote you encounter in the json:


[..]
Event *newNote = nil;

for (NSDictionary *singleNote in notes) {
    // create a new autoreleased object
    newNote = [[[Event alloc] initWithEntity:aDescription insertIntoManagedObjectContext:aContext] autorelease];
    newNote.content = [singleNote objectForKey:@"note content"];
}

// save managedobjectcontext
[..]

Unrelated

[UIApplication alloc] is not something you normally want to do. You probably want to use something like: [UIApplication sharedApplication].n networkActivityIndicatorVisible = YES;

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文