Why is array empty after appending object to it - ios

I am working in a TableViewController that I am trying to fill up with data from a plist.
I declared this at the top:
var studentsArray:Array<StudentData>?
And now I am doing the following in a function that loads my plist:
var path = NSBundle.mainBundle().URLForResource("students", withExtension: "plist")
let tmpArray = NSArray(contentsOfURL: path!)
for studentDict in tmpArray!{
let name = studentDict["name"]as! String
let dateOfBirth = studentDict["dateOfBirth"] as! NSDate
let regular = studentDict["regular"] as! Bool
let photoFileName = studentDict["photoFileName"] as! String
let data = StudentData(name : name, dateOfBirth: dateOfBirth, regular : regular, photoFileName: photoFileName)
self.studentsArray?.append(data)
println(studentsArray!.count)
}
I tried logging the properties of the Object, they are all being filled in, but it goes wrong at the .append and somehow it just won't do that. The array's count remains 'Nil' when logged.
I'm kind of lost here! Any help is appreciated.

Doesn't look like you are initializing studentsArray anywhere. Make sure to do that. For the record, array.count should be 0 if the array is empty, not nil. If you are seeing nil that means the array is probably nil (aka you didnt initialize it).

Try changing your array declaration to this and let me know if it works. Hope it helps:
var studentsArray:Array<StudentData>? = Array<StudentData>()

Related

iOS Swift 3 - Argument labels '(of:)' do not match any available overloads Error

I'm getting the error message Argument labels '(of:)' do not match any available overloads. Below is the code I'm using.
let prefs = UserDefaults.standard
var id: String!
if var array = prefs.string(forKey: "myArray"){
if let index = array.index(of: id) {
array.remove(at: index)
prefs.setValue(array, forKey: "myArray")
}
}
I've seen a lot of answers on Stack Overflow with very similar code to that. So I'm not quite sure why this wouldn't be working.
Basically I'm just trying to remove the element in the array that = id then set that new array to the user defaults.
Update
Just updated the code above to show how array is getting defined. id is a string that is defined in a separate section.
By accessing prefs.string(forKey: "myArray"), you are getting a String, not an array of strings. You should use this:
if var prefs.array(forKey: "myArray") as? [String] { }
or
if var prefs.value(forKey: "myArray") as? [String] { }
Make sure to not forget putting as! [String], because the first method returns [Any], an which can contain objects of any type, not specifically String. Then your error should be solved, because index(of: ) can only be used on Arrays of specified types.
Hope it helps!
Just make an alt + Click on an "array" variable to make sure it is of type Array ([String]), not a String. To apply .index(of:) method it must be an array.
Like this:
String does not have a method .index(of:). That's what the error is pointing at. And sure make a cast to [String]? if it fits.

NSMutableDictionary replicates the last inserted index in each inserted index instead of insert the new index

I've been googling for a while, trying to find a solution to my problem and ended here. I'm trying to create a dictionary of dictionaries to load all the data in tableViewCells.
So I need a key for "name", another key for "description", another key for "image name" and like this..
I'm doing an async call so I've created a global var, nsDict which is a NSMutableDictionary and in the async parseJson Function I've created another NSMutableDictionary named jsonValues.
I use jsonValues to store the data inside the loop. The data is stored with keys too :
jsonValues["name"] = Name
And at the end of the loop I store jsonValues inside nsDict, my NSMutableDictionary global variable.
nsDict.setObject(jsonValues, forKey: c)
c += 1
At this point there is already somebody that knows for sure my issue and my mistake. But I've been trying and reading a lot of stackoverflow and didn't find the way to do something that easy.
My dictionary, is getting filled by all the jsonValues, but instead of inserting diferent values, it's copying all of them. Which is, in the first round of the loop, it insert the first value (dictionary of values). In the second loop, it insert the second dictionary of values in the first and in the second index...
At the end I got 43 same dictionaries. All of them are the copy of the last one...
Does anybody know why? I've spent two hours with this issue. Some help would be very appreciated, thanks!
private func parseJson(json : NSMutableArray, tableView : UITableView){
var jsonValues = NSMutableDictionary()
nsDict.removeAllObjects()
nsDict = NSMutableDictionary.init(capacity: 10)
var c : Int = 0
for j in json {
var nsData : NSMutableDictionary
//clean array
// jsonValues.removeAll()
//Create main value
guard let value = j.valueForKey("value")?.valueForKey("value")! else{
return
}
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
return
}
jsonValues["name"] = Name
title = "Address: "
//Get Address
if let Address = value.valueForKey("Address")?.valueForKey("en") as? String{
jsonValues["Address"] = Address
}
title = "Country: "
//Get country
if let country = geoposition.valueForKey("country") as? String{
let fCountry = title+country
jsonValues["Country"] = fCountry
}else{}
nsDict.setObject(jsonValues, forKey: c)
c += 1
}
doTableRefresh(tableView);
}
just move your var jsonValues = NSMutableDictionary() inside cycle
You create an NSMutableDictionary and insert it repeatedly. The object is inserted, not its contents. Therefore each entry contains the same object. You need to insert a new object at each index.

