How do I property dissect/disseminate a Dictionary with an Array? - swift

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"]

Related

Parse Alamofire result swift

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

SwiftUI - Include Relationship info in FetchRequest

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

User Defaults Attempt to set a non-property-list object

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.

Why does the debugger 'po' works with 'var' vs 'let'?

Why does the debugger 'po' works with var:
var myDict = currentImageDownloader.dict
As shown here:
(lldb) po myDict
Some
{
[0] = {
key = "ispublic"
value = (instance_type = Builtin.RawPointer = 0xb000000000000013)
(lldb) po myDict
error: <EXPR>:1:1: error: use of unresolved identifier 'myDict'
myDict
...
yet via 'let':
let myDict = currentImageDownloader.dict
The debugger 'po' doesn't work:
(lldb) po myDict
error: <EXPR>:1:1: error: use of unresolved identifier 'myDict'
myDict
^
Although I can view everything via 'let' or 'var' using the debugger's frame command:
(lldb) fr v
(UICollectionView) collectionView = 0x00007fc2d2821600 {
UIKit.UIScrollView = {
UIKit.UIView = {
UIKit.UIResponder = {
ObjectiveC.NSObject = {}
}
}
}
}
(NSIndexPath) indexPath = 0xc000000000000016 {
ObjectiveC.NSObject = {}
}
(FlickrSwift.ViewController) self = 0x00007fc2d2580f20 {
UIKit.UIViewController = {
UIKit.UIResponder = {
ObjectiveC.NSObject = {}
}
}
collectionView = Some
}
(FlickrSwift.ImageDownloader) currentImageDownloader = 0x00007fc2d4449750 {
image = nil
bigImage = nil
dict = Some {
[0] = {
key = "ispublic"
value = (instance_type = Builtin.RawPointer = 0xb000000000000013)
}
[1] = {
key = "height_sq"
value = (instance_type = Builtin.RawPointer = 0xb0000000000004b3)
}
[2] = {
key = "url_m"
value = (instance_type = Builtin.RawPointer = 0x00007fc2d25131a0 -> 0x00000001088e7488 (void *)0x00000001088e7438: __NSCFString)
}
[3] = {
key = "title"
value = (instance_type = Builtin.RawPointer = 0x00007fc2d25a7030 -> 0x00000001088e7488 (void *)0x00000001088e7438: __NSCFString)
}
[4] = {
key = "isfamily"
value = (instance_type = Builtin.RawPointer = 0xb000000000000003)
}
...
}
descString = nil
}
(AnyObject) cell = <variable not available>
(UIImageView) photoImageView = <variable not available>
(UIImage) image = <variable not available>
There were a couple of bugs in the debug information for "let" variables that kept lldb from being able to understand them correctly. These should all be fixed in the upcoming Xcode release. You'll need to recompile your code once you get the new release, but after that you should be able to see them.
If you aren't please file a bug with http://bugreporter.apple.com.

How do I retrieve an array from a dictionary which and then retrieve a dictionary within that array?

I would like to know how to retrieve an array from within a dictionary and then retrieve the dictionary from the array object.
i'm following this http://ios.biomsoft.com/2011/09/11/simple-xml-to-nsdictionary-converter/
itemDict
(
{
postID = {
text = 26;
};
score = {
text = 20;
};
title = {
text = "http://www.google.com quiz";
};
url = {
text = "http://www.google.com";
};
},
{
postID = {
text = 27;
};
score = {
text = 10;
};
title = {
text = "http://www.google.com";
};
url = {
text = "http://www.google.com";
};
},
{
postID = {
text = 3;
};
score = {
text = 41;
};
title = {
text = "http://www.google.com";
};
url = {
text = "http://www.google.com";
};
},
{
postID = {
text = 35;
};
score = {
text = 10;
};
title = {
text = "Sample Video";
};
url = {
text = "http://www.google.com";
};
},
{
postID = {
text = 43;
};
score = {
text = 30;
};
title = {
text = "sample";
};
url = {
text = "http://www.google.com";
};
}
)
Alrighty, what you want to do is the following.
From what I can gather from the link posted as well, you have a top level NSDictionary which then contains the XML inside it. There would be an object inside the NSDictionary which would, from your example, be itemDict but that, to my eyes, looks more like an NSArray.
From here, I'd store that NSArray inside another one.
Each object inside that array is an NSDictionary of keys and objects matched to them. Obviously I'm talking about this bit.
{
postID = {
text = 26;
};
score = {
text = 20;
};
title = {
text = "http://www.google.com quiz";
};
url = {
text = "http://www.google.com";
};
},
Maybe something like the following will let you dive down deep enough.
NSArray *itemArray = [xmlDictionary objectForKey:#"itemDict"];
for (NSDictionary *dict in itemArray) {
NSLog(#"Dictionary: %#", dict);
}
That code should show the output of each NSDictionary inside the NSArray. From here it is a simple case of doing whatever you want with the NSDictionary.
EDIT
Just had another look and thought I'd add this in as well.
It seems each NSDictionary we would make with the above code, then has a key for another object and that object is stored inside another dictionary. Something really weird with the XML if you ask me...
But, a work around could be the following.
NSArray *itemArray = [xmlDictionary objectForKey:#"itemDict"];
for (NSDictionary *dict in itemArray) {
NSLog(#"Dictionary: %#", dict);
for (NSDictionary *dictObject in [dict allKeys]) {
NSLog(#"Dictionary Object: %#", dictObject);
}
}
If this isn't what you're wanting to do, please edit your question so I can rectify my response.
Hope that helps!
Lets suppose you parse it and have something like this:
(
//object 0
{
postID= 26;
score = 20;
title = www.google.com
url = www.google.com
},
//object 1
{
postID= 27;
score = 10;
title = www.google.com
url = www.google.com
}...
)
This is your array.
The objectAtIndex:0 which in this example is:
{
postID= 26;
score = 20;
title = www.google.com
url = www.google.com
}
is a dictionary.