主应用程序委托中的核心数据小部件基本功能?
Posted
技术标签:
【中文标题】主应用程序委托中的核心数据小部件基本功能?【英文标题】:Core Data Widget Basic Function in Main App Delegate? 【发布时间】:2015-09-28 18:12:30 【问题描述】:我刚开始在我的 Swift 2.0 ios 应用程序中实现小部件功能,经过大量研究后,我发现 SwiftWidget github 链接使用 CoreDataStore 文件,该文件包含通常包含在 App Delegate plus 中的所有核心数据功能能够将其设置为主队列或私有队列,这很好。
我的问题是,我真的需要在 App Delegate 之外进行设置吗,因为我的应用只使用基本的核心数据功能,而且无论如何都不是大型数据库。我问只是因为我创建了我的应用程序的克隆版本来试验更改并尝试使用 SwiftWidget 中修改为包含我所有应用程序信息的文件。
对于那些对这个文件使用的实际代码感兴趣的人,我在下面链接了它:
import Foundation
import CoreData
public class CoreDataStore
class var sharedInstance : CoreDataStore
struct Static
static let instance : CoreDataStore = CoreDataStore()
return Static.instance
// MARK: - Notifications
func contextDidSavePrivateQueueContext(notification: NSNotification)
if let context = self.mainQueueCtxt
self.synced(self, closure: () -> () in
context.performBlock(() -> Void in
context.mergeChangesFromContextDidSaveNotification(notification)
)
)
func contextDidSaveMainQueueContext(notification: NSNotification)
if let context = self.privateQueueCtxt
self.synced(self, closure: () -> () in
context.performBlock(() -> Void in
context.mergeChangesFromContextDidSaveNotification(notification)
)
)
func synced(lock: AnyObject, closure: () -> ())
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL =
// The directory the application uses to store the Core Data store file. This code uses a directory named "com.xxx.Appname" in the application's documents Application Support directory.
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
return urls[urls.count-1]
()
lazy var managedObjectModel: NSManagedObjectModel =
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = NSBundle.mainBundle().URLForResource("Appname", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? =
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let directory = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.xxx.Appname")
let url = directory?.URLByAppendingPathComponent("Appname.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
do
try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
catch var error1 as NSError
error = error1
coordinator = nil
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this 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.
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
catch
fatalError()
return coordinator
()
// MARK: - NSManagedObject Contexts
public class func mainQueueContext() -> NSManagedObjectContext
return self.sharedInstance.mainQueueCtxt!
public class func privateQueueContext() -> NSManagedObjectContext
return self.sharedInstance.privateQueueCtxt!
lazy var mainQueueCtxt: NSManagedObjectContext? =
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
var managedObjectContext = NSManagedObjectContext(concurrencyType:.MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator
return managedObjectContext
()
lazy var privateQueueCtxt: NSManagedObjectContext? =
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
var managedObjectContext = NSManagedObjectContext(concurrencyType:.PrivateQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator
return managedObjectContext
()
// MARK: - Core Data Saving support
public class func saveContext (context: NSManagedObjectContext?)
if let moc = context
var error: NSError? = nil
if moc.hasChanges
do
try moc.save()
catch let error1 as NSError
error = error1
// 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.
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
// MARK: - NSManagedObject Extension
extension NSManagedObject
public class func createInContext(entityName: String, context: NSManagedObjectContext) -> AnyObject
let entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
return NSManagedObject(entity: entity!, insertIntoManagedObjectContext: context)
public class func findAllInContext(entityName: String, context: NSManagedObjectContext) -> [AnyObject]?
let request = NSFetchRequest(entityName: entityName)
var error: NSError?
let result: [AnyObject]?
do
result = try context.executeFetchRequest(request)
catch let error1 as NSError
error = error1
result = nil
return result
再次重复主要问题,我能否仅使用 App Delegate 内部的 App Delegate 函数或通过将这些函数传输到 .swift 文件来有效地从我的主应用程序和今天的扩展程序读取/写入核心数据?如果不是,并且需要这种类型的文件,我将能够使用与应用程序委托中相同的获取命令和保存命令,还是我需要重写所有视图控制器代码,获取和保存以调用指定的createincontext 或 findallincontext 的函数?如果我现在并没有真正获取在线数据或导出在线数据,我应该只使用应用委托的堆栈构建吗?
MagicRecord 是实现这些功能的更好方法,并且仍然允许未来实现获取和发送在线数据的能力吗?我已经将大部分代码编写到与应用委托相关的函数中。
【问题讨论】:
【参考方案1】:AppDelegate 的工作是处理应用程序启动、退出和背景/前景转换。您的核心数据堆栈的工作是处理您的数据模型。这些是不同的职责领域,属于不同的类。
是的,您可以将所有内容混杂到 AppDelegate 中。对于一个玩具项目,你会侥幸逃脱。但这是草率的做法。当您想要提取该数据模型代码并在另一个项目中使用它时,您会怎么做?或者将您的项目从 iOS 移植到 tvOS 或 OS X?
【讨论】:
我很好奇为什么苹果在最初创建项目时实际上并没有切换核心数据堆栈的创建位置。在我看来,Swift 的处理方法是将核心数据堆栈设置在它自己的 .swift 文件中,这样就可以使用它,而无需为基本的核心数据使用进行太多修改。不管我对基本保存函数和获取函数的看法如何,应用程序委托中的核心数据堆栈应该能够复制到它自己的文件中,然后初始化为一个类对吗? 是的,将它放在自己的类中很好,这也是我在自己的项目中所做的。苹果的模板代码中有很多不好的例子!不一定要将它们视为最佳实践的样本。至于 Core Data,看看 Marcus Zarra 的堆栈,它很好地处理了多个父/子上下文,在正确的时间快速保存,并保持边界清晰。这篇文章在 Objective-C 中,但你可以在 Swift 中使用相同的逻辑:martiancraft.com/blog/2015/03/core-data-stack 阅读您的评论后,我决定承担将所有内容转换为自己的文件的任务,并在暂停应用程序以及关闭应用程序时执行保存调用。我仍在学习的一件事,但认为我在阅读数小时后现在已经理解了并发性。我不确定我的模型是否需要它,但是在后台保存而不是在加载基本用户功能的主线程上的想法对我很有吸引力。尽管我对 Objective-C 并不完全精通,但我会阅读这篇文章,但我相信概念是相同的。 是的,API 是一样的。它们在 Swift 中的发音与在 Objective-C 中的发音不同。近年来关于 Core Data 的 WWDC 视频涵盖了并发性。以上是关于主应用程序委托中的核心数据小部件基本功能?的主要内容,如果未能解决你的问题,请参考以下文章