关于动态更改默认核心数据模型内容的建议
我添加了以下图像来帮助更好地说明问题:
嗨,
我正在寻找最好的直接更改存储我的核心数据模型的数据的起点 - 作为该领域的新手发言。从我的阅读来看,我非常有信心我不应该碰我的 NSArrayController
,这是我的本能,而且我应该始终处理模型。这是有道理的,但因为我已经使用了绑定和核心数据,xcode 已经为我生成了所有内容,而且我自己没有从头开始构建类的感觉。
对于我的初始任务,我有一个“jobs”实体和 NSArrayController
。它有一个 jobTotalHours 属性,该属性是 00:00:00 格式的字符串,并且在 NSTableView
中为每个作业都有一个相应的“Hours”列。除此之外,我还有一个秒表按钮,该按钮链接到旁边的文本字段,将时间显示为 00:00:00 字符串。我有一个类可以启动和停止计时器计数,并以小时、分钟和秒的增量显示它。
我需要做的是让计时器将时间添加到 NSTableView
中突出显示的当前作业的 jobTotalHours 属性上。现在,单独的文本字段已绑定为显示当前突出显示的小时列的时间,以便处理该部分。换句话说,出于测试原因,计时器最初是向测试变量添加时间并将其显示在自主文本字段中。现在,我需要它为表视图中突出显示的任何作业添加时间,并且我需要以编程方式访问模型,而不确定首先要采取什么步骤。
预先感谢您的任何建议。如果有任何用处,我将在下面包含计时器类。我很确定它很粗糙而且很糟糕,但它有效:
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
更新:
通过阅读更多内容,我我想知道对我来说,在计时器更改的每一秒更新文本单元本身中的字符串,然后仅在计时器完成时提交对模型的更改(例如时钟停止)是否是更好的方法。之前我正在考虑逐秒保存模型的 jobTotalHours 字符串,因为这会直接改变模型并避免控制器,我认为这是建议采取的路线。
更新:
我为NSTableView
和NSArrayController
设置了一个子类。我能够使用它们来检测表中行的选择更改并将其打印到控制台。该子类被称为:
@interface modelUtilController : NSObject
它很好地执行了上述任务。我现在想要一个到 NSManagedObject 的出口,以便我可以直接操作其中的资产,同时保留到 NSTableView 的出口以检测行选择的更改。我读到子类应该是
@interface modelUtilController : NSManagedObject
我将其更改为的子类,并包含数据模型的出口。这会破坏行选择更改的原始检测,所以我现在做错了。也许我必须将子类分成 2 个?
更新:可能完成
好的,我想我已经在 3 天后解决了这个问题。据我所知,它正在工作,但我还没有完全投入使用。基本上,我创建了一个单独的函数,每秒从计时器调用一次:
void amendTotalHours(id anObject)
该函数使用我的作业 NSArrayController ,然后使用以下方法查找小时列中的当前值:
NSArray *selectedObjectsArray = [anObject selectedObjects];
NSManagedObjectModel *firstSelectedObject = [selectedObjectsArray objectAtIndex:0];
NSString *readCurrentTime = [firstSelectedObject valueForKey:@"jobTotalHours"];
然后,我将格式化的时间字符串转换为00:00:00 为总秒数的整数。我为计时器的每次调用添加一个,然后将秒数转换回 00:00:00 格式的字符串。最后,我使用以下命令将其发送回 NSArrayController:
[firstSelectedObject setValue:[NSString stringWithFormat:@"%@", timeValue] forKey:@"jobTotalHours"];
并松了一口气(也许是暂时的)。
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'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 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我想三天后我已经解决了这个问题。据我所知,它正在工作,但我还没有完全投入使用。基本上,我创建了一个单独的函数,每秒从计时器调用一次:
该函数使用我的作业 NSArrayController ,然后使用以下方法查找小时列中的当前值:
然后,我将格式化的时间字符串转换为00:00:00 为总秒数的整数。我为计时器的每次调用添加一个,然后将秒数转换回 00:00:00 格式的字符串。最后,我使用以下命令将其发送回 NSArrayController:
并松了一口气(也许是暂时的)。
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:
This function uses my jobs
NSArrayController
and then finds the current value in the hours column using: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:
And cry a (maybe temporary) sigh of relief.