Swift realm.io can get object property using object.getValueForKey("key") but not as object.key

I am trying since a whole day migrating my localStorage data to realm.io...
Now the only issue I am facing is that I can get the object property using
object.valueforKey("key")
but not using the simpler one
object.key
Here you have a peace of my code
let realm = try! Realm()
let predicate = NSPredicate(format: "groupID = %#", group.valueForKey("groupID") as! String )
let current = realm.objects(apiGroup).filter(predicate)
let currentGroup = current[0]
print(currentGroup.valueForKey("token") as! String)
print(currentGroup.token)
When I execute that this is been printed on the console.
56abbf408cfea7941a8b30b7
fatal error: unexpectedly found nil while unwrapping an Optional value
Can you please tell me if this is the normal behaviour or if I can do something to get the
"object.key"
notation??
Thanks in advance
Thanks all for your views. I ended up creating a custom object with a custom init and passing realm object to it...
Then I looped the realm object to assign the same object properties to the custom one... example
class Images:Object{
var picid:String = ""
var path:String = ""
var timeStamp:NSDate!
override class func primaryKey() -> String{
return "picid"
}
}
class realmImages{
var picid:String!
var path:String!
var timeStamp:NSDate!
init(object:Images){
picid = object.valueForKey("picid") as! String
path = object.valueForKey("path") as! String
timeStamp = object.valueForKey("timeStamp") as! NSDate
}
}
Hang on! I think I didn't actually understand the question properly!
If the .token property is actually a member of your class, that should absolutely work. Just to confirm, are you defining your members of your Realm model subclass properly, according to the documentation?
class APIGroup: Object {
dynamic var token = ""
}
If so, and you're STILL having trouble, it may be possible that Swift wasn't able to infer that the type of the object returned from the filter wasn't your APIGroup object (Which would explain why valueForKey still works).
If that's the case, stating the type should help:
let currentGroup = current[0] as APIGroup
Let me know if that helped!

How do I get Parse data as a String out of PFUser?

I am currently trying to get a value called "loot" out of the current user. I need the value as a String, but Swift is being stubborn and says it "cannot convert Anyobject to String". The Parse documentation for iOS says to use something like:
let score = gameScore["score"] as String
and so, I try this :
let lootAmount = user["loot"] as String
BTW 'user' is referring to the current user. When I try that, it gives error saying it's not convertible. I tried placing '!'s and '?'s wherever Xcode suggested, but it just crashed the app with no error.
So, how do I get the user value called "loot" as a String?
Loot is an NSNumber not an NSString or String.
You could convert it to a String like this:
if let loot = user["loot"] as? NSNumber {
let lootString = "\(loot)"
}
If you're not sure of an object's type, you can ask it using dynamicType:
print(user["loot"]!.dynamicType)
//prints `__NSCFNumber.Type`
You may need to downcast AnyObject. Try this: let lootAmount = user["loot"] as? String or unwrap your optional user if you haven't done so:
let currentUser = PFUser.currentUser()
if let user = currentUser {
let lootAmount = user["loot"] as String
}

SWIFT access nested dictionary

I have a Dictionary that has a User object, and that User object is a dictionary that has a key "Name".
In Swift, i need to access the value for "Name".
So I did the following:
let user = question[kUserOwner] as! PFUser
let userName = user[kName] as! String
userButton.setTitle(userName, forState:UIControlState.Normal)
1) Is there really no easier/shorter way to do this?
In Objective C:
[_userButton setTitle:[[question objectForKey:kUserOwner] objectForKey:kName] forState:UIControlStateNormal];
I do realize that it is not Type safe but I can live with that, as long as I know what I am doing.
2) Is there any way i can avoid casting?
When you subscript, you get an Optional. And you cannot subscript an Optional. Therefore, while you can perhaps avoid casting, you cannot avoid unwrapping:
let dinner = ["name":"Matt"]
let douter = ["owner":dinner]
let name = douter["owner"]!["name"]
But that only works because Swift knows very specifically what douter is. It would be better, therefore, to do this in stages, as Swift expects you to do, e.g. with a nested series of if let bindings:
let dinner : AnyObject = ["name":"Matt"] as AnyObject
let douter : AnyObject = ["owner":dinner] as AnyObject
if let owner = douter["owner"] as? [NSObject:AnyObject],
let name = dinner["name"] as? String {
// do something with name
}

Resources