Swift how can I make dictionary array? - arrays

object-C style
#interface TestViewController:UIViewController{
NSArray *dataList;
}
#end
#implementation TestViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSDictionary *dict1 =[[NSDictionary alloc] initWithObjectsAndKeys:#"32",#"age",#"andy",#"name", nil];
NSDictionary *dict1 =[[NSDictionary alloc] initWithObjectsAndKeys:#"34",#"age",#"smith",#"name", nil];
NSDictionary *dict1 =[[NSDictionary alloc] initWithObjectsAndKeys:#"27",#"age",#"jonathan",#"name", nil];
dataList = [[NSArray alloc]initWithObjects:dict1,dict2,dict3,nil];
}
#end
I want to make same code in Swift
so I typed swift style as follows
class ViewController: UIViewController {
var datalist = [Dictionary]() //Compile Error -> "Missing argument for parameter #1 in call"
// I can't understand error. What does it mean?
override func viewDidLoad() {
super.viewDidLoad()
let dict1 = ["age":"32","name":"andy"]
let dict2 = ["age":"34","name":"smith"]
let dict3 = ["age":"27","name":"jonathan"]
datalist = [dict1,dict2,dict3] //Compile Error -> 'ViewController' does not have a member named 'datalist'
}
}
but 2 Error
I don't know why issue error
Can you help me?

Arrays in swift do not take a parameter, you just create one by setting the array equal to [] (with or without values), for example:
var array : [Int] = []
var array2 = [1,2,3]
would create an array of integers.
Also, Dictionaries in swift need to know the types of the key and value, for example:
Dictionary<String, String>
But there is also a shorthand for creating dictionaries that looks like:
[String:String]
(Assuming String is the type for your key and value).
So for your example, you could rewrite your datalist object to be declared as:
var datalist : [[String:String]] = []
Then you can use the datalist object in the way you are using it, or by appending [String:String] objects to it.

Related

How to add a double dictionary to an Array using typeAlias in Swift 5

I use a typeALias to create a 'Double Dictionary' see code.
This dictionary I have to put this in an Array.
Why can't I use "typealias dataPersDict = [[String: Int],[String: Int]]". A comma instead of a semicolon?
typealias dataPersDict = [[String: Int],[String: Int]]
// type(of: dataPersDict())
let emplArr = [["emp_id": 1000]:["mgr_id":100]]
var dataArray = [dataPersDict]()
dataArray.append(emplArr) // works
dataArray.append([["emp_id": 1001]:[ "mgr_id": 100]]) // fine
dataArray.append([["emp_id": 1001],[ "mgr_id": 100]]) // error

Copy array of NSManagedObject objects in Swift 4

I have an array of NSManagedObject's and I want to copy them to a new array in order to manipulate them and not save the changes after the user is done.
The array:
var origQuestions: [Questions]?
This is how I retreive the data from CoreData:
self.origQuestions = MainDb.sharedInstance.randomQuestions(entity: "Questions", count: self.questionToShow)
This is what I need in Objective-C, but I want to know how to do so in Swift 4:
NSMutableArray *questionsCopy = [[NSMutableArray alloc] initWithArray:self.origQuestions copyItems:YES];
To translate that Objective-C code into Swift you do:
var questionsCopy = NSArray(array: origQuestions, copyItems:true) as! [Questions]
But since you declared origQuestions as optional, it needs to be:
var questionsCopy = origQuestions != nil ? NSArray(array: origQuestions!, copyItems:true) as? [Questions] : nil
Whether that fully works (Objective-C or Swift) with NSManagedObject or not is another question. See How can I duplicate, or copy a Core Data Managed Object? and its Swift answers for code that specifically covers doing deep copies of NSManagedObject instances.

cast dictionary elements of different types

I am using such code to get JSON from server:
var jsonresult = NSArray()
do {
jsonresult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSArray
}
It helps me to get an array of dictionaries in jsonresult variable.
Then I am looping through array to add all dictionaries to another array.
for i in jsonresult {
print(i)
self.otherArray.append(i as! Dictionary<String, AnyObject>)
}
I am using Dictionary type because there are strings values as well as Double values.
Problem is that after data is inserted I can not use "double" values. I get such error: Could not cast value of type 'NSTaggedPointerString' (0x10c472860) to 'NSNumber'
Yes, I know that I can use (value as! NSString).doubleValue but it would be better to cast NSTaggedPointerString into NSNumber in the begining.
Any ideas how can I do it? Maybe I can cast each element of dictionary while adding them to self.otherArray?

PFObject Array Sort

I'm using Parse and I have an array of PFObjects called "scorecardData". Each PFObject has a "score" property that is of type Int. I'm trying to sort my array by "score" but I'm getting the following error: "Binary operator '<' cannot be applied to two 'AnyObject?' operands". I'm not sure what I'm doing wrong here. I also tried down casting the objectForKey("score") as! Int but its not letting me do this. Any suggestions? Thanks in advance.
var scorecardData = [PFObject]()
scorecardData.sortInPlace({$0.objectForKey("score") < $1.objectForKey("score")})
You declared scorecardData variable as Array of PFObject. Why are you trying access PFObject property using objectForKey: reserved? Anyway I am not parse expert. But if you declared your array as [PFObject] you can use:
scorecardData.sortInPlace({$0.score < $1.score})
But this won't work unless you subclass PFObject for a more native object-oriented class structure. If you do that remember also to specify:
var scorecardData = [YOUR_NEW_CLASS]()
I strongly recommend subclassing PFObject to make use of all swift type-safe goodies.
But if you want to keep your data structure you can use:
scorecardData.sortInPlace({($0["score"] as! Int) < ($1["score"] as! Int)})
Keep in mind that it's dangerous, and in future avoid it.
If you want to Sort your array of PFOject... You can do this
extension Array where Element:PFObject {
func sort() -> [PFObject] {
return sort { (first, second) -> Bool in
let firstDate = first.objectForKey("time") as! NSDate//objectForKey(Constants.Parse.Fields.User.fullName) as? String
let secondDate = second.objectForKey("time") as! NSDate//objectForKey(Constants.Parse.Fields.User.fullName) as? String
return firstDate.compare(secondDate) == .OrderedAscending
}
}
}
Have you tried doing this?
var query = PFQuery(className:"ScoreCard")
// Sorts the results in ascending order by the score field
query.orderByDescending("score")
query.findObjectsInBackgroundWithBlock {

Converting Swift Array to NSData for NSUserDefaults.StandardUserDefaults persistent storage

I'm trying to get my head around Swift (after being relatively competent with Obj-C) by making a small app. I would like to use NSUserDefaults to persistently save a small amount of data but I am having problems.
I initialise an empty array of tuples like this:
var costCategoryArray: [(name:String, defaultValue:Int, thisMonthsEstimate:Int, sumOfThisMonthsActuals:Int, riskFactor:Float, monthlyAverage:Float)]=[]
When the array has an entry, I want to save the array to NSUserDefaults with standard Swift code such as this:
NSUserDefaults.standardUserDefaults().setObject(costCategoryArray, forKey: "financialData")
NSUserDefaults.standardUserDefaults().synchronize()
I get an error saying that the tuple array doesn't conform to the AnyObject class. So I tried to turn it into NSData:
var myNSData: NSData = NSKeyedArchiver.archivedDataWithRootObject(costCategoryArray)
var myUnarchivedData: Array = NSKeyedUnarchiver.unarchiveObjectWithData(myNSData)
...but I get the same error during the conversion to NSData. The object being held by my array doesn't conform to AnyObject. I've also tried at each stage to make it immutable by using:
let immutableArray = costCategoryArray
Ive also tried creating a class instead of using tuples which I understood would make it comply with AnyObject:
class costCategory : NSObject {
var name : String
var defaultValue : Int
var thisMonthsEstimate : Int
var sumOfThisMonthsActuals : Int
var riskFactor : Float
var monthlyAverage : Float
init (name:String, defaultValue:Int, thisMonthsEstimate:Int, sumOfThisMonthsActuals:Int, riskFactor:Float, monthlyAverage:Float) {
self.name = name
self.defaultValue = defaultValue
self.thisMonthsEstimate = thisMonthsEstimate
self.sumOfThisMonthsActuals = sumOfThisMonthsActuals
self.riskFactor = riskFactor
self.monthlyAverage = monthlyAverage
}
}
But the new error is:
"Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType')"
What is the problem with an array of tuples? Why can't I store an array of class objects? I feel like I need some expert advice as so far everything I try to do with Swift is pretty much incompatible...
Thanks!
Anything you are archiving to NSData and back needs to implement the NSCoding protocol. I found that in addition, my Swift class had to extend NSObject. Here is a quick example of a Swift class that encodes and decodes:
class B : NSObject, NSCoding {
var str : String = "test"
required init(coder aDecoder: NSCoder) {
str = aDecoder.decodeObjectForKey("str") as String
}
override init() {
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(str, forKey: "str")
}
}
// create an Object of Class B
var b : B = B()
// Archive it to NSData
var data : NSData = NSKeyedArchiver.archivedDataWithRootObject(b)
// Create a new object of Class B from the data
var b2 : B = NSKeyedUnarchiver.unarchiveObjectWithData(data) as B
value of "financialData" should be in quotes:
NSUserDefaults.standardUserDefaults().setObject("costCategoryArray", forKey: "financialData")
NSUserDefaults.standardUserDefaults().synchronize()

Resources