سؤال

I'm building a simple notes app and trying to figure out how to use a custom class that I created from the data model section with editor/create NSManaged object subclass.

Since i'm a beginner, if you don't mind I will post my .m files (because its really short) just so you can catch something I didn't do right that brought this error:

Note.h: (there is nothing in the .m file, and currently i'm only dealing with the content prop)

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>


@interface Note : NSManagedObject

@property (nonatomic, retain) NSString * noteID;
@property (nonatomic, retain) NSString * content;
@property (nonatomic, retain) NSDate * timeCreated;

@end

NotesListViewController.h:

    #import <UIKit/UIKit.h>

    @interface NONotesListViewController : UITableViewController

    - (IBAction) unwindToList:(UIStoryboardSegue *)segue;

    @end

#import "NONotesListViewController.h"
#import "Note.h"
#import "NOCreateNotesViewController.h"

@interface NONotesListViewController ()

@property (nonatomic, strong) NSMutableArray * notes;

@property NSInteger indx;

@end

@implementation NONotesListViewController

- (NSManagedObjectContext *)managedObjectContext
{
    NSManagedObjectContext *context = nil;
    id delegate = [[UIApplication sharedApplication] delegate];
    if ([delegate performSelector:@selector(managedObjectContext)]) {
        context = [delegate managedObjectContext];
    }
    return context;
}


- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"editeNote"]) {
        Note * selectedNote = [self.notes objectAtIndex:[self.tableView indexPathForSelectedRow].row];
        NOCreateNotesViewController * destination = [segue destinationViewController];
        destination.note = selectedNote;
        destination.isEdited = YES;
        self.indx = [self.tableView indexPathForCell:sender].row;
    }
}


- (IBAction) unwindToList:(UIStoryboardSegue *)segue
{
    NOCreateNotesViewController * source = [segue sourceViewController];

    Note * note = source.note;

    if (note != nil &&  source.isEdited == NO) {
        [self.notes addObject:note];
    } else {
        [self.notes replaceObjectAtIndex:self.indx withObject:note];
    }

    [self.tableView reloadData];
}


- (void)viewDidLoad
{
    [super viewDidLoad];

    self.notes = [[NSMutableArray alloc] init];

    NSManagedObjectContext * managedObjectContext = [self managedObjectContext];

    NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Note"];

    self.notes = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];

    [self.tableView reloadData];

}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return self.notes.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...

    Note * note = [self.notes objectAtIndex:indexPath.row];

    cell.textLabel.text = note.content;

    return cell;
}

@end

CreateNotesViewController.h:

#import <UIKit/UIKit.h>
#import "Note.h"

@interface NOCreateNotesViewController : UIViewController

@property (nonatomic, strong) Note * note;
@property BOOL isEdited;

@end

CreateNotesViewController.m:

#import "NOCreateNotesViewController.h"

@interface NOCreateNotesViewController ()

@property (weak, nonatomic) IBOutlet UITextView *noteText;

@property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;

@end

@implementation NOCreateNotesViewController

- (NSManagedObjectContext *) managedObjectContext
{
    NSManagedObjectContext *context = nil;

    id delegate = [[UIApplication sharedApplication] delegate];

    if ([delegate performSelector:@selector(managedObjectContext)]) {
        context = [delegate managedObjectContext];
    }

    return context;
}


- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if (sender != self.saveButton) return;
    if (self.noteText.text.length > 0) {
        self.note = [[Note alloc] init];
        self.note.content = self.noteText.text;
    }

    NSManagedObjectContext * context = [self managedObjectContext];

    if (self.isEdited) {
        [self.note setValue:self.noteText.text forKey:@"content"];
    }

    NSManagedObject *newNote = [NSEntityDescription insertNewObjectForEntityForName:@"Note" inManagedObjectContext:context];

    [newNote setValue:self.noteText.text forKey:@"content"];

    NSError * error = nil;

    if ([context save:&error]) {
        NSLog(@"Can't Save! %@ %@", error, [error localizedDescription]);
    }
}


- (void)viewDidLoad
{
    [super viewDidLoad];

    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


- (void)adjustViewForKeyboardReveal:(BOOL)showKeyboard notificationInfo:(NSDictionary *)notificationInfo
{
    // the keyboard is showing so ƒ the table's height
    CGRect keyboardRect = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    NSTimeInterval animationDuration =
    [[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect frame = self.noteText.frame;

    // the keyboard rect's width and height are reversed in landscape
    NSInteger adjustDelta = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? CGRectGetHeight(keyboardRect) : CGRectGetWidth(keyboardRect);

    if (showKeyboard)
    frame.size.height -= adjustDelta;
    else
    frame.size.height += adjustDelta;

    [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
    [UIView setAnimationDuration:animationDuration];
    self.noteText.frame = frame;
    [UIView commitAnimations];
}


- (void) viewWillAppear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}


- (void) keyboardWillShow:(NSNotification *)aNotification
{
    [self adjustViewForKeyboardReveal:YES notificationInfo:[aNotification userInfo]];
}


- (void) keyboardWillHide:(NSNotification *)aNotification
{
    [self adjustViewForKeyboardReveal:NO notificationInfo:[aNotification userInfo]];
}

And I'm getting this error:

enter image description here

هل كانت مفيدة؟

المحلول

You can't do [[Note alloc] init] because Note is an NSManagedObject subclass.

The designated initializer is awakeFromInsert: which is called after you insert the Note object in a managedObjectContext.

That gets called if you do something like this:

self.note = [Note [NSEntityDescription
    insertNewObjectForEntityForName:@"Note"
    inManagedObjectContext:self.managedObjectContext];

See "Creating and Deleting Managed Objects" in the Core Data Programming guide.

To be clear, you should not be subclassing NSManagedObject manually. You would create an entity called Note in the xcdatamodeld file, declare that it's represented by the class Note, create a new file of the type "Core Data" which would allow Xcode to properly create the class with an awakeFromInsert: function prototype in it. And if you start editing the Note class a lot, you want to look into the MOGenerator tool. xcdatamodeld might be sufficient without having XCode create the class files for you to edit.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top