I have an Expense entity with a one-to-many relationship to an Accounts Entity.
My current fetch request is as follows:
let request = NSFetchRequest<NSFetchRequestResult>(entityName: Expenses.entity().name ?? "Expenses")
request.predicate = predicate
request.returnsObjectsAsFaults = false
request.resultType = .dictionaryResultType
let expression = NSExpressionDescription()
// check operations list from apple or nshipster in nsexpressions
expression.expression = NSExpression(forFunction: "noindex:", arguments:[NSExpression(forKeyPath: "originAccounts.isCredit")])
expression.name = "checkIsCredit"
expression.expressionResultType = .booleanAttributeType // might be another
let expression1 = NSExpressionDescription()
expression1.expression = NSExpression(forFunction: "noindex:", arguments:[NSExpression(forKeyPath: "id")])
expression1.name = "checkExpenses"
expression.expressionResultType = .UUIDAttributeType
request.propertiesToFetch = [expression,expression1]
context.perform {
do {
let results = try request.execute()
print(results)
My Predicate is:
predicate: NSPredicate(format: "expenseDate >= %# AND expenseDate < %#", datesView.prevMonthPayStart as NSDate, datesView.nextPaydate as NSDate)
When I print the results I get
[{
expenseAccount = "Test Account";
expenseCategory = "Test Category";
expenseCost = 123;
expenseDate = "2020-11-12 05:00:00 +0000";
expenseIsPaid = 1;
expenseName = Test;
expenseType = "One-time";
id = "AFB5EB0E-20A2-47EA-8F36-22D07571C213";
shouldDupe = 1;
}, {
expenseAccount = "Test Account";
expenseCategory = "Test Category";
expenseCost = 23;
expenseDate = "2020-11-13 05:00:00 +0000";
expenseIsPaid = 0;
expenseName = "Test Recurring";
expenseType = Monthly;
id = "5CFB5E58-4377-40DA-9C6A-AF8027ACEC60";
shouldDupe = 1;
}]
I understand that I won't see attributes that are nil, but I want to get an attribute through originAccounts relationship. Is this possible? Specifically I want to get the value of originAccounts.isCredit. Here is an example object for reference.
<Expenses: 0x60000321af80> (entity: Expenses; id: 0xa7ab05bb9341bf4a <x-coredata://ED302202-3018-445F-8FFE-DD2E85219E64/Expenses/p1>; data: {
expenseAccount = "Test Account";
expenseCategory = "Test Category";
expenseCost = 123;
expenseDate = "2020-11-12 05:00:00 +0000";
expenseId = nil;
expenseIsPaid = 1;
expenseName = Test;
expenseType = "One-time";
id = "AFB5EB0E-20A2-47EA-8F36-22D07571C213";
lastMonthlyExpenseID = nil;
nextMonthlyExpenseID = nil;
originAccounts = "0xa7ab05bb9341bf4e <x-coredata://ED302202-3018-445F-8FFE-DD2E85219E64/Accounts/p1>";
originCategories = nil;
shouldDupe = 1;
})
Could you try NSExpressions, you won't make a fetch, therefore you'll be mutch efficient.
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "yourEntity")
fetchRequest.predicate = NSPredicate(format: "yourPredicate")
fetchRequest.resultType = .dictionaryResultType
fetchRequest.returnsObjectsAsFaults = false
let expression = NSExpressionDescription()
// check operations list from apple or nshipster in nsexpressions
expression.expression = NSExpression(forFunction: "yourOperation", arguments:[NSExpression(forKeyPath: "Expenses.originAccounts.isCredit")])
expression.name = "yourName"
expression.expressionResultType = .decimalAttributeType // might be another
fetchRequest.propertiesToFetch = [expression]
do {
let results = try viewContext.fetch(fetchRequest)
print(results)
} catch {
print("Failed to fetch aggregates")
}
}
Related
I'm very lost parsing the following response from an AF request – let json = result as! NSDictionary – in Swift:
{
errors = (
);
get = statistics;
parameters = {
country = germany;
};
response = (
{
cases = {
"1M_pop" = 14303;
active = 317167;
critical = 4179;
new = "+15161";
recovered = 863300;
total = 1200006;
};
continent = Europe;
country = Germany;
day = "2020-12-08";
deaths = {
"1M_pop" = 233;
new = "+380";
total = 19539;
};
population = 83900328;
tests = {
"1M_pop" = 347331;
total = 29141172;
};
time = "2020-12-08T09:15:08+00:00";
}
);
results = 1;
}
Any idea how to get the actual case numbers, i.e. for example the number of new cases?
So far I have tried the following (error throwing) approach:
if let responseDict = result as? NSDictionary {
if let data = responseDict.value(forKey: "response") as?
[NSDictionary] {
// Get case numbers
guard let cases = data[0]["cases"] else { return }
guard let casesPerOneMil = cases[0] as! Int else { return }
print(casesPerOneMil)
}
}
Basically don't use NS... collection types in Swift at all, use native types.
And don't use value(forKey, use key subscription.
And you have to conditional downcast Any to the expected concrete type.
There is another mistake: The object for cases is a dictionary, note the {} and you have to get the value for casesPerOneMil with key subscription, too
if let responseDict = result as? [String:Any],
let dataArray = responseDict["response"] as? [[String:Any]],
let firstDataItem = dataArray.first {
// Get case numbers
guard let cases = firstDataItem["cases"] as? [String:Any] else { return }
guard let casesPerOneMil = cases["1M_pop"] as? Int else { return }
print(casesPerOneMil)
}
}
I've got a problem with storing an NSDictionary object with 39 parameters (key and value) into a UserDefault object. The code crashes where I left the comment. self.userDefaults.set(data, forKey: "userData")
This is the error I'm getting:
[User Defaults] Attempt to set a non-property-list object {
city = "";
country = "";
cover = "default.png";
date = "2019-10-02";
description = "";
email = "hashdoge#outlook.com";
"email_comment" = 0;
"email_like" = 0;
"email_new_friend" = 0;
"email_newsletter" = 1;
facebook = "";
"first_name" = "";
follower = 3;
following = 2;
gender = 0;
gplus = "";
idu = 42;
image = "default.png";
ip = "";
"last_name" = "";
lastfm = "";
likes = 3;
"login_token" = "<null>";
"logout_time" = 0;
myspace = "";
notificationc = 1;
notificationd = 1;
notificationf = 1;
notificationl = 1;
offline = 0;
online = 1570879800;
password = "$2y$107675ze1wZ/riJgQ2e";
private = 0;
salted = "$2y$10$GKUmSJGcq932DMJGMA8791RIO";
soundcloud = "";
suspended = 0;
totaltracks = 0;
tumblr = "";
twitter = "";
username = HashDoge;
vimeo = "";
website = "";
youtube = "";} as an NSUserDefaults/CFPreferences value for key userData
Here is the code that I'm trying to make work
Code:
func callApigetLoginResponse(){
FTIndicator.showProgressWithmessage("", userInteractionEnable: false)
let parameters = ["useremail":txtEmail.text!,"password":txtPassword.text!]
SignInGet.ApiGetSignIn(parameters: parameters as NSDictionary) { (Result, Error) in
// print(Result!)
if Error != nil{
print(Error!)
}else{
let dataDict:NSDictionary = Result as! NSDictionary
if (dataDict["success"]as! Int == 1){
let loginResponse = dataDict["userlogin"] as! NSArray
let data = loginResponse[0] as! NSDictionary
let uid = data["idu"] as! String
self.sendTokenaApi(uid: uid)
self.userDefaults.set(uid, forKey: "id")
self.userDefaults.set(data, forKey: "userData") // code crashes here
self.userDefaults.synchronize()
let updateUserInfo = UpdateUserInfoUtl()
updateUserInfo.callApigetUserDataResponse()
self.pushToHomeController()
}else if (dataDict["success"]as! Int == 0) {
let message = dataDict["userlogin"] as! String
FTIndicator.showInfo(withMessage: message)
}
}
}
}
I fixed it. The problem was the "< n u l l >" in the login_token.
I made it as an empty string "" in the database and it worked.
I need convert NSArray to Dictionary, but don't know how can I do it.
After fetch request I have result in NSArray. This my request:
var results: NSArray = []
func fetchUpdateAttendee() {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Attendee")
let predicate = NSPredicate(format: "needUpdate != false")
fetchRequest.predicate = predicate
results = try! DBWorker.context.fetch(fetchRequest) as NSArray
results.forEach { result in
print(result)
}
var results: NSArray = []
print(results) give me
<Attendee: 0x60c000097750> (entity: Attendee; id: 0x60c000422200 <x-coredata:///Attendee/t9E88E2EE-9258-4FAE-AF80-9B036838C6D631> ; data: {
address = "1411 E 31st St";
affiliation = "";
attendeeType = nil;
city = Aguanga;
degree = MD;
email = "";
fax = "";
firstName = Oliver1212;
fullStateLicense = "";
id = nil;
lastName = Aalami;
meeting = nil;
needUpdate = 1;
phone = "";
signature = nil;
signatureTimeStamp = nil;
specialty = Surgery;
state = CA;
stateLicense = "";
status = nil;
timeStamp = nil;
zip = 92536;
})
I need to put these datas to: let dic4Attendee: [String: Any] = [:]
This is a Core Data NSManagedObject subclass, so the code is supposed to be
var results = [Attendee]()
func fetchUpdateAttendee() {
let fetchRequest = NSFetchRequest<Attendee>(entityName: "Attendee")
let predicate = NSPredicate(format: "needUpdate == TRUE")
fetchRequest.predicate = predicate
do {
results = try DBWorker.context.fetch(fetchRequest)
results.forEach { result in
print(result)
}
} catch { print(error) }
}
never use NSArray to represent an array of NSManagedObject subclass.
Add a property dictionaryRepresentation in the Attendee class and return the key value pairs you need for example
var dictionaryRepresentation : [String:Any] {
return ["address" : address,
"affiliation" : affiliation,
"city" : city
// and so on
]
}
then map the array
let mappedArray = results.map{ $0.dictionaryRepresentation }
Working on a part of my application that involves filtering the objects being sent to the tableview. I have tried using a CompoundNSPredicate but the result was nothing showed. If I do each filter separately I can call the fetchrequest for 1 type of objects but when I try to use a second line calling the second type of objects under the same loop condition the second objects don't appear at all. Example for where I am:
let fetchRequest = NSFetchRequest(entityName: "Cards")
let warriorpredicate = NSPredicate(format: "cardClass = %i", 1)
let shamanpredicate = NSPredicate(format: "cardClass = %i", 2)
let roguepredicate = NSPredicate(format: "cardClass = %i", 3)
let paladinpredicate = NSPredicate(format: "cardClass = %i", 4)
let hunterpredicate = NSPredicate(format: "cardClass = %i", 5)
let druidpredicate = NSPredicate(format: "cardClass = %i", 6)
let warlockpredicate = NSPredicate(format: "cardClass = %i", 7)
let magepredicate = NSPredicate(format: "cardClass = %i", 8)
let priestpredicate = NSPredicate(format: "cardClass = %i", 9)
let minionpredicate = NSPredicate(format: "cardClass = %i", 10)
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
if ((passedDeckObject?.classSelected.classname = "Warrior" ) != nil) {
fetchRequest.predicate = warriorpredicate
} else {
if ((passedDeckObject?.classSelected.classname = "Shaman" ) != nil) {
fetchRequest.predicate = shamanpredicate
fetchRequest.predicate = minionpredicate
} else {
if ((passedDeckObject?.classSelected.classname = "Rogue" ) != nil) {
fetchRequest.predicate = roguepredicate
}
if ((passedDeckObject?.classSelected.classname = "Paladin" ) != nil) {
fetchRequest.predicate?.isEqual(paladinpredicate)
fetchRequest.predicate?.isEqual(minionpredicate)
} else {
if ((passedDeckObject?.classSelected.classname = "Hunter" ) != nil) {
fetchRequest.predicate?.isEqual(hunterpredicate)
fetchRequest.predicate?.isEqual(minionpredicate)
} else {
if ((passedDeckObject?.classSelected.classname = "Druid" ) != nil) {
fetchRequest.predicate?.isEqual(druidpredicate)
fetchRequest.predicate?.isEqual(minionpredicate)
} else {
if ((passedDeckObject?.classSelected.classname = "Warlock" ) != nil) {
fetchRequest.predicate?.isEqual(warlockpredicate)
fetchRequest.predicate?.isEqual(minionpredicate)
} else {
if ((passedDeckObject?.classSelected.classname = "Mage" ) != nil) {
fetchRequest.predicate?.isEqual(magepredicate)
fetchRequest.predicate?.isEqual(minionpredicate)
} else {
if ((passedDeckObject?.classSelected.classname = "Priest" ) != nil) {
fetchRequest.predicate = priestpredicate
}
}
}
}
}
}
}
}
return fetchRequest
}
Some of the code looks different but that's cause I was testing each one with different lines I gave examples using both ways I have tried minus the compoundpredicate attempt which showed nothing at all.
The answer to this came in multiple ways. There were many methods that could be used to actually do what I was looking to do but the simplest most elegant solution was:
func listFetchRequest() -> NSFetchRequest {
let requiredClassName = passedDeckObject!.classSelected.classname
var requiredCardClasses = [Int]()
let fetchRequest = NSFetchRequest(entityName: "Cards")
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
switch(requiredClassName) {
case "Warrior":
requiredCardClasses = [1,10]
case "Shaman":
requiredCardClasses = [2,10]
case "Rogue":
requiredCardClasses = [3,10]
case "Paladin":
requiredCardClasses = [4,10]
case "Hunter":
requiredCardClasses = [5,10]
case "Druid":
requiredCardClasses = [6,10]
case "Warlock":
requiredCardClasses = [7,10]
case "Mage":
requiredCardClasses = [8,10]
case "Priest":
requiredCardClasses = [9,10]
default:
requiredCardClasses = [10]
}
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.predicate = NSPredicate(format:"cardClass IN %#", requiredCardClasses)
return fetchRequest
}
I'm trying to disseminate the response of a NSJSONSerialization:
let responseDict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &jsonError) as NSDictionary
So far, I have a good output which I want to dissect/disseminate:
(lldb) po responseDict
{
photos = {
page = 1;
pages = 1333;
perpage = 100;
photo = (
{
farm = 4;
"height_m" = 243;
"height_s" = 117;
"height_sq" = 75;
"height_t" = 49;
id = 15148883617;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = "48531100#N04";
secret = fb6596ca90;
server = 3926;
title = "An Exceptional Roman Orichalcum Sestertius of Nero (54-68 C.E.), a Magnificent Depiction of the Temple of Janus on the Reverse";
"url_m" = "https://farm4.staticflickr.com/3926/15148883617_fb6596ca90.jpg";
"url_s" = "https://farm4.staticflickr.com/3926/15148883617_fb6596ca90_m.jpg";
"url_sq" = "https://farm4.staticflickr.com/3926/15148883617_fb6596ca90_s.jpg";
"url_t" = "https://farm4.staticflickr.com/3926/15148883617_fb6596ca90_t.jpg";
"width_m" = 500;
"width_s" = 240;
"width_sq" = 75;
"width_t" = 100;
},
...
...
The problem is doing the dissemination.
Here's the contents of "photos" key (rather ugly compared to the ObjC counterpart):
(lldb) po responseDict["photos"]
(instance_type = Builtin.RawPointer = 0x00007fce90ec74e0 -> 0x0000000105a910e0 (void *)0x0000000105a91220: __NSDictionaryM)
{
instance_type = 0x00007fce90ec74e0 -> 0x0000000105a910e0 (void *)0x0000000105a91220: __NSDictionaryM
}
This line produces a fatal (dynamic cast) crash:
let myPhotos = responseDict["photos"] as NSArray
Here's an ObjC equivalent (that works):
jsonDict[#"photos"][#"photo"];
Compare that to the following Swift equivalent that gives me an error (even though I had downcast it to NSDictionary):
(lldb) po responseDict["photos"]["photo"]
error: <EXPR>:1:1: error: 'AnyObject?' does not have a member named 'subscript'
responseDict["photos"]["photo"]
Question: How do I properly dissect a dictionary (or any collection) in Swift as I can in Objective-C?
I managed to get down to the individual dictionary:
let myPhotos = responseDict["photos"] as? NSDictionary
let photos = myPhotos!["photo"] as? NSArray
let myPhoto:AnyObject = photos![0]
println(myPhoto)
Here's the output:
{
farm = 4;
"height_m" = 500;
"height_s" = 240;
"height_sq" = 75;
"height_t" = 100;
id = 15150188169;
isfamily = 0;
isfriend = 0;
ispublic = 1;
owner = "87355413#N02";
secret = e9cfed5225;
server = 3905;
title = "Miss 18mths wearing Music Box pinafore in grey denim (18-24mths). Trimmed with aqua/pink ric rac, and \"bow\" button.";
"url_m" = "https://farm4.staticflickr.com/3905/15150188169_e9cfed5225.jpg";
"url_s" = "https://farm4.staticflickr.com/3905/15150188169_e9cfed5225_m.jpg";
"url_sq" = "https://farm4.staticflickr.com/3905/15150188169_e9cfed5225_s.jpg";
"url_t" = "https://farm4.staticflickr.com/3905/15150188169_e9cfed5225_t.jpg";
"width_m" = 375;
"width_s" = 180;
"width_sq" = 75;
"width_t" = 75;
}
And to test it further:
let myPhoto = myPhotoInfo["url_m"] as String
Produces:
https://farm4.staticflickr.com/3920/15333895891_956d072454.jpg
From the Objective-C code that works it appears that responseDict["photos"] is not an NSArray, it is NSDictionary. This should work:
let myPhotos = responseDict["photos"] as? NSDictionary
let photo = myPhotos!["photo"]