我正在尝试创建一个用户可以添加条目的iPhone应用程序.当他按下一个新条目时,会弹出一个框,询问他一些信息.然后他可以按"取消"或"保存"以丢弃数据或将其保存到磁盘.
为了保存,我使用的是Core Data框架,它运行得很好.但是,我无法使用"取消"按钮.当窗口弹出,询问信息时,我在托管对象上下文(MOC)中创建一个新对象.然后当用户按下取消时,我尝试使用属于MOC的NSUndoManager.
我还想使用嵌套的撤消组来执行此操作,因为可能存在嵌套组.
为了测试这个,我写了一个简单的应用程序.该应用程序只是启用了Core Data的"基于Window的应用程序"模板.对于Core Data模型,我创建了一个名为"Entity"的实体,其整数属性为"x".然后在applicationDidFinishLaunching中,我添加以下代码:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after app launch
unsigned int x=arc4random()%1000;
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager beginUndoGrouping];
NSManagedObject *entity=[NSEntityDescription insertNewObjectForEntityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[entity setValue:[NSNumber numberWithInt:x] forKey:@"x"];
NSLog(@"Insert Value %d",x);
[self.managedObjectContext processPendingChanges];
[self.managedObjectContext.undoManager endUndoGrouping];
[self.managedObjectContext.undoManager undoNestedGroup];
NSFetchRequest *fetchRequest=[[NSFetchRequest alloc] init];
NSEntityDescription *entityEntity=[NSEntityDescription entityForName:@"Entity"
inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entityEntity];
NSArray *result=[self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
for(entity in result) {
NSLog(@"FETCHED ENTITY %d",[[entity valueForKey:@"x"] intValue]);
}
[window makeKeyAndVisible];
}
Run Code Online (Sandbox Code Playgroud)
这个想法很简单.尝试插入新的Entity对象,撤消它,获取MOC中的所有Entity对象并将其打印出来.如果一切正常,最后应该没有对象.
但是,我得到了这个输出:
[Session started at 2010-02-20 13:41:49 -0800.]
2010-02-20 13:41:51.695 …Run Code Online (Sandbox Code Playgroud) 我有NSManagedObject两个属性:
NSNumber *score;
NSDate *score_timestamp;
Run Code Online (Sandbox Code Playgroud)
我希望score_timestamp每次更新时都会更新我的字段score.
我显然不能使用-willSave方法,因为我的上下文偶尔score_timestamp会被保存,并且不会是最新的.因此,我应该覆盖-setScore:或设置我的托管对象作为其自己score字段的键值观察器.
该-setScore:解决方案似乎很容易:
- (void) setScore:(NSNumber *)score
{
[self willChangeValueForKey:@"score"];
[self setPrimitiveScore:score];
[self didChangeValueForKey:@"score"];
self.score_timestamp = [NSDate date];
}
Run Code Online (Sandbox Code Playgroud)
以这种方式做事有什么警告吗?或者我应该使用KVO解决方案?
更新
到目前为止,我收到了两个响应,我的代码无法通过setValue: forKey:,我还在等待示例.天真的召唤[(NSManagedObject *)myObject setValue:value forKey:@"score"]呼唤我的二传手.
因此,如果我切换到KVO解决方案,我应该addObserver:在所有awake方法中将其删除willTurnIntoFault吗?或者那不是那么简单?
我需要为索引数据提供一些唯一且一致的ID,我尝试使用NSManagedObject的objectID,但看起来对于同一个实体,它的objectID不断变化,是否有人知道这是不一致的?
有没有办法删除已插入上下文但尚未保存的单个托管对象?我想删除单个对象,而不是回滚整个上下文.我已经尝试过调用deleteObject:但它会引发异常,因为根据核心数据,该对象在MOC中尚不存在.通过查看核心数据的插入对象属性,我肯定知道它已被插入,并且通过查看已删除的对象,我知道它已被标记为删除.基本上我想"取消插入"对象.先保存然后删除是不可接受的.谢谢.
我目前正在将我的项目更新为Swift 3,并且我将所有NSDate方法和扩展都移动到Date以便在应用程序中保持标准.
问题是我使用Xcode自动生成我的NSManagedObject子类,它生成日期属性为NSDate而不是Date.
有没有办法用日期属性作为日期生成它?
Core Data本身支持各种属性类型,例如字符串,日期和整数(分别表示为NSString,NSDate和NSNumber的实例).
所以我觉得这不可能= /
在我的核心数据模型中,a Person有一个或多个Cars,由无序的多对多关系'Cars'指定.通常情况下,我需要检索一个人的汽车datePurchased,或通过dateLastUsed.
到现在为止,我已经将我自己的方法来Person进行carsByDatePurchased.这使用排序描述符对NSSet进行排序cars并返回NSArray.
可能/我应该使用Fetched Property吗?每次我需要按特定顺序购买汽车时,我会遇到使用排序描述符的一些性能开销,甚至可能实现我自己的缓存carsByDatePurchased.看起来像是为我缓存了获取的属性 - 这是正确的吗?
获取属性与我自己的实现有什么限制?
至关重要的是,获取的财产的价值在执行之间是否仍然存在?如果我更新了fetched属性并保存了我的上下文,那么下次启动应用程序时是否存储了值?
我对如何使用一些核心数据的NSManagedObject子类来处理持久数据和非持久数据有一些想法.
假设您有一个配方应用程序,显示您自己的CoreData配方列表,在同一个应用程序中,您也可以搜索其他用户配方.这些其他用户配方当然来自API,我们不希望将它们保存到核心数据中.但我们想要的是我们的配方细节View Controller,无论是给定持久配方还是非持久性配方,它都可以起作用.我自然认为我们应该在数据周围使用相同的对象包装器,让我们的View Controller对数据的来源视而不见.
问题是NSManagedObject子类不能手动初始化,必须插入上下文.这对我们的其他用户食谱不利.另一方面,对于我们自己的配方,我们需要将这些对象插入到上下文中.
我有几个解决方案,但我真的很想看看你们对这个问题的看法.
您是否认为这是一些实现问题,应该通过将两个数据对象包装到一个对象中来解决?例如,通过覆盖所有getter和setter来处理coredata对象和NSDictionary对象?
或者它是一个体系结构问题,您可以通过嵌套NSManagedContext或使用多个持久性存储(一个在内存中,另一个在Sqlite中)来解决它?
我正在使用RestKit RKObjectManager从我的服务器获取数据并存储在核心数据中(参见我的其他帖子)
我想配置数据库中剩余的旧条目的删除行为.
我看到RKEntityMapping类中有一个deletionPredicate属性,但我知道只有当服务实际返回标记为"要删除"的要删除的对象时才会使用它.(我对吗?)
在我的情况下,当一些对象必须被删除时,它们只是不被服务器返回,我想让我的客户端应用程序理解这意味着它应该删除它们.
那可能吗?如果是这样,怎么样?
编辑:
好的,我查看了该链接,并将此获取请求块添加到我的RKObjectManager:
[[RKObjectManager sharedManager] addFetchRequestBlock:^NSFetchRequest *(NSURL *URL) {
RKPathMatcher *pathMatcher = [RKPathMatcher pathMatcherWithPattern:@"/path_to_ressource"];
NSDictionary *argsDict = nil;
BOOL match = [pathMatcher matchesPath:[URL relativePath] tokenizeQueryStrings:NO parsedArguments:&argsDict];
if (match) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"entityId" ascending:YES] ];
return fetchRequest;
}
return nil;
}];
Run Code Online (Sandbox Code Playgroud)
我保留了sortDescriptor,但这里的目的究竟是什么?
Xcode 6有很多错误.但我不太确定这是不是一个bug.可能不是因为这是我刚刚学习的东西.
我的问题是,每当我尝试实例化NSManagedObject的子类时,我都没有选择将entity: NSEntityDescription和NSManagedContext: insertIntoManagedContext参数传递给构造函数,Xcode在调用中说"额外参数'实体'"
我从头开始创建一个新的Xcode项目,看看我是否可以在一个较小的,最小的项目中重新创建问题.
ToDoList.Item Item在数据模型检查器中设置为实体类.
这是代码:
override func viewDidLoad() {
super.viewDidLoad()
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let ent = NSEntityDescription.entityForName("Item", inManagedObjectContext: context)!
//compiler complains here
var item = Item(entity: ent, insertIntoManagedObjectContext: context)!
}
Run Code Online (Sandbox Code Playgroud)
这是子类:
import UIKit
import CoreData
class Item: NSManagedObject {
@NSManaged var title: String
@NSManaged var completed: Bool
}
Run Code Online (Sandbox Code Playgroud)
所有帮助表示赞赏.
我有一个用于NSPersistentCloudKitContainer与 iCloud 同步数据的应用程序。用户报告偶尔数据丢失,之后我开始调试我的实现。
我的应用程序实现的一部分是显示一个弹出窗口,其中显示信息并有一个确认按钮。当用户单击此按钮时,自定义NSManagedObject子类的一个或多个实例将被修改。
同时,NSPersistentCloudKitContainer在应用程序退出并激活时触发镜像过程。当用户单击上述确认按钮时会发生这种情况。它通过执行NSCloudKitMirroringExportRequest和NSCloudKitMirroringImportRequest请求来做到这一点。
换句话说,在我的应用程序中,数据同时被修改(通过代码显式)和镜像(通过 CloudKit 隐式),这就是出错的地方。
本质上是这样的:
NSTimeInterval实例的属性 ( )NSManagedObject增加(例如 0 + 1 = 1)。NSPersistentCloudKitContainer 当应用程序激活或退出时隐式开始镜像数据。在这个阶段,我希望属性的值与最新的(本地)更改相匹配(因此在我的示例 2 中)。但相反,它匹配初始增量(因此在我的示例 1 中),覆盖我最新的(本地)更改导致数据丢失。显然,NSCloudKitMirroringImportRequest恢复到镜像进程启动时的状态,这也可以在日志中看到:
CoreData: debug: CoreData+CloudKit: -[PFCloudKitImporterZoneChangedWorkItem applyAccumulatedChanges:error:]
[…]
Importing updated records:
(
"<CKRecord: 0x10225b560; recordID=5458F9C8-7BE2-4563-92DE-650ED4C643F5:(com.apple.coredata.cloudkit.zone:__defaultOwner__), recordChangeTag=23, values={\n \"CD_activity\" = \"3E497A4C-6467-48F4-B7F4-6F1B2B7BC779\";\n \"CD_date\" = \"2020-04-26 07:28:00 +0000\";\n \"CD_duration\" = \"1\";\n \"CD_entityName\" = Mutation;\n}, recordType=CD_Mutation>"
)
Run Code Online (Sandbox Code Playgroud)
在这个阶段,我不确定这是否是NSPersistentCloudKitContainer …
macos nsmanagedobject swift cloudkit nspersistentcloudkitcontainer
nsmanagedobject ×10
core-data ×7
ios ×6
macos ×2
objective-c ×2
swift ×2
cloudkit ×1
cocoa ×1
iphone ×1
nsdate ×1
nspersistentcloudkitcontainer ×1
restkit ×1
swift3 ×1
undo ×1
xcode ×1