Predicate is not working with NSSet - ios

I want to filter Places where categoryId == value but my predicate is failing.
Here is my code.
categoryList is an array of Objects of class VenueCategory and categoryId is property of Category class.
class Place: NSManagedObject {
class func GetPlaces(keys:[String],values:[String],forPlaceTab:Bool?,visitType:VisitType) -> [Place] {
//1
let managedContext = CoreDataStack.sharedStack().mainContext
var predicates = [NSPredicate]()
//2
let fetchRequest = NSFetchRequest(entityName:TABLE_PLACE)
for (index, key) in keys.enumerate() {
let value = values[index]
let predicateFormat = key != "categoryId" ? "\(key) == \(value)" : "ANY categoryList.categoryId == \(value)"
let resultPredicate = NSPredicate(format: predicateFormat)
predicates.append(resultPredicate)
}
if let forPlaceTab = forPlaceTab{
let predicateFormat = "isPlaceTab == \(forPlaceTab.boolValue)"
let resultPredicate = NSPredicate(format: predicateFormat)
predicates.append(resultPredicate)
}
fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates)
//3
//var error: NSError?
do {
if let results = try managedContext.executeFetchRequest(fetchRequest) as? [Place]{
return results
}
} catch let error as NSError {
print(error)
}
return []
}
}

I got the problem. issue was categories were not getting added in categoriesList. predicate was Ok.

Related

NSPredicate array for NSCompoundPredicate

Please Help me, i want to make a coredata get function in Swift 2.2 NSPredicate array for NSCompoundPredicate
public func loadData(entityName: String, filters: [String: String] = [:], dataFault: Bool = true) -> [NSManagedObject] {
var listItems: [NSManagedObject]?
let delegate = UIApplication.sharedApplication().delegate as? AppDelegate
if let context = delegate?.managedObjectContext {
let fetchRequist = NSFetchRequest(entityName: entityName)
if (filters.count > 0) {
var predicte: [NSPredicate]
for (key, value) in filters {
let p1:NSPredicate = NSPredicate(format: "%K == %#", key, value as NSObject)
predicte.appendContentsOf(p1)
}
fetchRequist.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicte)
}
fetchRequist.returnsObjectsAsFaults = dataFault
do{
let results = try context.executeFetchRequest(fetchRequist)
listItems = results as? [NSManagedObject]
}
catch let err {
print(err)
}
}
else{
print("context Error")
}
return listItems!
}
There show error on predicte.appendContentsOf(p1)
In your code, p1 is not a CollectionType, so you need to use append, not appendContentsOf:
predicte.append(p1)
Also, you need to initialize your predicte appropriately:
var predicte: [NSPredicate] = []

Update core data object swift 3

