How to get a value from a complicated dictionary? - swift

An API returns this response below but I don't know how to parse it.
Response JSON
[
"results": [
[
"address": "mgG2W14th6TXYWXNDrZ24shsJ2wYhJm2b3",
"total": [
"balance": 0,
"received": 0,
"sent": 0
],
"confirmed": [
"balance": 0,
"received": 0,
"sent": 0
]
]
]
]
Swift Code
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.chain!.getAddress(address!) { dictionary, error in
NSLog("%#", dictionary)
}
Dictionary Object
(lldb) po dictionary
[results: (
{
address = mgG2W14th6TXYWXNDrZ24shsJ2wYhJm2b3;
confirmed = {
balance = 0;
received = 0;
sent = 0;
};
total = {
balance = 0;
received = 0;
sent = 0;
};
}
)]
I tried it many times... Can you share how to fix it please..
(lldb) po dictionary["results"]![0]
{
address = mgG2W14th6TXYWXNDrZ24shsJ2wYhJm2b3;
confirmed = {
balance = 0;
received = 0;
sent = 0;
};
total = {
balance = 0;
received = 0;
sent = 0;
};
}
po dictionary["results"]![0]!["address"]
error: <EXPR>:1:28: error: cannot subscript a value of type 'AnyObject' with an index of type 'String'
dictionary["results"]![0]!["address"]
I got "Could not find member 'subscript'" at "let address = ..." line.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.chain!.getAddress(address!) { dictionary, error in
NSLog("%#", dictionary)
let address = dictionary["results"]![0]["address"]!
print("address: \(address)")
}

if let myDictionary = dictionary as? [String:AnyObject] {
if let results = myDictionary["results"] as? [AnyObject] {
if let firstItem = results[0] as? [String: AnyObject] {
if let address = firstItem["address"] as? String {
print(address)
}
if let total = firstItem["total"] as? [String:Int] {
if let balance = total["balance"] {
print(balance)
}
if let received = total["received"] {
print(received)
}
if let sent = total["sent"] {
print(sent)
}
}
if let confirmed = firstItem["confirmed"] as? [String:Int] {
if let balance = confirmed["balance"] {
print(balance)
}
if let received = confirmed["received"] {
print(received)
}
if let sent = confirmed["sent"] {
print(sent)
}
}
}
}
}
In order to simplify things you can create a class which will be managing such parsing if the data returned always has the same format.

Related

CoreData batch insert Entities with Relationship

Is there anyway to insert entities with relationship? I get error "Illegal attempt to establish a relationship 'content' between objects in different contexts"
addUsers(users: [userData])
func addUsers(users: [User]) {
let taskContext = container.viewContext
taskContext.perform {
let batchInsertRequest = self.newBatchInsertRequest(with: users)
if let fetchResult = try? taskContext.execute(batchInsertRequest),
let batchInsertResult = fetchResult as? NSBatchInsertResult,
let success = batchInsertResult.result as? Bool, success {
return
}
}
}
crash happens in below code
private func newBatchInsertRequest(with users: [Users]) -> NSBatchInsertRequest {
var index = 0
let total = message.count
let batchInsertRequest = NSBatchInsertRequest(entity: WaUser.entity(), managedObjectHandler: { managedObject in
guard index < total else { return true }
let user = users[index]
if let waUser = managedObject as? WaUser {
waUser.name = user.name
let waUserInfo = waUserInfo(context: self.container.viewContext)
waUserInfo.pass = "12345"
waUserInfo.key = "asdfgh"
waUser.info = waUserInfo **//crash occurs here**
}
index += 1
return false
})
return batchInsertRequest
}

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

How to save nested data to the Firestore?

I'm new here. An error occurs while writing the nested data to the Firestore. This is my data structure:
struct CartArray: Codable {
var num:Int
var name:String
var price:Double
init (num: Int,name: String,price: Double)
{ self.num = num
self.name = name
self.price = price
}
this is the data recording function:
let db = Firestore.firestore()
var arrayCart: [CartArray] = []
#IBAction func buttonCheckout(_ sender: Any) {
saveData()
}
...
func saveData () {
let menuItems = [arrayCart]
var list_menuItem = [Any]()
for item in menuItems {
do {
let jsonData = try JSONEncoder().encode(item)
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
list_menuItem.append(jsonObject)
}
catch {
// handle error
}
}
print(list_menuItem)
let parameters = [
"address": userAddress as Any,
"datetime": Timestamp(date: Date()),
"status": "Заказано",
"user_phone": userPhone as Any,
"username": userName as Any,
"total":cart.total,
"order":list_menuItem
]
db.collection("orders").document().setData(parameters)
{ err in
if let e = err {
print("$-- error save data \(e)")
} else {
print("success!")
}
}
}
this is the converting json of array:
[<__NSArrayI 0x600001f97880>( { name = "\U041f\U0438\U0440\U043e\U0436\U043a\U0438 \U0441 \U043c\U044f\U0441\U043e\U043c"; num = 3; price = 40; },
{ name = "\U041f\U0438\U0446\U0446\U0430 \U0421\U0442\U0430\U043d\U0434\U0430\U0440\U0442"; num = 1; price = 500; } ) ]
When saving occurs in the 'order' field, an 'Nested arrays are not supported' error occurs. Why?
The problem is that in the saveData() you are creating an array of arrays of CartArray.
Replace: let menuItems = [arrayCart]
with: let menuItems = arrayCart

