I am trying to implement method chaining for success and failure calls in my code but I seem to be having trouble getting the onSuccess methods to actually be called.
A view controller calls the getProduct(_:) function.
getProduct(_:) makes an API call and then calls storeProduct(_:) with the retrieved json
storeProduct(_:) calls fetchProduct(_:)
fetchProduct(_:) calls doSuccess(_:) but this never gets back into the onSuccess of the previous calls.
Some Code Snippets
BSProductChainable.swift
import Foundation
class BSProductChainable<SuccessParams, FailureParams> {
var successClosure: ((SuccessParams) -> ())? = nil
var failureClosure: ((FailureParams) -> ())? = nil
func onSuccess(closure: (SuccessParams) -> ()) -> BSProductChainable {
successClosure = closure
return self
}
func onFailure(closure: (FailureParams) -> ()) -> BSProductChainable {
failureClosure = closure
return self
}
func doSuccess(params: SuccessParams) {
if let closure = successClosure {
closure(params)
}
}
func doFailure(params: FailureParams) {
if let closure = failureClosure {
closure(params)
}
}
}
BSProductManagerSwift.swift
class BSProductManagerSwift: NSObject {
typealias productResponseChain = BSProductChainable<Product, NSError?>
typealias productsResponseChain = BSProductChainable<[Product], NSError?>
var serviceClient: BSNetworkingServiceClient!
var objectContext: NSManagedObjectContext!
var productChains: BSProductChainable<Product, NSError?>!
var productsChains: BSProductChainable<[Product], NSError?>!
convenience init(serviceClient: BSNetworkingServiceClient) {
self.init()
self.serviceClient = serviceClient
self.objectContext = managedObjectContext
self.productChains = BSProductChainable<Product, NSError?>()
self.productsChains = BSProductChainable<[Product], NSError?>()
}
func getProduct(ean: String) -> productResponseChain {
let urlString = BSConstants.BarcodeScanner.productEndpoint.stringByAppendingString(ean)
serviceClient.GET(urlString, failure: { (error) in
print("Could not get product")
}) { (response) in
if let json = response {
self.storeProduct(json).onSuccess({ (returedProduct) in
print("Stored product")
})
}
}
return productChains
}
func storeProduct(json: JSON) -> productResponseChain {
fetchProduct(json["ean"].stringValue).onSuccess { (returedProduct) in
self.productChains.doSuccess(returedProduct)
}
return productChains
}
func fetchProduct(ean: String) -> productResponseChain {
let fetchRequest = NSFetchRequest(entityName: "Product")
let predicateEAN = NSPredicate(format: "%K == %#", "ean", ean)
let predicateMarket = NSPredicate(format: "%K == %#", "market", BSCountryManager.sharedInstance().getCurrentCountry().market)
let predicateLocale = NSPredicate(format: "%K == %#", "locale", BSLocalizationManager.sharedManager().currentLocalization.localeIdentifier())
let predicateCurrency = NSPredicate(format: "%K == %#", "currency", BSLocalizationManager.sharedManager().currentLocalization.country.currencyIdentifierDMW)
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateEAN, predicateMarket, predicateLocale, predicateCurrency])
fetchRequest.predicate = compoundPredicate
do {
let matchingProuducts = try objectContext.executeFetchRequest(fetchRequest)
if matchingProuducts.count == 0 {
print("No matching products found")
let entity = NSEntityDescription.entityForName("Product", inManagedObjectContext: objectContext)
productChains.doSuccess(Product(entity: entity!, insertIntoManagedObjectContext: objectContext))
} else {
print("Found matching product")
let d = matchingProuducts.first as! Product
productChains.doSuccess(d)
}
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
productChains.doFailure(error)
}
return productChains
}
I initially initialised the chainable class per function but this had its own issues from which I thought (possibly incorrectly) that I should only initialise the chainable class once and pass around its reference.
Some input as to where I am going wrong/what I could try next would be great.
As recommended by #john elements, I decided to use PromiseKit
This didn't require to much of a code change and here are what the functions now look like (still need to do a bit of a code cleanup but it works!):
func getProduct(ean: String) -> Promise<Product> {
return Promise { fullfill, reject in
let urlString = BSConstants.BarcodeScanner.productEndpoint.stringByAppendingString(ean)
serviceClient.GET(urlString, failure: { (error) in
reject(error!)
}) { (response) in
if let json = response {
self.storeProduct(json).then ({ returnedProduct in
print("We stored the product: \(returnedProduct.ean)")
fullfill(returnedProduct)
}).error { returnedError in
print("We had a problem storing the product: \(returnedError)")
}
}
}
}
}
func storeProduct(json: JSON) -> Promise<Product> {
return Promise { fullfill, reject in
fetchProduct(json["ean"].stringValue).then ({ returnedProduct in
var storedProduct: Product!
var isNewProduct = false
print("Fetched Product: \(returnedProduct.ean)")
isNewProduct = returnedProduct.valueForKey("ean") == nil
storedProduct = returnedProduct
storedProduct.setValue(json["name"].stringValue, forKey: "name")
storedProduct.setValue(json["ean"].stringValue, forKey: "ean")
storedProduct.setValue(json["image"].stringValue, forKey: "image")
storedProduct.setValue(json["price"].doubleValue, forKey: "price")
storedProduct.setValue(json["status"].intValue, forKey: "status")
storedProduct.setValue(json["pdp"].stringValue, forKey: "pdp")
storedProduct.setValue(BSCountryManager.sharedInstance().getCurrentCountry().market, forKey: "market")
storedProduct.setValue(BSLocalizationManager.sharedManager().currentLocalization.localeIdentifier(), forKey: "locale")
storedProduct.setValue(BSLocalizationManager.sharedManager().currentLocalization.country.currencyIdentifierDMW, forKey: "currency")
do {
try self.objectContext.save()
print("Stored Product: \(returnedProduct.ean)")
fullfill(returnedProduct)
if isNewProduct {
NSNotificationCenter.defaultCenter().postNotificationName("DidAddScanEntry", object: nil)
}
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
reject(error)
}
}).error { returnedError in
print("We had a problem fetching the product: \(returnedError)")
reject(returnedError)
}
}
}
func fetchProduct(ean: String) -> Promise<Product> {
return Promise { fullfill, reject in
let fetchRequest = NSFetchRequest(entityName: "Product")
let predicateEAN = NSPredicate(format: "%K == %#", "ean", ean)
let predicateMarket = NSPredicate(format: "%K == %#", "market", BSCountryManager.sharedInstance().getCurrentCountry().market)
let predicateLocale = NSPredicate(format: "%K == %#", "locale", BSLocalizationManager.sharedManager().currentLocalization.localeIdentifier())
let predicateCurrency = NSPredicate(format: "%K == %#", "currency", BSLocalizationManager.sharedManager().currentLocalization.country.currencyIdentifierDMW)
let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicateEAN, predicateMarket, predicateLocale, predicateCurrency])
fetchRequest.predicate = compoundPredicate
do {
let matchingProuducts = try objectContext.executeFetchRequest(fetchRequest)
if matchingProuducts.count == 0 {
print("No matching products found")
let entity = NSEntityDescription.entityForName("Product", inManagedObjectContext: objectContext)
fullfill(Product(entity: entity!, insertIntoManagedObjectContext: objectContext))
} else {
print("Found matching product")
let d = matchingProuducts.first as! Product
fullfill(d)
}
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
reject(error)
}
}
}
Related
I'm trying to update an already saved entry in Core data, objectContext isn't nil neither is the managedObject. The new values get set to the managedObject with said Id. No errors are thrown when calling managedContext.save() but no changes are reflected in the coreData
I have tried using setValue() no avail and I have searched far and wide on google and stack overflow for a similar problem and most of the time it says to say that the managedObject is nil.
var taskName:String!
var resultsController: NSFetchedResultsController<Tasks>!
// MARK: - Properties
// Manage objects and update tasks
//var resultsController: NSFetchedResultsController<Tasks>!
var managedContext: NSManagedObjectContext!
var tasksArray = [NSManagedObject]()
var fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Tasks")
func settextfields() {
let res = resultsController.fetchedObjects!
print(res)
for r in res {
if r.name == taskName {
txt_name.text = "\(r.name ?? "Task name" )"
txt_date.text = "\(r.date ?? "Task date")"
segmentedBtn.selectedSegmentIndex = Int(r.priority)
}
}
}
func loadTable() {
let request: NSFetchRequest<Tasks> = Tasks.fetchRequest()
// Sort by date
let sortDescriptor = NSSortDescriptor(key: "date", ascending: true)
request.sortDescriptors = [sortDescriptor]
resultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: coreData.managedContext, sectionNameKeyPath: nil, cacheName: nil)
// Fetch data
do {
try resultsController.performFetch()
print("Fetch successful")
} catch {
print("Error performing fetch: \(error)")
}
}
#IBAction func saveEdit(_ sender: Any) {
guard let name = txt_name.text, !name.isEmpty else {
return
}
guard let date = txt_date.text, !date.isEmpty else {
return
}
do {
loadTable()
let res = resultsController.fetchedObjects!
for r in res {
i += 1
if r.name == taskName {
print(r)
guard let name = txt_name.text, !name.isEmpty else {
return
}
guard let date = txt_date.text, !date.isEmpty else {
return
}
do {
r.name = name
r.date = date
r.priority = Int16(segmentedBtn.selectedSegmentIndex)
}
do {
try managedContext.save()
print(managedContext, r)
dismiss(animated: true)
print("Edit Successful!")
} catch {
print("Error saving task: \(error)")
}
}
}
}
I actually rewrote the save function using predicate like the person above suggested and it worked. Then I added a viewWillLoad to the mainViewController to reload the tableView once the entry is updated
#IBAction func saveEdit(_ sender: Any) {
guard let name = txt_name.text, !name.isEmpty else {
return
}
guard let date = txt_date.text, !date.isEmpty else {
return
}
do {
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "Tasks")
fetchRequest.predicate = NSPredicate(format: "name = %#", taskName)
let test = try managedContext.fetch(fetchRequest)
let obj = test[0] as! NSManagedObject
obj.setValue(name, forKey: "name")
obj.setValue(date, forKey: "date")
obj.setValue(Int16(segmentedBtn.selectedSegmentIndex), forKey: "priority")
do {
try managedContext.save()
dismiss(animated: true)
print("Edit Successful!")
} catch {
print("Error saving task: \(error)")
}
} catch {
print(error)
}
}
I'm trying to edit a value in a previously saved object in CoreData.
The object appears to have been updated, until I relaunch the app, and the value is now set to 'nil'.
Here is my method for saving the changes:
class SaveNewQuickShareTrip: NSManagedObject {
static func addNewTrip(_ username: String, newTrip: TripModel, tripType : String, in context: NSManagedObjectContext) {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: Constants.User)
request.predicate = NSPredicate(format: "username=%#", username)
request.returnsObjectsAsFaults = false
var currentTrips : [TripModel] = Array<TripModel>()
do {
let matches = try context.fetch(request)
if matches.count == 1 {
for userData in matches as! [NSManagedObject] {
currentTrips = userData.value(forKey: tripType) as! Array<TripModel>
print("currentTrips OLD count = ", currentTrips.count)
currentTrips.append(newTrip)
userData.setValue(currentTrips, forKey: Constants.quickShareTrips)
print("currentTrips NEW count = ", currentTrips.count)
}
do {
try context.save()
} catch {
print("Saving the new trip failed!")
}
}
} catch {
print("Something went wrong when saving the quick share trip.")
}
}
}
And code I'm using to retrieve the object upon launch:
class UserRetrieval: NSManagedObject {
static func fetchUser(_ username: String, in context: NSManagedObjectContext) -> [NSManagedObject] {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: Constants.User)
request.predicate = NSPredicate(format: "username=%#", username)
request.returnsObjectsAsFaults = false
var theUser = [NSManagedObject]()
do {
let matches = try context.fetch(request)
if let records = matches as? [NSManagedObject] {
theUser = records
}
} catch {
print("Can't find User.")
}
return theUser
}
}
I am storing and creating posts with this function in my view controller:
#objc func createPost(){
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let post = Post(context: managedContext)
var mediaURI: URL?
let timeInSeconds = Int64((postDate?.timeIntervalSince1970)!)
if isVideo == true {
let filename = String(timeInSeconds) + ".MOV"
FileService.uploadVideo(videoURL: pickedVideoURL, name: filename)
post.mediaFilename = filename
} else {
let filename = String(timeInSeconds) + ".JPG"
FileService.uploadImage(image: postImage, name: filename)
post.mediaFilename = filename
}
var postTags:[Tag] = []
if let tokens = tagsView.tokens() {
for token in tokens {
let tagFetchRequest: NSFetchRequest<Tag> = Tag.fetchRequest()
tagFetchRequest.predicate = NSPredicate(format: "name == %#", token.title)
do {
let res = try managedContext.fetch(tagFetchRequest)
var tag: Tag!
if res.count > 0 {
tag = res.first
} else {
tag = Tag(context: managedContext)
tag.name = token.title
tag.mostRecentUpdate = NSDate()
tag.mostRecentThumbnail = postImage?.jpegData(compressionQuality: 1.0) as NSData?
}
postTags.append(tag)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return
}
}
}
for tag in postTags {
post.addToTags(tag)
}
post.isVideo = isVideo!
post.thumbnail = pickedPostThumbnail?.jpegData(compressionQuality: 1.0) as NSData?
post.notes = notesView.text
post.timeStamp = postDate! as NSDate
do {
try managedContext.save()
dismiss(animated: true, completion: nil)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
I am doing a lot of stuff there, but notably, I am setting the post.thumbnail with a UIImage as NSData? and at the end I am saving the context.
So I create posts and close the app, then open it again and another view controller does this:
fileprivate lazy var posts: NSFetchedResultsController<Post> = {
let appDelegate =
UIApplication.shared.delegate as? AppDelegate
let managedContext =
appDelegate?.persistentContainer.viewContext
let request: NSFetchRequest<Post> = NSFetchRequest(entityName: "Post")
request.predicate = NSPredicate(format: "%# IN self.tags", tag)
let timeSort = NSSortDescriptor(key: "timeStamp", ascending: true)
request.sortDescriptors = [timeSort]
let posts = NSFetchedResultsController(fetchRequest: request, managedObjectContext: managedContext!, sectionNameKeyPath: nil, cacheName: nil)
posts.delegate = self
return posts
}()
override func viewDidLoad(){
....
do {
try posts.performFetch()
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
...
}
let post = posts.object(at: indexPath)
cell.mediaFileName = post.mediaFilename
if let data = post.thumbnail {
print(data,"data?")
cell.thumbnail.image = UIImage.init(data: data as Data)
} else {
print("couldn't find")
}
This works fine the first few restarts. However soon, it starts printing ("couldn't find") and not loading the image. The other fields associated with post are still loading. This is being run on the iPhone 8 simulator that comes with Xcode.
What am I doing wrong here? Is there something about how a simulator stores images in core data that doesn't persist? Or am I misusing the managed context?
I want to write class for manage all entity that i have in my application.
there is my code fore managerClass for one custom entity, but I have a problem to set manageObject type in this context.
public func clearEntityContex() {
let fetchRequest: NSFetchRequest<Shop> = Shop.fetchRequest()
if let fetchResult = try? self.stack.mainQueueContext.fetch(fetchRequest){
for user : Shop in fetchResult {
self.stack.mainQueueContext.delete(user as Shop)
}
do {
try stack.mainQueueContext.save()
}
catch {
debugPrint(error.localizedDescription)
}
}
}
//MARK: _fetch Contex
public func fetchsShopEntity() -> [Shop]? {
var shops : [Shop]?
let fetchRequest: NSFetchRequest<Shop> = Shop.fetchRequest()
do {
let fetchResult =
try self.stack.mainQueueContext.fetch(fetchRequest)
if fetchResult.count > 0 {
shops = fetchResult
}
}
catch {
fatalError("Failed to fetch Account: \(error)")
}
return shops
}
//MARK: _save entity
public func saveEntityInModel(entityItem : Shop){
if let entity = NSEntityDescription.entity(forEntityName: "Shop", in: self.stack.mainQueueContext) {
if let contex = NSManagedObject(entity: entity, insertInto: self.stack.mainQueueContext) as? Shop {
contex.packID = entityItem.packID
contex.packName = entityItem.packName
contex.packImage = entityItem.packImage
contex.priceDolar = entityItem.priceDolar
contex.packDescription = entityItem.packDescription
do {
try stack.mainQueueContext.save()
}
catch {
debugPrint(error.localizedDescription)
}
}
}
}
for example i want to write method that can clear any entityContext. but i cant pass manageObject to this method.
public func clearEntityContex(entityObject: NSManagedObject) {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = entityObject.fetchRequest()
if let fetchResult = try? self.stack.mainQueueContext.fetch(fetchRequest){
for entity in fetchResult {
self.stack.mainQueueContext.delete(entity as entityObject)
}
do {
try stack.mainQueueContext.save()
}
catch {
debugPrint(error.localizedDescription)
}
}
}
how can solve pass NSManagedObject to this method?
thanks for all reply
Here's a more generic implementation that we use in our projects.
import CoreData
class ACSwiftCoreData: ACCoreDataPlugin {
let managedObjectModelName: String
let databasePath: URL
init(managedObjectModelName: String, databasePath: URL) {
self.managedObjectModelName = managedObjectModelName
self.databasePath = databasePath
}
// MARK: Managed Object Contexts
private var sharedContext: NSManagedObjectContext?
func getSharedManagedObjectContext() throws -> NSManagedObjectContext {
if let sharedContext = self.sharedContext {
return sharedContext
}
let context = try self.createManagedObjectContext()
self.sharedContext = context
return context
}
func createManagedObjectContext() throws -> NSManagedObjectContext {
let storeCoordinator = try self.getPersistentStoreCoordinator()
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = storeCoordinator
managedObjectContext.mergePolicy = NSMergePolicy(merge: NSMergePolicyType.mergeByPropertyObjectTrumpMergePolicyType)
return managedObjectContext
}
// MARK: Creating Entities
func createEntityInSharedContext<EntityType>(_ entityName: String) throws -> EntityType {
let context = try self.getSharedManagedObjectContext()
return try self.createEntity(entityName, context: context)
}
func createEntity<EntityType>(_ entityName: String, context: NSManagedObjectContext) throws -> EntityType {
let entity = NSEntityDescription.insertNewObject(forEntityName: entityName, into: context)
guard let expectedEntity = entity as? EntityType else {
throw self.errorWithMessage("ACSwiftCoreData: Entity for name \(entityName) does not match class \(EntityType.self).")
}
return expectedEntity
}
// MARK: Saving Entity
func saveEntity(_ entity: NSManagedObject) throws {
guard let context = entity.managedObjectContext else {
throw errorWithMessage("ACSwiftCoreData: Cannot save Entity. ManagedObjectContext is missing.")
}
if context.hasChanges {
try context.save()
}
}
// MARK: Delete Entity
func deleteEntity(_ entity: NSManagedObject) throws {
guard let context = entity.managedObjectContext else {
throw errorWithMessage("ACSwiftCoreData: Cannot delete Entity. ManagedObjectContext is missing.")
}
context.delete(entity)
try context.save()
}
// MARK: Fetch Requests
func fetchEntitiesInSharedContext<EntityType: AnyObject>(_ entityName: String, predicate: NSPredicate?) -> [EntityType] {
guard let context = try? self.getSharedManagedObjectContext() else {
return [EntityType]()
}
return self .fetchEntities(entityName, context: context, predicate: predicate)
}
func fetchEntities<EntityType: AnyObject>(_ entityName: String, context: NSManagedObjectContext, predicate: NSPredicate?) -> [EntityType] {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
fetchRequest.predicate = predicate
let results = try? context.fetch(fetchRequest)
guard let resultEntitys = results as? [EntityType] else {
return [EntityType]()
}
return resultEntitys
}
// MARK: Technical Details
private var storeCoordinator: NSPersistentStoreCoordinator?
private func getPersistentStoreCoordinator() throws -> NSPersistentStoreCoordinator {
if let storeCoordinator = self.storeCoordinator {
return storeCoordinator
}
let model = try self.getManagedObjectModel()
let storeCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
var options = [AnyHashable: Any]()
options[NSMigratePersistentStoresAutomaticallyOption] = true
options[NSInferMappingModelAutomaticallyOption] = true
try storeCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: self.databasePath, options: options)
self.storeCoordinator = storeCoordinator
return storeCoordinator
}
private var objectModel: NSManagedObjectModel?
private func getManagedObjectModel() throws -> NSManagedObjectModel {
if let objectModel = self.objectModel {
return objectModel
}
let momName = self.managedObjectModelName
guard let modelUrl = Bundle.main.url(forResource: momName, withExtension:"momd") else {
throw self.errorWithMessage("ACSwiftCoreData: DataModel Url could not be created.")
}
guard let objectModel = NSManagedObjectModel(contentsOf: modelUrl) else {
throw self.errorWithMessage("ACSwiftCoreData: DataModel could not be loaded.")
}
self.objectModel = objectModel
return objectModel
}
// MARK: Error handling
private func errorWithMessage(_ message: String) -> NSError {
let userInfo = [NSLocalizedDescriptionKey: message]
let error = NSError(domain: "com.appcron.accomponents", code: 0, userInfo: userInfo)
return error
}
}
In some project that I made and when I used CoreData, I usually create a Singleton with function to fetch, save and delete a CoreData object.
This is my CoreDataController:
import Foundation
import CoreData
import UIKit
final class CoreDataController {
static let sharedInstances = CoreDataController()
private var context: NSManagedObjectContext
private init(){
let application = UIApplication.shared.delegate as! AppDelegate
self.context = application.persistentContainer.viewContext
}
func loadAll() {
print("Fetch from CoreData")
let fetchRequest: NSFetchRequest<YourEntity> = YourEntity.fetchRequest()
do {
let entityArray = try self.context.fetch(fetchRequest)
guard entityArray.count > 0 else {
print("There aren't element in CoreData "); return}
} catch let error {
print("FetchRequest error")
print(" Print error: \n \(error) \n")
}
}
func save(entityToSave: String, item: String){
let entity = NSEntityDescription.entity(forEntityName: entityToSave, in: self.context)
let newItem = YourEntity(entity: entity!, insertInto: self.context)
newItem.name = item
do {
try self.context.save()
} catch let error {
print("Problem with \(newItem)")
print(" Print error: \n \(error) \n")
}
print("Element \(newItem) saved in CoreData")
}
func loadFromName(entityName:String, name: String) -> Any {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
request.returnsObjectsAsFaults = false
let predicate = NSPredicate(format: "yourEntityAttribute = %#", yourEntityAttribute)
request.predicate = predicate
let items = self.loadFromFetchRequest(request: request)
return items[0]
}
private func loadFromFetchRequest(request: NSFetchRequest<NSFetchRequestResult>) -> [Any] {
var array = [Any]()
do {
array = try self.context.fetch(request)
guard array.count > 0 else {print("There aren't element in CoreData"); return []}
for item in array {
print("Item: \(item)")
}
} catch let error {
print("FetchRequest Error")
print(" Print Error: \n \(error) \n")
}
return array
}
func delete(entityName: String, name: String) {
let item = self.loadFromName(entityName: entityName, name: name)
self.context.delete(item as! NSManagedObject)
do {
try self.context.save()
} catch let error {
print("Deleting problem")
print("Print Error: \n \(error) \n")
}
}
func loadData(entity: String) -> [YourEntity] {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
var data = [YourEntity]()
do {
data = try self.context.fetch(fetchRequest) as! [YourEntity]
} catch let error {
print("Print Error: \n \(error) \n")
}
return data
}
}
When you have to call, just write:
CoreDataController.sharedInstances.save(entityToSave: "Profile", item: textfield.text!)
or other functions!!!
I hope this is useful for you.
For use this Class with every Entity you can write like that:
let entity = NSEntityDescription.entity(forEntityName: entityToSave, in: self.context)
let newItem: Any
switch entityToSave {
case "YourEntity":
newItem = YourEntity(entity: entity!, insertInto: self.context)
(newItem as! YourEntity).entityAttribute = firstItem
(newItem as! YourEntity).entityAttribute = secondItem
case "YourEntity2":
newItem = YourEntity2(entity: entity!, insertInto: self.context)
(newItem as! YourEntity2).entityAttribute = firstItem
(newItem as! YourEntity2).entityAttribute = secondItem
case "YourEntity3":
newItem = YourEntity3(entity: entity!, insertInto: self.context)
(newItem as! YourEntity3).entityAttribute = firstItem
(newItem as! YourEntity3).entityAttribute = secondItem
case "YourEntity4":
newItem = YourEntity4(entity: entity!, insertInto: self.context)
(newItem as! YourEntity4).entityAttribute = firstItem
(newItem as! YourEntity4).entityAttribute = secondItem
default:
fatalError("Error in entityToSave function")
}
do {
try self.context.save()
} catch let error {
print("Problem to save \(newItem)")
print("Print Error: \n \(error) \n")
}
print("Element \(newItem) saved correctly")
}
I am trying to check if the item exits in coredata if not add it to coredata. How am I going to implement the check?
var authorList = [AuthorList]()
let articleEntity = NSEntityDescription.entityForName("AuthorList", inManagedObjectContext: self.context!)
let newAuthor = AuthorList(entity: articleEntity!, insertIntoManagedObjectContext: self.context!)
//if authorID is not in coredata then....
newAuthor.authorName = authorName!
newAuthor.authorImage = authorImage!
newAuthor.newspaperName = newspaperName!
newAuthor.newsPaperImage = newsPaperImage!
newAuthor.authorID = authorID!
In case any body looking for swift 3 solution.:
Swift 3
Xcode 8x
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Friends")
let predicate = NSPredicate(format: "friendName == %#", frd.text)
request.predicate = predicate
request.fetchLimit = 1
do{
let app = UIApplication.shared.delegate as! AppDelegate
let context = app.managedObjectContext
let count = try context.count(for: request)
if(count == 0){
// no matching object
print("no present")
}
else{
// at least one matching object exists
print("one matching item found")
}
}
catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
Used NSPredicate to filter articlID in coredata...
let fetchRequest = NSFetchRequest(entityName: "FavArticles")
let predicate = NSPredicate(format: "articleID == %ld", articleID!)
fetchRequest.predicate = predicate
let fetchResults = self.context!.executeFetchRequest(fetchRequest, error: nil) as? [FavArticles]
if fetchResults!.count > 0 {
println("already favd")
}
func checkIfItemExist(id: String) -> Bool {
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Products")
fetchRequest.fetchLimit = 1
fetchRequest.predicate = NSPredicate(format: "productId == %#", id)
do {
let count = try DatabaseHelper.context!.count(for: fetchRequest)
if count > 0 {
return true
} else {
return false
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
return false
}
}