【发布时间】: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 是实现这些功能的更好方法,并且仍然允许未来实现获取和发送在线数据的能力吗?我已经将大部分代码编写到与应用委托相关的函数中。
【问题讨论】: