Swift 3 / iOS 10, Proper Core Data Usage - ios

Before upgrading my apps to Swift 3 and iOS 10, I had no problems with using CoreData as a data store for simple objects. Lightweight Migrations were simple, saving and fetching was simple, ect. But ever since the recent upgrade, I have had nothing but trouble with CoreData.
My question is in two parts. First, does anyone know of any good resources to help me learn how CoreData works behind the scenes so I can get better at debugging it? Apple's docs are extremely limiting, and all the articles I read act like the new CoreData is so simple. I have decent experience with relational databases, so CoreData is adding an uncomfortable layer of abstraction for me.
Second, what is wrong with the following code? Lightweight migrations aren't working as they did before iOS 10, using this code. Objects are saving to CoreData (I can interact with them in app after saving), but then disappear after the app is restarted.
lazy var persistentContainer: NSPersistentContainer = {
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
let container = NSPersistentContainer(name: "MY_APP")
container.persistentStoreDescriptions = [description]
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
container.persistentStoreDescriptions = [description]
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
I'm using a separate file to abstract the storing of my objects:
class Repository
{
func getContext () -> NSManagedObjectContext
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
func delete<T>(_ a: some T)
{
getContext().delete(a as! NSManagedObject)
}
// ----------- Password Repo ----------
func savePassword(name: String, hint: String, un: String) {
let context = getContext()
//retrieve the entity that we just created
let entity = NSEntityDescription.entity(forEntityName: "Password", in: context)
let transc = NSManagedObject(entity: entity!, insertInto: context)
//set the entity values
transc.setValue(name, forKey: "name")
transc.setValue(hint, forKey: "thing")
transc.setValue(un, forKey: "newThing")
//save the object
do {
try context.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
func updatePassword(pas: Password) -> Password
{
let context = getContext()
// sec.is_new = false
// TODO, add updates
// Try updating the model in the DB
do {
try context.save()
} catch {
print(error)
}
return pas
}
func fetchPasswords() -> [Password]
{
let context = getContext()
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<Password> = Password.fetchRequest() as! NSFetchRequest<Password>
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
//go get the results
let searchResults = try getContext().fetch(fetchRequest)
return searchResults
} catch {
print("Error with request: \(error)")
}
return []
}
// ----------- End Password Repo ----------
// ----------- Hints Repo ----------
func saveHint (name: String, hint: String) {
let context = getContext()
//retrieve the entity that we just created
let entity = NSEntityDescription.entity(forEntityName: "Hint", in: context)
let transc = NSManagedObject(entity: entity!, insertInto: context)
//set the entity values
transc.setValue(value1, forKey: "some_string")
transc.setValue(value2, forKey: "some_thing")
//save the object
do {
try context.save()
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
func fetchHints() -> [Hint]
{
let context = getContext()
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<Hint> = Hint.fetchRequest() as! NSFetchRequest<Hint>
let sortDescriptor = NSSortDescriptor(key: "my_key", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
//go get the results
let searchResults = try getContext().fetch(fetchRequest)
return searchResults
} catch {
print("Error with request: \(error)")
}
return []
}
}
Then I call this Repository class like so:
Repository().savePassword(name: nameText.text!, hint: hintSoFarLabel.text!, un: "Hey")
The Repository class is working, until I restart the app...
I'm also trying to migrate to a new version of my Core Data Model which simply adds a non-optional String attribute (with default value), which would be a simple lightweight migration in iOS 9/Swift 2. What am I missing about swift 3 lightweight migrations?
I have no doubt that the problem is me not understanding CoreData in iOS 10 well enough. I've been a software engineer for a while, but I've only been working with iOS and Swift for a few months, so please be gentle. And thank's in advance!

Well, I feel like an idiot. I added a non-optional string and didn't give it a default value. I always gave default values to non-string types, but the way Xcode is set up made it appear that it would just give strings a default value of "" if no other was given.
Adding a default value to the new attribute allowed the migration to work in Swift3/iOS10. Noob mistake, but maybe it will help someone here in the future.

Related

how to validate login form into next page using Sqllite in iOS?

**this is to how to create a login validation form to move from login to next view controller **
**fetching the data from database**
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
**it stores the data**
let managedContext = appDelegate.persistentContainer.viewContext
//it fetches the data
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Details")
**validation code to check it but the condition fails**
do {
let result = try managedContext.fetch(fetchRequest)
for data in result as! [NSManagedObject] {
if ([emailid.text].count != 0 && [password.text].count != 0){
if (emailid.text == data.value(forKey: "emailId") as? String) && (password.text == data.value(forKey: "passWord") as? String){
let secondvc = storyboard?.instantiateViewController(withIdentifier: "loginVcID") as! loginVc
self.navigationController?.pushViewController(secondvc, animated: true)
}
in this condition it is not moving to next view controller
to check another condition
}
else {
self.label.text = "enter a valid data"
}
}
}
**when it fails it goes to catch to show that**
catch
{
print("Failed")
}
}
}
**this code is for registration to save into database**
**to create a database and store the value**
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let detailEntity = NSEntityDescription.entity(forEntityName: "Details", in: managedContext)!
** creation of database**
let detail = NSManagedObject(entity: detailEntity, insertInto: managedContext)
detail.setValue(username.text, forKeyPath: "userName")
detail.setValue(emailid.text, forKey: "emailId")
detail.setValue(password.text, forKey: "passWord")
detail.setValue(city.text, forKey: "city")
**saving the data**
do {
try managedContext.save()
}
** it display whatever in that method**
catch let error as NSError
{
its shows error when it fails
print("Could not save. (error), (error.userInfo)")
}
Go to you appDelegate, you will find a line // MARK: - Core Data stack & // MARK: - Core Data Saving support, remove the saveContext() function & also remove persistentContainer.. Then
Add this class to your project
final class PersistenceManager {
private init() {}
static let shared = PersistenceManager()
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded 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.
*/
let container = NSPersistentContainer(name: "ProjectNAME")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() 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.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
lazy var context = persistentContainer.viewContext
// MARK: - Core Data Saving support
func save() {
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() 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.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
func fetch<T: NSManagedObject>(_ objectType: T.Type) -> [T] {
let entityName = String(describing: objectType)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
do {
let fetchedObjects = try context.fetch(fetchRequest) as? [T]
return fetchedObjects ?? [T]()
} catch {
return [T]()
}
}
func deleteAll<T: NSManagedObject>(_ objectType: T.Type) {
let entityName = String(describing: objectType)
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try persistentContainer.persistentStoreCoordinator.execute(deleteRequest, with: context)
} catch {
print(error.localizedDescription)
}
}
func delete(_ object: NSManagedObject) {
context.delete(object)
save()
}
}
To fetch data
PersistenceManager.shared.fetch(User.self)
To delete data
PersistenceManager.shared.delete(user)
To create user
let newUser = Users(context: PersistenceManager.shared.context)
newUser.name = "Zero Cool"
newUser.password = "qwerty"
PersistenceManager.shared.save()

Saving into multiple entities - Core Data - Swift

Hopefully this will make sense.
I am trying to store data into 2 different entities from one function but not having much luck with storing data into the second entity.
My 2 entities are called - Job & ShootKitChecklist.
I have created a core data manager, I have stripped this back to just show you the section I am using:
struct CoreDataManager {
static let shared = CoreDataManager()
let persistentContainer: NSPersistentContainer = {
// initialization of core data stack
let container = NSPersistentContainer(name: "TBAShootCoreData")
container.loadPersistentStores { (storeDescription, error) in
if let error = error {
fatalError("loading of store failed: \(error)")
}
}
return container
}()
func createSKCItem(item: String, used: Bool, visible: Bool, job: Job) -> (ShootKitChecklist?, Error?) {
let context = persistentContainer.viewContext
// create Shoot kit item
let SKC = NSEntityDescription.insertNewObject(forEntityName: "ShootKitChecklist", into: context) as! ShootKitChecklist
SKC.job = job
SKC.setValue(item, forKey: "item")
SKC.setValue(used, forKey: "used")
SKC.setValue(visible, forKey: "visible")
do {
try context.save()
return (SKC, nil)
} catch let error {
print ("Failed to add Shoot Kit Item:", error)
return (nil, error)
}
}
}
When I try to save the data, the Job entity (First Entity)writes to the context and I can fetch it in another class.
The data I am trying to save to the ShootKitChecklist is from an array so I put my setValues into a for look. However, it seems to ignore saving any data to the entity.
var SKCequipment = ["A","B","C","D","E"]
#IBAction private func HandleSave(sender : UIButton) {
let context = CoreDataManager.shared.persistentContainer.viewContext
let job = NSEntityDescription.insertNewObject(forEntityName: "Job", into: context)
let SKC = NSEntityDescription.insertNewObject(forEntityName: "ShootKitChecklist", into: context)
job.setValue(jobBrandTextField.text, forKey: "jobBrand")
job.setValue(jobNameTextField.text, forKey: "jobName")
job.setValue(directorTextField.text, forKey: "directorName")
job.setValue(agencyTextField.text, forKey: "agencyName")
job.setValue(prodCoTextField.text, forKey: "prodCoName")
for item in SKCequipment {
print(item)
SKC.setValue(item, forKey: "item")
SKC.setValue(true, forKey: "used")
SKC.setValue(true, forKey: "visible")
}
do {
try context.save()
dismiss(animated: true) {
self.delegate?.didAddJob(job: job as! Job)
}
} catch let saveError {
print("Failed to save company:", saveError)
}
}
To test to see if the items have been added to the core data I am fetching the items like this:
guard let SKCitem = job?.skc?.allObjects as? [ShootKitChecklist] else { return}
self.skcitems = SKCitem
print(skcitems)
Thank you in advance, huge help!
Okay I have fixed it by adding another function to my protocol and appending the Entity in the delegate(I realise that I didn't share this before (apologies). Here is my new protocol:
protocol NewJobControllerDelegate {
func didAddJob(job : Job)
func didAddSKC(SKC : ShootKitChecklist)
}
And then in my HandleSave action I changed my for loop to this:
for item in SKCequipment {
let tuple = CoreDataManager.shared.createSKCItem(item: item, used: true, visible: true, job: job as! Job)
if let error = tuple.1 {
print("Cannot save items", error)
} else {
self.delegate?.didAddSKC(SKC: tuple.0!)
}
And finally my new function from my delegate:
func didAddSKC(SKC: ShootKitChecklist) {
ShootKit.append(SKC)
}
Thank you for your help!

Unable to save values to Core Data

I am trying to store data to Core-Data in AppDelegate itself and then fetch that data from ViewController. For some reason, it is not getting saved in Core-Data. I have tried searching for this issue on the internet but did not get any specific solution. I have pasted the code below -
AppDelegate.swift
func saveContext () {
let context = persistentContainer.viewContext
print(context)
let entity = NSEntityDescription.entity(forEntityName: "Msg", in: context)
print(entity)
let new = NSManagedObject(entity: entity!, insertInto: context)
print(new)
print(getData.alert_message)
new.setValue(getData.alert_message, forKey: "title")
do {
try context.save()
print("save")
print(new.value(forKey: "title"))
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
Console Output
You can fetch record from the entity by NSFetchRequest
Try with below method, You just need to pass name of the entity as argument of the function.
func getAllRecordFromTableWhere(_ tableName: String) -> [NSManagedObject]? {
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: tableName)
do {
return try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
return nil
}
and call function like
if let arrayOfData = DBHelper.getAllRecordFromTableWhere("Msg") {
print(arrayOfData)
}
Hear I have Set My Own Solution, Hope This help You
let contex = ((UIApplication.shared.delegate) as! AppDelegate).persistentContainer.viewContext
func SaveData()
{
let entity = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: contex);
entity.setValue(txtname.text, forKey: "empname") // txtname.text is My TexField name
entity.setValue(txtadd.text, forKey: "empadd");
do
{
try contex.save();
}
catch
{
}
}
I think you are not giving values to all attributes of the entity so check that first.
try something like
new.setValue(msgdata, forKey: "msgdata")
//msgdata is what you want to save on Coredata entity
//try something like this
In my case i was trying to update data saved in core data. but every time it was returning the old data ( not the updated version )
Saved successfully message was being printed in console same as yours
Here are some simple steps that finally solved my problem
fetch data with a NSFetchRequest
save data into a temp variable
delete old data from core data
modify data from temp variable
and finally save context
Here is my update data function
func updateUserData(_ userDetails: UserModel) {
let request = UserDetails.fetchRequest() as NSFetchRequest<UserDetails>
do {
let result = try persistentContainer.viewContext.fetch(request)
if let data = result.first?.userData as Data? {
var loginModel = LoginModel(data: data)
loginModel?.user = userDetails
self.clearUserData() //deleting old data
self.userLoginData = loginModel?.jsonData
}
}catch let error as NSError {
debugPrint(error.localizedDescription)
}
}

Core Data fetch returns zero records though table is not empty

I'm a Swift newbie, building a Core Data app. I've built and run a sample app from Ray Wenderlich's site which works as expected.
I've lifted and modified the following excerpt from Ray's app:
var people: [NSManagedObject] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//1
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
// 2
let fetchrequest = NSFetchRequest<NSManagedObject>(entityName: "Person")
// 3
do {
people = try managedContext.fetch(fetchrequest)
print("\(people.count) fetched from Person")
}
catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
This works as expected. However, the following is what I've implemented in my app:
var players: [NSManagedObject] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Golfer")
do {
players = try managedContext.fetch(fetchRequest)
print("\(players.count) fetched from Golfer")
// Load any saved players, otherwise load sample data.
if players.count == 0 {
// Load the sample data.
// There are no players to load
os_log("Loading sample players", log: OSLog.default, type: .debug)
loadSamplePlayers()
}
}
catch let error as NSError {
print("Could not fetch Golfers. \(error), \(error.userInfo)")
}
}
The sample code always returns the full results of the Person table and the person array count is always equal to the number of rows in the table.
However, for my version, it always reports that the players array has a count of zero. Consequently, the loadSamplePlayers() method is called each time (which adds three sample records into the Golfer table).
Using an SQL Lite database inspector, I can see that the Golfer table continues to grow after each invocation of the app.
I'm stumped on why these two, near-identical, code samples should behave differently.
Any insights would be much appreciated.
Thanks!
EDIT:
Here's the loadSamplePlayers() method and printDatabaseStats() which is also referenced:
private func loadSamplePlayers() {
let sampleFirstNames: [String] = ["Casper", "Jocelyn", "Arthur"]
let sampleLastNames: [String] = ["Vitturio", "Brown", "Mullard"]
let sampleEmails: [String] = ["a#b.com", "fred#x.co.uk", "last#ohm.com"]
let sampleHandicaps: [Double] = [16.2, 6.4, 27.2]
let entity = NSEntityDescription.entity(forEntityName: "Golfer", in: managedObjectContext!)!
for i in 1...3 {
let player = NSManagedObject(entity: entity, insertInto: managedObjectContext)
player.setValue(sampleFirstNames[i-1], forKeyPath: "firstName")
player.setValue(sampleLastNames[i-1], forKey: "lastName")
player.setValue(sampleEmails[i-1], forKey: "emailAddress")
player.setValue(sampleHandicaps[i-1], forKey: "exactHandicap")
// player.setValue(sampleMugshots[i-1], forKey: "mugShot")
print("Prepare to save")
do {
try managedObjectContext?.save()
players.append(player)
}
catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
print("There are now \(printDatabaseStats()) in the Golfers table")
}
}
private func printDatabaseStats() -> Int {
var count = 0
managedObjectContext?.performAndWait {
if let golferCount = try? self.managedObjectContext!.count(for: NSFetchRequest(entityName: "Golfer")) {
print("\(golferCount) Payers")
count = golferCount
}
}
return count
}
This appears to work successfully as the print(...) methods produce the expected console messages and the Golfer table is populated and contains the rows as defined.
Not included in the original question was a class definition, thus:
var managedObjectContext: NSManagedObjectContext? = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext
This is defined differently to:
let managedContext = appDelegate.persistentContainer.viewContext
yet I was using them as if they were the same. I normalised the two so they are identical and the problem has gone.

(iOS Swift) Fetching record from Core Data return fatal error or nil

I'm starting to code with Swift for iPhone apps, i'm facing this rather confusing obstacle that for some of you might be trivial. I keep getting error message that the record is either fatal error: unexpectedly found nil while unwrapping an Optional value or nil, but when i check the .sqlite the record is there
Let me walk you through
The name of my .xcdatamodeld is ReviewerApp.xcdatamodeld, the same as my app name ReviewApp
ReviewerApp.xcdatamodeld
My class name is Users and my Entity name is User
Class: Users, Entity: User
My Attributes (username, email, password) are all type: String, with properties: optional
Users.swift
import Foundation
import CoreData
#objc(Users)
class Users: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
#NSManaged var username: String?
#NSManaged var email: String?
#NSManaged var password: String?
}
The saveUser() function in signUpController.swift
func saveUser() {
// create an instance of our managedObjectContext
let moc = DataController().managedObjectContext
// we set up our entity by selecting the entity and context that we're targeting
let entity = NSEntityDescription.insertNewObjectForEntityForName("User", inManagedObjectContext: moc) as! Users
// add our data
entity.setValue(usernameTxtFld.text, forKey: "username")
entity.setValue(emailTxtFld.text, forKey: "email")
entity.setValue(passwordTxtFld.text, forKey: "password")
// we save our entity
do {
try moc.save()
//user.append(entity)
print("saved")
} catch {
fatalError("Failure to save context: \(error)")
}
}
The fetch() function in SignInController.swift
let moc = DataController().managedObjectContext
let userFetch = NSFetchRequest(entityName: "User")
do {
let fetchedUser = try moc.executeFetchRequest(userFetch) as! [Users]
print(fetchedUser.first!.username!)
} catch {
fatalError("Failed to fetch person: \(error)")
}
Everytime i save the user registration process, the record is saved in core data. But everytime i am trying to fetch it:
by: print(fetchedUser.first!.username!) , the message in the console is fatal error: unexpectedly found nil while unwrapping an Optional value
by: print(fetchedUser.first?.username) , the message in the console is nil
Thank you very much for the help, in advance
First I would highly suggest you not to using '!' anywhere in your code as it will crash your app (only for static resources). You can use 'if let XXX = YYY as? [...]' to safely cast whatever you want...
Then you are probably not saving anything in your Database. How is your model? Yours Users class must be adequate to the model you built otherwise it won't work (which is a pain), also in your model you have to give your entity its class (in the 'class' field just below 'parent entity').
Also you don't have to use 'entity.setValue(usernameTxtFld.text, forKey: "username")' as you casted your entity beforehand. You could just 'entity.username =usernameTxtFld.text'.
If I didn't help, try to also add the xcdatamodel please.
I think you missed out on
let entityDescription = NSEntityDescription.entityForName("User", inManagedObjectContext: moc)
fetchRequest.entity = entityDescription
do {
let fetchedUser = try moc.executeFetchRequest(fetchRequest)
print(fetchedUser.first!.username!)
} catch {
let fetchError = error as NSError
print(fetchError)
}
The method returns an array of results if the fetch request is successful. Note that Core Data always returns an array if the fetch request is successful, even if we expect one result or if Core Data didn't find any matching records.
For more information and clarification visit - http://code.tutsplus.com/tutorials/core-data-and-swift-managed-objects-and-fetch-requests--cms-25068
The case is closed. There is some problem with the DataController.swift. It was called to save the data, but when it is called to fetch the data it somehow pointing to different place. So, what i did was
Not use the DataController.swift anymore
Equipped my AppDelegate.swift with // MARK: - Core Data Saving support for saving context, because i didn't set my app with including core data in the beginning
func saveContext () {
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
// 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.
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
}
I changed my saving function to
func saveUser() {
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let entity = NSEntityDescription.insertNewObjectForEntityForName("Users", inManagedObjectContext: managedContext) as! Users
//3
entity.setValue(usernameTxtFld.text, forKey: "username")
entity.setValue(emailTxtFld.text, forKey: "email")
entity.setValue(passwordTxtFld.text, forKey: "password")
//4
do {
try managedContext.save()
//5
message = "Signing up is successful"
alertMessage(message)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
And changed my fetch function to
func fetch() {
let appDelegate =
UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
//2
let fetchRequest = NSFetchRequest(entityName: "Users")
let predicate = NSPredicate(format: "email == %# AND password == %#", emailTxtFld.text!, passwordTxtFld.text!)
fetchRequest.predicate = predicate
//3
do {
let results =
try managedContext.executeFetchRequest(fetchRequest)
user = results as! [Users]
let row = user.count
if row > 0 {
message = "You're signed in"
//self.performSegueWithIdentifier("signInIdentifier", sender: self)
}else{
message = "Email & password combination is incorrect!"
}
alertMessage(message)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}

Resources