I want to update a core data object in swift 3. After some googled I didn't found anything about swift 3.
So my question is: how can I update a core data object in swift 3?
Fetch the existing values using a fetch request with a predicate. Use a unique value in the predicate. Once you've fetched the object, update the object with new values and save the context.
let empId = "001"
let fetchRequest:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest.init(entityName: "EmpDetails")
let predicate = NSPredicate(format: "empId = '\(empId)'")
fetchRequest.predicate = predicate
do {
let result = try persistentContainer.viewContext.fetch(fetchRequest)
if let objectToUpdate = result.first as? NSManagedObject {
objectToUpdate.setValue("newName", forKey: "name")
objectToUpdate.setValue("newDepartment", forKey: "department")
objectToUpdate.setValue("001", forKey: "empID")
try persistentContainer.viewContext.save()
}
} catch {
print(error)
}
Using NSManagedObject subclass
let empId = "001"
let fetchRequest: NSFetchRequest<Employee> = Employee.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "%K = %#", #keyPath(Employee.id), empId)
do {
let results = try persistentContainer.viewContext.fetch(fetchRequest)
if let employee = results.first {
employee.name = "new name"
employee.department = "new department"
}
try persistentContainer.viewContext.save()
} catch let error as NSError {
print(error.localizedDescription)
}
Batch updates
Batch updates help to update multiple Core Data objects without having
to fetch anything into memory.
let batchUpdate = NSBatchUpdateRequest(entityName: "Employee")
batchUpdate.propertiesToUpdate = [#keyPath(Employee.isActive): true]
batchUpdate.affectedStores = persistentContainer.viewContext.persistentStoreCoordinator?.persistentStores
batchUpdate.resultType = .updatedObjectsCountResultType
do {
let batchResult = try coreDataStack.managedContext.execute(batchUpdate) as? NSBatchUpdateResult
print(batchResult?.result)
} catch let error as NSError {
print(error.localizedDescription)
}
Pass unique id in variable "id"(Unique variable created in Core data model) and all the variable as you want to update values:
func context() -> NSManagedObjectContext {
let context=(UIApplication.shared.delegate as!AppDelegate).persistentContainer.viewContext
return context
}
func save() {
(UIApplication.shared.delegate as! AppDelegate).saveContext()
}
func UpdateCartByTestId(id:Int64,name:String) {
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Update")
fetchRequest.returnsObjectsAsFaults = false
fetchRequest.predicate = NSPredicate(format:"id == %d",id)
let result = try? context().fetch(fetchRequest)
if result?.count == 1 {
let dic = result![0]
dic.setValue(id, forKey: "id")
dic.setValue(name, forKey: "name")
save()
}
}

NSBatchUpdateRequest raise an error in Swift

This is my NSBatchUpdateRequest:
let batchUpdateRequest = NSBatchUpdateRequest(entityName: "WLItem")
batchUpdateRequest.predicate = NSPredicate(format: "source != rt")
batchUpdateRequest.propertiesToUpdate = ["position": 2]
batchUpdateRequest.resultType = NSBatchUpdateRequestResultType.UpdatedObjectsCountResultType
do {
let batchUpdateResult = try NSManagedObjectContext.MR_defaultContext().executeRequest(batchUpdateRequest) as! NSBatchUpdateResult
} catch {
print("error: \(error)")
}
output on console is:
error: NilError
What is wrong? Is it a problem with XCode7? I am working with NSBatchUpdateRequest first time, so I do not know whether was it like that before or not. For me that code should just works.
You have to refresh your managedContextObject to update the database. I have created a function in which am using the NSBatchUpdateRequest to update the database. Below is the function:-
let managedContext = SharedInstance.appDelegate?.persistentContainer.viewContext
func updateDataFromTable(tableName:String, idOfPaticularTable ID:String, updatedDict:Dictionary<String, String>, success:#escaping (_ response:Bool)-> Void, failure:#escaping (_ error: Error?) -> Void) {
let batchRequest = NSBatchUpdateRequest(entityName: tableName)
let predicate = NSPredicate(format: "id == %#", ID)
batchRequest.predicate = predicate
batchRequest.propertiesToUpdate = updatedDict
batchRequest.resultType = .updatedObjectIDsResultType
do {
// Execute Batch Request
let batchUpdateResult = try managedContext?.execute(batchRequest) as! NSBatchUpdateResult
// Extract Object IDs
let objectIDs = batchUpdateResult.result as! [NSManagedObjectID]
for objectID in objectIDs {
// Turn Managed Objects into Faults
let managedObject = managedContext?.object(with: objectID)
managedContext?.refresh(managedObject!, mergeChanges: false)
}
success(true)
} catch let error as NSError {
print(error)
failure(error)
}
}
struct SharedInstance {
static let appDelegate = UIApplication.shared.delegate as? AppDelegate
static let employeetable = "EmployeeModel"
}
Same problem that I faced in my project. Below solution working for me. Try this
let batchRequest = NSBatchUpdateRequest(entityName: "Card")
let predicate = NSPredicate(format: "set == %#", set)
batchRequest.predicate = predicate
batchRequest.propertiesToUpdate = [ "count" : 54 ]
batchRequest.resultType = .UpdatedObjectsCountResultType
do {
try self.managedObjectContext.executeRequest(batchRequest) as! NSBatchUpdateResult
} catch _ {
}

Syncing parse data with coredata, how do I figure out which objects to delete?

I have successfully written the code to download the parse objects, fetch the current objects in my database and then compare.
My algorithm:
I iterate through the parse objects and run a fetchrequest and compare their objectID's. If I get nothing, I make a new object for my database. Otherwise I then look at the modifiedDate I have in my database and the updatedAt from parse and compare to see if I need to set new values. This code works great.
The code:
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
let object = object as! PFObject
let name = object["name"] as! String
let email = object["email"] as! String
let subjectsTaught = object["subjectsTaught"] as [String: String]
let category = object["category"] as! String
let uniqueID = object.objectId!
let modifiedDate = object.updatedAt!
let fetchRequest2 = NSFetchRequest(entityName: "Teacher")
fetchRequest2.predicate = NSPredicate(format: "uniqueID == %#", uniqueID)
var error2: NSError?
if let foundTeachers = self.managedObjectContext.executeFetchRequest(fetchRequest2, error: &error2) as? [Teacher] {
if foundTeachers.isEmpty == true {
let teacher = NSEntityDescription.insertNewObjectForEntityForName("Teacher", inManagedObjectContext: self.managedObjectContext) as! Teacher
teacher.name = name
teacher.email = email
teacher.subjectsTaught = subjectsTaught
teacher.category = category
teacher.uniqueID = uniqueID
teacher.modifiedDate = modifiedDate
} else {
if let teacher = foundTeachers.first {
let date1 = teacher.modifiedDate
let date2 = modifiedDate
let compareResult = date1.compare(date2)
if compareResult == NSComparisonResult.OrderedAscending {
teacher.setValue(name, forKey: "name")
teacher.setValue(email, forKey: "email")
teacher.setValue(subjectsTaught, forKey: "subjectsTaught")
teacher.setValue(category, forKey: "category")
teacher.setValue(modifiedDate, forKey: "modifiedDate")
}
}
}
}
var error: NSError?
if !self.managedObjectContext.save(&error) {
println("Error \(error)")
abort()
}
}
}
My question is how should I figure out which objects where not in parse? I don't want to query parse for every object in my database as I assume that would be network intensive.
Should I do a fetchrequest for all Teacher objects in the beginning and as I iterate through the parse objects, delete them as I go? If I have objects left, those should be deleted?
Okay, I figured out what to do. I ended up running a fetchrequest first for all teacher and appending their names to an array. During the parse iteration, I deleted teachers from that list as I went through them and at the end, used that list to delete teachers from the database.
let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName("Teacher", inManagedObjectContext: self.managedObjectContext)
var error: NSError?
var foundTeacherNames = [String]()
if let foundTeachers = self.managedObjectContext.executeFetchRequest(fetchRequest, error: &error) as? [Teacher] {
for teacher in foundTeachers {
foundTeacherNames.append(teacher.name)
}
}
//Find teachers in parse database
let query = PFQuery(className: "TeacherList")
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
let object = object as! PFObject
let name = object["name"] as! String
let email = object["email"] as! String
let subjectsTaught = object["subjectsTaught"] as! [String: String]
let category = object["category"] as! String
let uniqueID = object.objectId!
let modifiedDate = object.updatedAt!
let fetchRequest2 = NSFetchRequest(entityName: "Teacher")
fetchRequest2.predicate = NSPredicate(format: "uniqueID == %#", uniqueID)
var error2: NSError?
if let foundTeachers = self.managedObjectContext.executeFetchRequest(fetchRequest2, error: &error2) as? [Teacher] {
if foundTeachers.isEmpty == true {
let teacher = NSEntityDescription.insertNewObjectForEntityForName("Teacher", inManagedObjectContext: self.managedObjectContext) as! Teacher
teacher.name = name
teacher.email = email
teacher.subjectsTaught = subjectsTaught
teacher.category = category
teacher.uniqueID = uniqueID
teacher.modifiedDate = modifiedDate
} else {
if let teacher = foundTeachers.first {
let date1 = teacher.modifiedDate
let date2 = modifiedDate
let compareResult = date1.compare(date2)
if compareResult == NSComparisonResult.OrderedAscending {
teacher.setValue(name, forKey: "name")
teacher.setValue(email, forKey: "email")
teacher.setValue(subjectsTaught, forKey: "subjectsTaught")
teacher.setValue(category, forKey: "category")
teacher.setValue(modifiedDate, forKey: "modifiedDate")
}
}
}
if contains(foundTeacherNames, name) {
let i = find(foundTeacherNames, name)!
foundTeacherNames.removeAtIndex(i)
}
}
var error: NSError?
if !self.managedObjectContext.save(&error) {
println("Error \(error)")
abort()
}
if !foundTeacherNames.isEmpty {
for teacher in foundTeacherNames {
let request = NSFetchRequest(entityName: "Teacher")
request.predicate = NSPredicate(format: "name = %#", teacher)
if let fetchResults = self.managedObjectContext.executeFetchRequest(request, error: nil) as? [NSManagedObject] {
if fetchResults.count != 0 {
self.managedObjectContext.deleteObject(fetchResults[0])
}
}
}
}
Yes, the best way is to fetch all entities and then check for the unique ids. You could use key-value-coding (or its Swift equivalents such as map) to just get the ids you are interested in.
let existingIDs = entitiesFromParse.map() { $0.uniqueID as? String }
You can then check if an ID exists with
let idExists = existingIDs.contains(idToCheck)
This is preferable to multiple fetch requests which are expensive.

swift - How to check CoreData exists

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
}
}

Resources