Everytime I use NSPredicate in fetching my records from CoreData, I always get zero or no records at all. Here's my function:
func get_facility(company: String, territory: String){
print("company: " + company)
print("territory: " + territory)
var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
var context:NSManagedObjectContext = appDel.managedObjectContext
let companyPredicate = NSPredicate(format: "company LIKE %#", company)
let territoryPredicate = NSPredicate(format: "territory LIKE %#", territory)
let predicate = NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates: [companyPredicate, territoryPredicate])
let fetchRequestFacility = NSFetchRequest(entityName:"Facility")
fetchRequestFacility.predicate = predicate
do {
let facility_temp = try context.executeFetchRequest(fetchRequestFacility)
facility = facility_temp as! [Facility]
c = facility_temp.count
print(c)
tableview_facility.reloadData()
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
}
When I comment out the the line fetchRequestFacility.predicate = predicate it shows all of my records. The fields company and territory are of type String.
I also tried changing the LIKE keyword to == and =. But I still get no records.
Possible values for company = 1 and territory = 1. These are numbers but with String data type. And here's the structure of my facility entity:
I think I found the culprit, when I print the values of company and territory, I get the:
company: Optional(1)
territory: Optional(1)
And when I try this predicate: let companyPredicate = NSPredicate(format: "company = '1'"), I am able to fetch records. Maybe its because the variables company and territory have Optionals string. I don't know how to remove it. I tried putting ! to my variable but still the same.
Related
i have a string called "word" and i stored this string into a an entity called Lose inside an attribute word,
i want when the user save a string "word" again it will overwrite the current value not sitting a duplicate one, how to do that ?
what i have done so far:
//save the data to core data
let library = Lose(context: savecatch.context)
library.word = "word"
savecatch.saveContext()
before the saving i need to check if "word" is already exist or not
You have to fetch the record with the given attribute, then modify it and save it
let query = "word"
let request = NSFetchRequest<Lose> = Lose.fetchRequest()
request.predicate = NSPredicate(format: "word == %#", query)
do {
let result = try context.fetch(request)
if let found = result.first {
found.word = "word"
context.save()
}
} catch {
print(error)
}
I am a new hand to Core Data,I don't know how to write some query sentence for NSPredicate and meet some problem.Please help to find my problem and give me some suggestion to achieve my query aim.For example,now I Have a table ,it has some data .(As the picture show)My database
The data in the table with the month attribute "2015/03/01 00:00:00".Now,I want to query a date which month is began with 2015/03,I code "fetchRequest.predicate = NSPredicate(format: "month BEGINSWITH[cd] %#/0%#", year,month)" or "fetchRequest.predicate = NSPredicate(format: "month LIKE[c] %#/0%#", year,month)",am I right?(year=2015,month=03)
If not,I really hope someone can help me.And another question is the 'cd/c' in [] means what?Is it set structures?The code as follow:
func remove(model:MonthlySummery) -> Int {
let cxt = self.managedObjectContext!
let entity = NSEntityDescription.entityForName("MonthlySummery", inManagedObjectContext: cxt)
let component = NSCalendar.currentCalendar().components([.Year,.Month], fromDate: model.month!)
let year = component.year
let month = component.month
let fetchRequest = NSFetchRequest()
fetchRequest.entity = entity
NSLog("month == %i/0%i", year,month)
fetchRequest.predicate = NSPredicate(format: "month BEGINSWITH[cd] %#/0%#", year,month)
do{
let listData = try cxt.executeFetchRequest(fetchRequest) as NSArray!
if listData.count > 0 {
let dailyRecord = listData.lastObject as! NSManagedObject
cxt.deleteObject(dailyRecord)
if cxt.hasChanges {
try cxt.save()
}
}
} catch {
NSLog("Remove failure!")
let nserror = error as NSError
NSLog("Error: \(nserror), \(nserror.userInfo)")
}
return 0
}
It is a bad idea to parse dates by relying on formatted date strings.
Refactor your code to use proper dates. The NSManagedObject subclass should have a property of type NSDate. In the actual SQLite database, this will be represented by a long number, but you should not be interested in that.
You then calculate start and end date of particular month and use a predicate like this:
NSPredicate(format: "month >= %# && month < %#", start, end)
I'm trying to implement a search by Core Data key, in Swift. I want to get back relevant results, both exact and proximate, sorted in order of distance (from the closest match to the most distant).
For example, if someone searches for, say, "friend", I want the search results to look something like the following: "friend", "friends", "friendly", and "friand".
I've tried my best to implement such a search, but I'm fairly new to this sort of code, and my attempted implementation is not quite working for me at the moment. This is my code:
var request = NSFetchRequest(entityName: "db")
request.returnsObjectsAsFaults = false
request.predicate = NSPredicate(format: "dbKey MATCHES %#", ".*" + searchString + ".*")
var results: Array = context.executeFetchRequest(request, error: nil)!
if (results.count > 100) {
results.removeRange(Range(start: 100, end: results.count-1))
}
var sortedResults: Array = [results[0]]
for (var i = 1; i < results.count; ++i) {
if (countElements(results[i].valueForKey("dbKey") as String) < countElements(sortedResults[i-1].valueForKey("dbKey") as String)) {
var j = i-1
while (countElements(results[i].valueForKey("dbKey") as String) < countElements(sortedResults[j].valueForKey("dbKey") as String)) {
if (j != 0) {
--j
} else {
break
}
}
sortedResults.insert(results[i], atIndex: j)
} else {
sortedResults.append(results[i])
}
}
results = sortedResults
The problem is twofold:
Firstly, the results come back in no particular order, so if I search for "a", I'm going to get back a huge amount of words containing "a" long before I get the exact match. Since I cut off after the first 100 results, I never get the exact match to show up in my results.
Secondly, the ranking is approximate. This is probably a maths error on my part, but currently, many longer words show up before shorter words, so you don't see exact or near-exact matches at the top of the results list, as you should.
I tried to find a library which would incorporate search functionality of the kind I am looking for (something like Fuse.js), but I've had no luck. Any help would be most appreciated.
You could filter your results using different predicates and decide which one to use;
let result = NSPredicate(format: "dbKey CONTAINS[cd] %#", searchString)
let result = NSPredicate(format: "dbKey startsWith[cd] %#", searchString)
let result = NSPredicate(format: "dbKey LIKE '%#'", searchString)
For particular order, you should use NSSortDescriptor
Not an actual answer to your question, but a solution to what you're trying to do still: have a look at PermissiveResearch.
It would look something like this:
extension UIViewController: PermissiveResearchDelegate {
// Call this once
func rebuildDatabase() {
PermissiveResearchDatabase.sharedDatabase().delegate = self
for db in allDbs { // Assuming allDbs is your array of DB objects
PermissiveResearchDatabase.sharedDatabase().addManagedObject(db, forKey: "dbKey")
}
}
// A basic search method
func search(searchString: String) {
PermissiveResearchDatabase.sharedDatabase().searchString(searchString, withOperation: ScoringOperationTypeExact)
}
// PermissiveResearchDelegate method
func searchCompletedWithResults(results: [AnyObject]!) {
let pResults = results as! [PermissiveCoreDataObject]
for result in pResults {
let db = try! self.managedObjectContext.existingObjectWithID(result.objectID) as! DB
print("\(result.score) - \(db.dbKey)")
}
}
}
Very new to Core Data but I've read that I can fetch data that uses Entity relationships. Now, coming from Mysql maybe I'm making too many assumptions, but I have 2 Entities set up with a Relationship between them and I can't fetch the proper data.
Here are my 2 models:
#objc(Categories)
class Categories: NSManagedObject {
#NSManaged var category: String
#NSManaged var exp: String
#NSManaged var order: NSNumber
}
#objc(Techniques)
class Techniques: NSManagedObject {
#NSManaged var korean: String
#NSManaged var order: NSNumber
#NSManaged var spanish: String
#NSManaged var categories: Categories
}
After I created a Relationship from Techniques to Categories, Core Data added this field to the Sqlite DB:
ZCATEGORIES - INTEGER
Let's say I want to fetch all Techniques that belong to the category #3 (with internal ZID: 3)
If I do this:
request.predicate = NSPredicate(format: "categories == %#", 3)
It works. But if I do:
request.predicate = NSPredicate(format: "categories == %#", category.category)
It doesn't work. I understand that it doesn't work because category.category is a String, not an Integer.
My question is:
Do I have to create my own relationhip IDs field in the Category Entity and set that, then reference the Technique like:
request.predicate = NSPredicate(format: "categories == %#", category.categoryID)
?
Isn't there a way to access the Category's internal ID to get this relationship to work?
Or better yet, it would seem to me that there should be an internal mechanish to retrieve these relationships without writing a SQL-like query but just using the Object, something like: Techniques.categores.
Thanks. I haven't found a good answer anywhere.
You are missing an attribute name, so the predicate knows which attribute of the category class to compare. This way you won't need to use the internal unique ID. Although it can be derived (and would work) it's not the way to go with Core Data, who is trying to abstract that information for you.
let categoryPredicate = NSPredicate(format: "categories.category == %#", category.category)
As mentioned setting up an inverse relationship is recommended. It allows Core Data to maintain the consistency of the object graph, and can be used to go from a category to it's techniques.
As you solved friend?
import UIKit
import CoreData
let appdelegado:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let contexto2:NSManagedObjectContext = appdelegado.managedObjectContext
class Consultar: UIViewController {
let marca = Marca()
let modelo = Modelo()
override func viewDidLoad() {
super.viewDidLoad()
//Consultando con diferente contextp
let entityMarca = NSEntityDescription.entityForName("Modelo", inManagedObjectContext: contexto2)
let oderBy = NSSortDescriptor(key: "nombre", ascending: true)
let consulta = NSFetchRequest(entityName: "Modelo")
consulta.sortDescriptors = [oderBy]
//???¿¿???¿¿???¿ HELP
let predicate = NSPredicate(format: "modelo.marca = %#",)
consulta.entity = entityMarca
consulta.predicate = predicate
//let arrayResultado:[NSArray] = try!contexto.executeFetchRequest(consulta) as! [NSArray]
//if let resultado = try?contexto.executeFetchRequest(consulta) where resultado.count > 0{
if let arrayResultado:[NSArray] = try!contexto.executeFetchRequest(consulta) as! [NSArray] where arrayResultado.count > 0{
for x in arrayResultado {
print("\n ====================DATOS RECUPERADOS======================")
print(x)
// print(x.valueForKey("nombre")!)
// print(x.valueForKey("marca")!)
}
}else{
print("Sin modelos")
}
}
}
i read out all my Core Data Objects using:
var fetchRequest = NSFetchRequest(entityName: "QuestionsSelectOption")
fetchRequest.predicate = NSPredicate(format: "questions = %#", currentQuestion!)
selectOptions = context.executeFetchRequest(fetchRequest, error: nil) as [QuestionsSelectOption]
And now i can use my Objects with
let myTestObject = selectOptions(index) as QuestionsSelectOption
But how do i update a Core Data Object without any Identifier? How can i make a NSPredicate with my Object itself as my ID?
Or what is the best way to update (in this case) "myTestObject" in Swift? I could use the Index, but i dont think that is a good way.
Edit: Now i use:
request.predicate = NSPredicate(format: "self = %#", myTestObject)
var results = context.executeFetchRequest(request, error: nil) as Array
if(results.count == 1) {
let currentQuestionSelectOption = results[0] as QuestionsSelectOption
currentQuestionSelectOption.selected = selected
context.save(nil)
}
It works - But is there not an easier/better solution?
Just modify the selected property of myTestObject call context.save() then that's it. Because results[0] if any is actually myTestObject.