开发者

Advice on dynamically altering default core data model content

开发者 https://www.devze.com 2023-02-11 00:37 出处:网络
I\'ve added the following image to help illustrate the problem better: Hi, I\'m looking for the best starting point to alter the data stored my core data model directly - speaking as someone who\'

I've added the following image to help illustrate the problem better:

Advice on dynamically altering default core data model content

Hi,

I'm looking for the best starting point to alter the data stored my core data model directly - speaking as someone who's new to the area. From my reading I'm pretty confident I shouldn't touch my NSArrayController, which was my natural instinct, and that I should always tackle the model. This makes sense but because I've used bindings and core data, xcode has generated everything for me and I don't have a sense of building up a class from scratch myself.

For my initial task, I have a 'jobs' entity and NSArrayController. It has a jobTotalHours attribute that's a string in the 00:00:00 format and has a corresponding 'Hours' column for each job in an NSTableView. Separate to this, I have a stopwatch button that's linked to a text field next to it, displaying time as a 00:00:00 string. I have a class working that starts and stops a timer counting and displays it in increments of hours, minutes and seconds.

What I need to do is to make the timer add time onto the jobTotalHours attribute for the current job highlighted in the NSTableView. The separate textfield has now been bound to display the time of the current highlighted hours column so that part's taken care of. In other words, the timer was originally adding time to a test variable and displaying it in an autonomous text field for testing reasons. Now I need it to add time onto whatever job is highlighted in a table view and I need to access the model programmatically without being sure of what step to take first.

Thanks in advance for any advice. I'll include the timer class below if it's any use. I'm pretty sure it's rough and bad but it works:

timerController.h:

#import <Cocoa/Cocoa.h>
BOOL timerStarted;
int timerCount;
int timerSeconds;
int timerMinutes;
int timerHours;
NSString *timerString;
NSString *timerFieldSeconds;
NSString *timerFieldMinutes;
NSString *timerFieldHours;

@interface timerController : NSObject <NSApplicationDelegate> {
    NSWindow *window;
    NSTimer *timerNoOne;
    IBOutlet NSCell *timerOneOutputLabel;
    IBOutlet id timerClockField;
}
-(IBAction)toggleTimerClock:(id)sender;
@property (assign) IBOutlet NSWindow *window;

@end

timerController.m:

#import "timerController.h"


@implementation timerController
-(IBAction)toggleTimerClock:(id)sender
{
    if (timerStarted==FALSE) {
        timerStarted = TRUE;
    } else {
        timerStarted = FALSE;
    }
}

@synthesize window;


- (void) awakeFromNib {
    // clear timer 
    [timerClockField setStringValue:@"00:00:00"];
    // initialize timer to count each second
    timerNoOne = [NSTimer scheduledTimerWithTimeInterval:1 
                            target:self 
                            selector:@selector(updateTimerNoOne:) 
                            userInfo:nil 
                            repeats:YES];   

}


- (void) updateTimerNoOne:(NSTimer *) timer {
    if (timerStarted==FALSE) {
        // do nothing. Timer is switched off.
    } else {
        timerCount = timerCount + 1;
        timerSeconds = fmod(timerCount, 60);
        timerMinutes = floor(timerCount / 60);
        timerHours = floor(timerCount / 3600);

        if (timerSeconds < 10) { // add a leading 0 for formatting reasons.
            timerFieldSeconds = [NSString stringWithFormat:@"0%d",timerSeconds];
        } else {
            timerFieldSeconds = [NSString stringWithFormat:@"%d",timerSeconds];
        }

        if (timerMinutes < 10) {
            timerFieldMinutes = [NSString stringWithFormat:@"0%d",timerMinutes];
        } else {
            timerFieldMinutes = [NSString stringWithFormat:@"%d",timerMinutes];
        }

        if (timerHours < 10) {
            timerFieldHours = [NSString stringWithFormat:@"0%d",timerHours];
        } else {
            timerFieldHours = [NSString stringWithFormat:@"%d",timerHours];
        }

        NSString *timerString = [NSString stringWithFormat:@"%@:%@:%@",timerFieldHours,timerFieldMinutes,timerFieldSeconds];
        //[timerClockField setStringValue:timerString];

    }
}
@end

Update:

From reading some more, I'm wondering if it's a better approach for me to update the string in the textcell itself on each second of timer change and then only commit changes to the model on the timer finishing (e.g. the clock was stopped). Previously I was thinking of saving the model's jobTotalHours string second by second as this was directly altering the model and avoiding controllers, which I thought was the advised route to take.

Update:

I had a subclass set up for NSTableView and NSArrayController. I was able to use them to detect selection changes to the rows in the table and print them out to the console. The subclass was called:

@interface modelUtilController : NSObject

Which performed the above tasks fine. I now wanted an outlet to the NSManagedObject so that I could directly manipulate assets in it while keeping outlets to the NSTableView to detect changed in row selection. I read that the subclass should be

@interface modelUtilController : NSManagedObject

which I changed it to and included an outlet to the data model. This crashes the original detection for changes in row selection, so I'm doing something wrong now. Perhaps I have to separate the subclass into 2?

Update : Possibly Complete

Ok I think I've solved this after 3 days at it. As far as I can see it's working but I haven't put it fully to work yet. Basically I created a separate function that I call from my timer once every second:

void amendTotalHours(id anObject)

This function uses my jobs NSArrayController and then finds the current value in the hours column using:

NSArray *selectedObjectsArray = [anObject selectedObjects];
NSManagedObjectModel *firstSelectedObject = [selectedObjectsArray objectAtIndex:0];
NSString *readCurrentTime = [firstSelectedObject valueForKey:@"jobTotalHours"];

I then convert the string of time formatted into 00:00:00 to an integer of the total seconds. I add one onto this for each call from the timer and then convert t开发者_Python百科he seconds back into a string in the 00:00:00 format. Finally, I send this back to the NSArrayController using:

[firstSelectedObject setValue:[NSString stringWithFormat:@"%@", timeValue] forKey:@"jobTotalHours"];

And cry a (maybe temporary) sigh of relief.


Ok I think I've solved this after 3 days at it. As far as I can see it's working but I haven't put it fully to work yet. Basically I created a separate function that I call from my timer once every second:

void amendTotalHours(id anObject)

This function uses my jobs NSArrayController and then finds the current value in the hours column using:

NSArray *selectedObjectsArray = [anObject selectedObjects];
NSManagedObjectModel *firstSelectedObject = [selectedObjectsArray objectAtIndex:0];
NSString *readCurrentTime = [firstSelectedObject valueForKey:@"jobTotalHours"];

I then convert the string of time formatted into 00:00:00 to an integer of the total seconds. I add one onto this for each call from the timer and then convert the seconds back into a string in the 00:00:00 format. Finally, I send this back to the NSArrayController using:

[firstSelectedObject setValue:[NSString stringWithFormat:@"%@", timeValue] forKey:@"jobTotalHours"];

And cry a (maybe temporary) sigh of relief.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号