How to store multiple datas in an Array in swift 4? - arrays

I am getting a JSON from an API. So, I want to store a particular value with key SKU. So, what I did was:
var skuArr = [""]
{ (response, error) in
if (error != nil)
{
print("Error \(error.debugDescription)")
}
else
{
self.coinsArr = response.arrayObject as? Array<Dictionary<String, Any>>
for i in 0 ..< (self.coinsArr?.count)!
{
self.skuArr = [response[i]["sku"].rawValue as! String]
}
}
So, with this I am getting the array in skuArr, but when i is 0 I am getting ["a"], and when i is 1 I want it to be ["a","b"], but it gives ["b"] only and when the loop ends with only the last value and not with ["a","b","c","d"] which I want as the final result. How can I insert each of them in the Array?

First of all declare skuArr as empty string array.
var skuArr = [String]()
And this is Swift. There are better ways than ugly index based loops to extract data for example with map or compactMap
if let result = response.arrayObject as? Array<Dictionary<String, Any>> {
self.coinsArr = result
self.skuArr = result.compactMap{ $0["sku"] as? String }
}
And why is coinsArr declared as optional as you are going to force unwrap it anyway? It's highly recommended to use non-optional types as much as possible. Non-optionals can never cause a well-liked unexpected found nil crash

Don't use this:
self.skuArr = [response[i]["sku"].rawValue as! String]
As this will replace the previous value with new one.
Use .append to insert into array.
self.skuArr.append([response[i]["sku"].rawValue as! String])
EDIT
change your initialisation as below:
skuArr: [String] = []

Related

Convert to "native" swift data type

I am getting some data from firestore. The problem is that they are in a format that I don't know how to use. This is the data I
receive:
"["TestKey3": <__NSArrayM 0x600002d30b10>(
ArrayElement1,
ArrayElement2,
ArrayElement3
)
, "TestKey5": 12345, "TestKey4": 1, "TestKey2": TestValue2, "TestKey1": TestValue1]
"
And this is the data type:"DataType: Dictionary<String, Any>". Dictionary seems okay normal. I can use dictionary as normal. I need to unwrap Optional and then it is okay.
5 is Int, 4 is Bool, 3 is array, 2 and 1 is string.
The problem is is the array. Even though I have have unwrapped the dictionary, I need to unwrap the array again. It is a __NSArrayM, so I can't use it as a native/swift array, which I want, like using append(). How do I convert it?
This is the script:
static func getData(collectionName: String, documentName: String) {
let docRef = db.collection(collectionName).document(documentName)
docRef.getDocument { (document, error) in
if let document = document, document.exists {
let dataDescription = document.data()
guard var output = dataDescription else {
return
}
print("Getting data at: /\(collectionName)/\(documentName)")
print("DataType: \(type(of: output))")
print(output)
} else {
print("Error getting data at: /\(collectionName)/\(documentName)")
}
}
}`
I want to use "completion: #escaping ([String: Any]?) -> Void)" on the function, so it can wait, but don't know what exactly it should be.

Fetch Core Data as comma separated list

I realise that I am missing something simple but as a Swift newbie I am going around in circles & would appreciate a pointer as to what I am doing wrong?!
I have a Core Data Entity called "Numbers" with an attribute (Int16) called "userNumbers". I am fetching the results like:
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Numbers")
//request.predicate = NSPredicate(format: "age = %#", "12")
request.returnsObjectsAsFaults = false
do {
let result = try context.fetch(request)
for data in result as! [NSManagedObject] {
print("\(data.value(forKey: "userNumbers") as! Int16)")
}
} catch {
print("Failed")
}
The result in my console is:
12
13
18
19
21
I need to know how to make this a comma separated list so I can use it in an array. Essentially I need the return to be: 12,13,18,19,21
Everything I try seems to be wrong!
First of all create a more specific fetch request to get a distinct result type
let request = NSFetchRequest<Numbers>(entityName: "Numbers")
A comma separated list is not possible because the type of userNumbers is numeric.
You can map the result to an array of Int16 with
do {
let result = try context.fetch(request) // the type is [Numbers]
let numberArray = result.map{$0.userNumbers}
print(numberArray)
}

add multiple objects to swift array in for loop

for tempExportData in exportDataArray {
let tmpRegNO:NSString = (tempExportData as AnyObject).object(forKey: kRegisteredNo) as! NSString
print("tmpRegNO is",tmpRegNO)
var tmpNoArray:Array = [String]()
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
I am trying to add string value i.e tmpRegNO to the Array tmpNoArray.
In this I can able to add only one value to the array at a time.
How to add the next value to that array when it is looping for second time.
As already mentioned you have to declare the array before entering the loop.
Your code is very objectivecish. This is a swiftier version. Don't annotate types the compiler can infer and use key subscription rather than ugly casting to AnyObject and objectForKey:.
var tmpNoArray = [String]()
for tempExportData in exportDataArray {
let tmpRegNO = tempExportData[kRegisteredNo] as! String
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
You can even write the whole expression in one line:
let tmpNoArray = exportDataArray.flatMap { $0[kRegisteredNo] as? String }
You need move the tempNoArray initialization outside of your for in loop, if not the your array will be initialized once for every item in your exportDataArray remaining only the las item as consequence
You need something like this
var tmpNoArray:Array = [String]()
for tempExportData in exportDataArray{
if let tmpRegNO = tempExportData[kRegisteredNo] as? String
{
print("tmpRegNO is",tmpRegNO)
tmpNoArray.append(tmpRegNO as String)
print("Count is",tmpNoArray.count)
print("ARRAY is",tmpNoArray)
}
}

Swift3 how do I get the value of a specific key in a string?

I've got a server response returning
(
{
agreementId = "token.virtual.4321";
city = AMSTERDAM;
displayCommonName = "bunch-of-alphanumeric";
displaySoftwareVersion = "qb2/ene/2.7.14";
houseNumber = 22;
postalCode = zip;
street = "";
}
)
how do I get the value of agreementId? response['agreementId'] is not working. i've tried some example code with .first but I cannot get it working.
Some extra information, I do a http call to a server with alamofire. I try to parse the json to a constant response:
let response = JSON as! NSDictionary
However that returns a error message
Could not cast value of type '__NSSingleObjectArrayI' (0x1083600) to 'NSDictionary' (0x108386c).
So now parse the json to an array, which seems to be working. The code above is what
let response = JSON as! NSArry
print(response)
spits out.
Now I only need to retrieve the value from the key "agreementId" and I have no clue how to do that.
In swift you need to use Swift's native type Array/[] and Dictionary/[:] instead of NSArray and NSDictionary, if you specify the type like above means more specific then the compiler won't complain. Also use optional wrapping with if let or guard let to prevent crash.
if let array = JSON as? [[String:Any]] {//Swift type array of dictionary
if let dic = array.first {
let agreementId = dic["agreementId"] as? String ?? "N/A"//Set default value instead N/A
print(agreementId)
//access the other key-value same way
}
}
Note: If you having more than one object in your array then you need to simply loop through the array to access each dictionary of array.
if let array = JSON as? [[String:Any]] {//Swift type array of dictionary
for dic in array {
let agreementId = dic["agreementId"] as? String ?? "N/A"//Set default value instead N/A
print(agreementId)
//access the other key-value same way
}
}

How to check a value is inside nested dictionary swift

I have a problem concerning my nested dictionary.
var level1Dictionary = [String : [String : String]]()
var ChosenDeckLabel = [String]
textview.text
I want to see if the dictionary contains a certain value within my, else if statement as such:
else if level1Dictionary[ChosenDeckLabel[textview.text]] != nil {
this returns error:
Cannot subscript value of type String with an index of type String!
How should I cast it to check if the nested dictionary contains the value?
Dictionaries are optionals by default because they are not sure if a key/value pair exist. Be sure to include your "!" AND "?" to wrap and unwrap your data being passed.
Arrays offer subscripting via integers and ranges as seen in Swift's API:
public subscript (index: Int) -> Element
public subscript (subRange: Range<Int>) -> ArraySlice<Element>
You're trying to subscript via a string which is throwing the error. You need to get the index of the element in the array and then use that to subscript the array to get the value: e.g.
let dictOfDicts = [String : [String : String]]()
var arrayOfStrings: [String] = ["a", "b", "c"]
let stringToCheck = "a"
dictOfDicts["a"] = ["some": "thing"]
if let index = array.indexOf(stringToCheck) {
if dictOfDicts[array[Int(index)]] != nil {
// do something
}
}
I think this is what you intend to do:
else if level1Dictionary[strIndex1][strIndex2] != nil {
When you are doing this:
level1Dictionary[ChosenDeckLabel[textview.text]]
you are trying to access the ChosenDeckLabel array using a String subscript:
ChosenDeckLabel[textview.text]
which is not a valid operation. Arrays are Int indexed and not string indexed.

Resources