Swift dictionary retrieve values

Hello I am using the linked in SDK to log into my app.
The API returns a json string which i have converted to a dictionary object.
Using the line below I can successfully retrieve some of the values.
let firstName : NSString? = dict?["firstName"] as? NSString
How would I retrieve the company name and the job title?
["publicProfileUrl": https://www.linkedin.com/in/joebloggs, "formattedName": Joe Bloggs, "id": Zazobgtf1Q, "pictureUrls": {
"_total" = 1;
values = (
"https://media.licdn.com/mpr/mprx/0_xBXVf6v56zJf42DuUQJy70N69gfspmi8VYJMYZq_Q6X8SCm_a-4jUmz6FF4wOai_xjJMpPN_qiNQ7xaiUpvv4jq5_iN67xx8apv4S6HL9JLf7HadaZ5JIuNzlJ"
);
}, "pictureUrl": https://media.licdn.com/mpr/mprx/0_OzOPtLSS9GH8gFDYUA6-xtfSKPkgY5YmNkEPBAGSc5ypRvS_AzXjVcuSNssssXO_qkE1Mi_DxXcyZT2mBQR7sAa3VXcjZTdGlQRKlrR2ALGltB-YjcSOAkzjslDDATY14Lxx9mjGA2G, "lastName": Bloggs, "emailAddress": joe#gmail.com, "positions": {
"_total" = 1;
values = (
{
company = {
id = 9433004;
industry = "Marketing & Advertising";
name = "Company Name";
size = "2-10";
type = "Privately Held";
};
id = 865817330;
isCurrent = 1;
location = {
country = {
code = gb;
name = "United Kingdom";
};
name = "Leeds, United Kingdom";
};
startDate = {
month = 9;
year = 2016;
};
title = "Staff";
}
);
}, "firstName": Joe]
Here is the code I am using for the linkedIn login:
func linkedInLogin(){
LISDKSessionManager.createSession(withAuth: [LISDK_BASIC_PROFILE_PERMISSION, LISDK_EMAILADDRESS_PERMISSION], state: nil, showGoToAppStoreDialog: true, successBlock: { (returnState) -> Void in
print("success called!")
let session = LISDKSessionManager.sharedInstance().session
//let url = "https://api.linkedin.com/v1/people/~"
let url = "https://api.linkedin.com/v1/people/~:(id,summary,positions,email-address,first-name,last-name,public-profile-url,formatted-name,picture-url,picture-urls::(original))?format=json"
if LISDKSessionManager.hasValidSession() {
LISDKAPIHelper.sharedInstance().getRequest(url, success: { (response) -> Void in
// print(response!.data!)
let str = response!.data!
let dict = self.convertToDictionary(text: str)
print(dict!)
let firstName : NSString? = dict?["firstName"] as? NSString
let lastName : NSString? = dict?["lastName"] as? NSString
let email : NSString? = dict?["emailAddress"] as? NSString
let userName : NSString? = dict?["formattedName"] as? NSString
let linkedInID : NSString? = dict?["id"] as? NSString
let link : NSString? = dict?["publicProfileUrl"] as? NSString
let liid : NSString? = dict?["id"] as? NSString
let picurl : NSString? = dict?["pictureUrl"] as? NSString
// let summary : NSString? = dict?["summary"] as? NSString
let positions : NSString? = dict?["positions"] as? NSString
}, error: { (error) -> Void in
print(error!)
})
}
}) { (error) -> Void in
print("Error: \(error)")
}
}
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}

realmOC can't update data

addobject is success. but i want to update data. After realm.beginWriteTransaction() executes, breakpoint can't continue execute backup.quanId = 5, it's like just jump over.
class YQQuanBackup: RLMObject {
dynamic var groupId:Int = 0
dynamic var quanId:Int = 0
dynamic var content:String = ""
}
GCDBlock.async(.Default) {
let results:RLMResults = YQQuanBackup.objectsWhere("groupId == %d", self.groupInfo!.groupId)
let quanBackup = results.firstObject() as? YQQuanBackup
guard let backup = quanBackup else { return }
let realm = RLMRealm.defaultRealm()
realm.beginWriteTransaction()
backup.quanId = 5
backup.content = YQRichTextUtil.richTextToPublishText(self.textView.attributedText, uploadedImageUrls: self.uploadedImageUrls)
do {
try realm.commitWriteTransaction()
} catch {
print(error)
}
}