Ios 默认情况下,核心数据是否使用线程?
我正在考虑使用coreData来存储用户名和密码,以便从用户那里获得持久性。在测试过程中,我注意到当我在保存数据后快速关闭程序并重新启动它以检查数据是否持久化时,它有时会说什么都不存在,然后当我再次重新启动应用程序时,它就会存在。我等待的时间越长,在重新启动应用程序时,持久化数据出现的可能性就越大 我将coreData添加到一个现有的项目中,所以我创建了一个名为DataController.swift的控制器,并从apple复制了建议的代码。代码如下Ios 默认情况下,核心数据是否使用线程?,ios,swift,core-data,swift2,Ios,Swift,Core Data,Swift2,我正在考虑使用coreData来存储用户名和密码,以便从用户那里获得持久性。在测试过程中,我注意到当我在保存数据后快速关闭程序并重新启动它以检查数据是否持久化时,它有时会说什么都不存在,然后当我再次重新启动应用程序时,它就会存在。我等待的时间越长,在重新启动应用程序时,持久化数据出现的可能性就越大 我将coreData添加到一个现有的项目中,所以我创建了一个名为DataController.swift的控制器,并从apple复制了建议的代码。代码如下 import UIKit import Co
import UIKit
import CoreData
class DataController: NSObject {
var managedObjectContext: NSManagedObjectContext
override init() {
// This resource is the same name as your xcdatamodeld contained in your project.
guard let modelURL = NSBundle.mainBundle().URLForResource("AppSettings", withExtension:"momd") else {
fatalError("Error loading model from bundle")
}
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
guard let mom = NSManagedObjectModel(contentsOfURL: modelURL) else {
fatalError("Error initializing mom from: \(modelURL)")
}
let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)
self.managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
self.managedObjectContext.persistentStoreCoordinator = psc
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let docURL = urls[urls.endIndex-1]
/* The directory the application uses to store the Core Data store file.
This code uses a file named "DataModel.sqlite" in the application's documents directory.
*/
let storeURL = docURL.URLByAppendingPathComponent("AppSettings.sqlite")
do {
try psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil)
} catch {
fatalError("Error migrating store: \(error)")
}
}
}
}
我的LoginViewController.swift如下:
import UIKit
import CoreData
class LoginViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var passwordField: UITextField!
let moc = DataController().managedObjectContext
@IBAction func SignUpButtonPressed(sender: UIButton) {
print("sign up")
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldShouldEndEditing(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func viewDidLoad() {
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tap)
print("view loaded, check if already signed in here")
let loggedIn = checkIfLoggedInAlready() //checks database to see
if(loggedIn){
print("was logged in!")
}
}
func checkIfLoggedInAlready() -> Bool{
let fetchRequest = NSFetchRequest(entityName: "AppSettings")
//let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest) //Deletes ALL appsettings entities
do {
let fetchRequest = try moc.executeFetchRequest(fetchRequest) as! [AppSettings]
guard let appSettingsArrayItem = fetchRequest.first where fetchRequest.count>0 else {
print ("no entities found...")
return false
}
guard let username = (appSettingsArrayItem as AppSettings).username else{
print ("username not found")
return false
}
print("number Of AppSetting Entities =\(fetchRequest.count)")
print(username)
//The following code deletes ALL the entities!
//try moc.persistentStoreCoordinator!.executeRequest(deleteRequest, withContext: moc)
//To delete just '1' entry use the code below.
//moc.deleteObject(appSettingsArrayItem)
// try moc.save()//save deletion change.
print("deleted particular entity item")
return true
} catch{
fatalError("bad things happened \(error)")
}
}
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
print("prepar seque")
}
func displayErrorMessage(errorMessage: String){
print("show error console with Error:"+errorMessage)
let alert = UIAlertController(title: "Error", message: errorMessage, preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
switch(identifier){
case "loginSegue":
print("loginSegue Check")
guard let password = passwordField.text!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) where !password.isEmpty else {
displayErrorMessage("Password can not be empty!")
return false
}
guard let username = usernameField.text!.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) where !username.isEmpty else{
displayErrorMessage("Username can not be empty!")
return false
}
let url = "http://mywebsite.com/restapi/v1/userlogin?email="+username+"&password="+password
print(url)
let json = JSON(url:url)
print(json)
if(json["status"].asInt==1){
let entity = NSEntityDescription.insertNewObjectForEntityForName("AppSettings", inManagedObjectContext: moc) as! AppSettings
entity.setValue(username, forKey: "username")
entity.setValue(password, forKey: "password")
entity.setValue(json["tokenid"].asString, forKey: "token")
entity.setValue(json["roleid"].asInt, forKey: "roleid")
entity.setValue(json["role"].asString, forKey: "role")
entity.setValue(json["companyid"].asInt , forKey: "companyid")
entity.setValue(json["isdev"].asInt, forKey: "isdev")
//save token and other details to database.
do {
try moc.save()
print("saved to entity")
}catch{
fatalError("Failure to save context: \(error)")
}
//token
//roleid int
//role
//companyid int
return true //login succesfull
}else{
displayErrorMessage("Incorrect Username or Email")
return false//failed
}
default:
displayErrorMessage("Unknown Error Related To Segue Not Found")
}
return false //if it gets to this point assume false
}
}
要测试我的代码,只需取消注释删除实体的部分(//moc.deleteObject(appSettingsArrayItem)
)在函数checkiLoggedInready()中
简言之,虽然这个问题的答案很简单,是或不是,但我有一种预感,这就是为什么延迟很重要。我认为它是线程化的,因为DataController.swift中有一行
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0))
但不确定这是否是影响它的因素。创建实体的代码在shouldperformsegue中完成,标识符为LoginViewController.swift,默认情况下不是这样。所有NSManagedObject都绑定到具有自己队列的NSManagedContext。如果需要并发性,则需要使用专用队列创建另一个NSManagedContext。您可以在此处阅读有关核心数据中并发性的内容:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0))
此外,切勿对核心数据使用
dispatch\u async
。每个上下文都有自己的peformBlock
,在其队列上运行。默认情况下不是这样。所有NSManagedObject都绑定到具有自己队列的NSManagedContext。如果需要并发性,则需要使用专用队列创建另一个NSManagedContext。您可以在此处阅读有关核心数据中并发性的内容:
此外,切勿对核心数据使用
dispatch\u async
。每个上下文都有自己的peformBlock
,在其队列上运行。仅供参考使用CoreData存储用户凭据是个坏主意,它不够安全。我绝对建议您使用钥匙链来存储数据。你可以在这里了解更多信息:谢谢你的帮助,我不知道,我会查清楚的。仅供参考,使用CoreData存储用户凭据是个坏主意,它不够安全。我绝对建议您使用钥匙链来存储数据。您可以在这里了解更多信息:感谢您的帮助,我不知道,我们将确定查找。我有一个与此类似的命令问题,让fetchRequest=try moc.executeFetchRequest(fetchRequest)as![AppSettings],(与上面列出的代码相同)似乎有时它会获取实体,有时则不会。大多数时候,它会赚钱,但有时不会。有什么办法可以保证它会发生吗?(或者至少给它一点时间来真正正确地运行它的代码我的命令也有类似的问题,让fetchRequest=try moc.executeFetchRequest(fetchRequest)as![AppSettings],(与上面列出的代码相同)似乎有时它会获取实体,有时它不会。大多数时候它会获取,但有时它不会。有没有办法确保它会获取实体?(或者至少给它时间实际正确运行代码