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] = []
Related
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 have a very beginner question.
First of all, i have an Entity(Person) with an Attribute(name).
I want to fetch the name attributes to one array to pick a randomElement from. The following code successfully returns data to separate arrays:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Person")
request.returnsObjectsAsFaults = false
var myArray: [String]?
do {
let results = try context.fetch(request)
for result in results as! [NSManagedObject] {
if let username = result.value(forKey: "name") as? String {
myArray = [username]
print(myArray!)
}
}
}
catch {
print("not successful")
}
What can I use instead of 'FOR'? And how?
Thank you so much, and sorry for my soo beginner question.
You may cast to actual entity name
var myArray = [String]()
do {
let results = try context.fetch(request)
myArray = (results as! [Person]).compactMap { $0.name }
print(myArray)
}
catch {
print("not successful")
}
Right now my code is using NSPredicate or sort descriptor to basically just collect a name. I would like NSPredicate to sort all of the names from a-z thats it.
COREDATAHANDLER
class coreDataHandler: NSObject {
private class func getContext() -> NSManagedObjectContext{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
class func saveObject(username:String, password:String) -> Bool{
let context = getContext()
let entity = NSEntityDescription.entity(forEntityName: "User", in: context)
let managedObject = NSManagedObject(entity: entity!, insertInto: context)
managedObject.setValue(username, forKey: "username")
managedObject.setValue(password, forKey: "password")
do {
try context.save()
return true
} catch {
return false}
}
class func filterData() -> [User]? {
let conttext = getContext()
let fetchRequest:NSFetchRequest<User> = User.fetchRequest()
var user:[User]? = nil
var predicate = NSPredicate(format: "username contains[d] %#" ,"duke")
fetchRequest.predicate = predicate
do {
user = try conttext.fetch(fetchRequest)
return user
}catch {
return user
}
}
VIEWCONTROLLER
user = coreDataHandler.filterData()
for i in user! {
print("Judou : \(i.username!)")
}
If you want your user array to be sorted by username and then password, I would add a class function to your CoreDataHandler class to get a sorted array:
class func getSortedData() -> [User]? {
let conttext = getContext()
let fetchRequest:NSFetchRequest<User> = User.fetchRequest()
var user:[User]? = nil
var nameSort = NSSortDescriptor(key:"username", ascending:true)
var passwordSort = NSSortDescriptor(key:"password", ascending:false)
fetchRequest.sortDescriptors = [nameSort, passwordSort]
do {
user = try conttext.fetch(fetchRequest)
return user
} catch {
return user
}
}
Then in your view controller, use this new function to get the sorted array:
user = coreDataHandler.getSortedData()
for i in user! {
print("Judou : \(i.username!), Password:\(i.password)")
}
In swift 4 or swift 5, you can use
func sortlist(){
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "User")
let sort = NSSortDescriptor(key: "username", ascending: false)
fetchRequest.sortDescriptors = [sort]
//3
do {
let langugeCodes = try managedContext.fetch(fetchRequest)
for result in langugeCodes as [NSManagedObject] {
var username:String = result.value(forKey: "username")! as! String
var password:String = result.value(forKey: "password")! as! String
print("username==>",username)
print("name==>",name)
}
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
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.
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 _ {
}