How to point a Json array to a local image? - swift

I'm new at this so sorry if this is basic but I'm trying to use an array in a json file and have it point to an image in my asset library but I'm running into problems. Its written as:
[
{
"image":"shrew",
},
]
Is it wrong to write it as a string? Do I need to have specific code to translate the string into my image names?
Thanks for any help you can offer!
Edit:
The error I'm getting is on line
TrackPic.image = image
"Use of unresolved identifier 'TrackPic'"
class QuizModel: NSObject {
func getQuestions() -> [Question] {
// Array of question objects
var questions:[Question] = [Question]()
// Get Json array of dictionaries
let jsonObjects:[NSDictionary] = self.getLocalJsonFile()
// Loop through each dictionary and assign values to our question objs
var index:Int
for index = 0; index < jsonObjects.count; index++ {
// Current JSON dict
let jsonDictionary:NSDictionary = jsonObjects[index]
// Create a question obj
var q:Question = Question()
let imageName = jsonDictionary["image"] as! String
let image = UIImage(named: imageName)
TrackPic.image = image
// Assign the values of each key value pair to the question object
q.image = jsonDictionary["image"] as! String
q.questionText = jsonDictionary["question"] as! String
q.answers = jsonDictionary["answers"] as! [String]
q.correctAnswerIndex = jsonDictionary["correctIndex"] as! Int
q.module = jsonDictionary["module"] as! Int
q.lesson = jsonDictionary["lesson"] as! Int
q.feedback = jsonDictionary["feedback"] as! String
// Add the question to the question array
questions.append(q)
}
// Return list of question objects
return questions
}

you first need to get the image name from the json like you did
let imageName = jsonDictionary["image"] as! String
(If you want to be certain that you are parsing your JSON correctly, be sure to write the imageName to the console)
Then you need to initialise a UIImage with UIImage(named: String) with you image name from json so
let image = UIImage(named : imageName)
Then you have your image, and you can put this on an UIImageView.
I suppose in your case, this would be
q.image = image
IF q is a UIImageView

Related

Changing UIImage image property with the image name set in a dictionary

I'm building a simple app which you click on a button and the image change randomly but I also want to add a label which describes the image so I created a dictionary contains the ["fileName":"Description"] but when I try changing the image I get an error:
"Cannot subscript a value of type '[String : String]' with an index of type 'Int'"
var randomNumber = 0
let arrayOfImages : [String:String] = ["ball1":"yes","ball2":"no","ball3":"ask again later","ball4":"the answer is yes","ball5":"i dont know"]
func rollButton() {
randomNumber = Int.random(in: 0...4)
ballImage.image = UIImage(named: arrayOfImages[randomNumber])
}
How can I change the UIImage.image using a Dictionary?
Replace
ballImage.image = UIImage(named: arrayOfImages[randomNumber])
with
ballImage.image = UIImage(named: Array(arrayOfImages.keys)[randomNumber])
As you can't subscript a dictionary it's for arrays , A good practice is to create
struct Item {
let imageName:String
let des:String
}
let arr = [Item(imageName: "ball1", des: "con1"),Item(imageName: "ball2", des: "con2"),Item(imageName: "ball3", des: "con3")]
let ran = arr[Int.random(in: 0...2)]
ballImage.image = ran.imageName
You are creating a list of [String: String], so you should access it using a key (String) and not a number (Int).
So you should correct this:
ballImage.image = UIImage(named: arrayOfImages["ball\(randomNumber)"])

Swift Create Categories for Items (Classes + Attributes) at runtime

I have a problem I am not able to figure out myself or find any answer to:
I am creating an inventar app for my company and I want that the people are able to create categories for new items like in this example:
Create category at runtime (German Inventar Program)
My problem here is that I use firebase as the backend and - of course - upload all the attributes for the stored items whereas every item belongs to a category with predefined attributes. When I want to work with these items, I download the item from firebase and create an object with these specific attributes from a class I hard-coded at compile time.
I don't want to hard code the class at compile time and change all the functions and if-else blocks where i am checking for the actual category for an item. Now - when adding a new category - I have to change at least 50 places in code to make it work...
For better understanding, here is a function for one category which downloads all the items from firebase:
func downloadMiscsFromFirebase(handler: #escaping (_ miscs: [Miscellaneous]) -> ()) {
var miscs = [Miscellaneous]()
DataService.instance.hardwareRef.child(category).observeSingleEvent(of: .value) { (snapshot) in
if let snapshots = snapshot.children.allObjects as? [DataSnapshot] {
for snap in snapshots {
let description = snap.childSnapshot(forPath: FirebaseIDs.Item.description).value as! String
let category = snap.childSnapshot(forPath: FirebaseIDs.Item.category).value as! String
let lfdNr = snap.childSnapshot(forPath: FirebaseIDs.Item.lfdNr).value as! Int
let fromTeam = snap.childSnapshot(forPath: FirebaseIDs.Item.fromTeam).value as! String
let hw = snap.childSnapshot(forPath: FirebaseIDs.Miscellaneous.hw).value as! String
let sw = snap.childSnapshot(forPath: FirebaseIDs.Miscellaneous.sw).value as! String
let other = snap.childSnapshot(forPath: FirebaseIDs.Miscellaneous.other).value as! String
let givenOut = snap.childSnapshot(forPath: FirebaseIDs.Item.givenOut).value as? Bool
let givenTo = snap.childSnapshot(forPath: FirebaseIDs.Item.givenTo).value as? String
let givenAt = snap.childSnapshot(forPath: FirebaseIDs.Item.givenAt).value as? String
let givenUntil = snap.childSnapshot(forPath: FirebaseIDs.Item.givenUntil).value as? String
let storageLocation = snap.childSnapshot(forPath: FirebaseIDs.Item.storageLocation).value as? String
let misc = Miscellaneous(UID: snap.key,
lfdNr: lfdNr,
description: description,
category: category,
fromTeam: fromTeam,
hw: hw,
sw: sw,
other: other,
givenOut: givenOut,
givenTo: givenTo,
givenAt: givenAt,
givenUntil: givenUntil,
storageLocation: storageLocation)
// Only add item if from the same team.
if fromTeam == self.fromTeam {
miscs.append(misc)
}
}
handler(miscs)
}
}
}
Thank you in advance!
I would create a general CategoryDefinition class/struct and a Category class/struct that looked something like
class CategoryDefinition {
var categoryName: String
var fields: [String: FieldType] //Dictionary with field definitions
}
class Category {
var values: [String: Any?] //Dictionary with field values
}
then two functions to convert from and to Firebase format.
To make it more flexible to work with this I would have a protocol with the properties and functions I mentioned. It would make sense to have a Factory class to generate Category instances from CategoryDefinition.
FieldType above is my made up enum since I assume you have pre-defined set of data types-

How to get some data out of an array in swift?

Here is my problem: I have an plist file, which have a simple strut:
root object is an array, and there are 2 sections in the array, each of them are dictionary including 2 pair key-value data:
and I'm going to create a tableView to show the datas, but I can't get the content out of the array :
here is how i declared my dataArray:
var plistArray = [AnyObject]()
can some one help me?
You need to properly cast at each level:
if let innerArray = plistArray[0] as? [AnyObject] {
if let dataDic = innerArray[indexPath.row] as? [String:String] {
if let imageName = dataDic["Pic"] {
cell?.imageView?.image = UIImage(named: imageName)
}
}
}
But why are you using AnyObject when you know what the plist contains? Use proper types. You know it's an array of arrays of dictionaries with String keys and String values.
var plistArray = [[[String:String]]]()
Then all you need is:
if let imageName = plistArray[0][indexPath.row]["Pic"] {
cell?.imageView?.image = UIImage(named: imageName)
}

Firebase and reading nested data using Swift

I am trying to create a simple Instagram style app using Swift and Firebase and I am running into trouble reading comments for each Image post from Firebase.
A couple questions here:
I have the Posts at the top of the tree and then the keys per image under which have data on the comments added by each user. Is it possible to use the username as the key instead of the key generated by childbyAutoId in this instance ?
How would I read the userComment and UserName and save them into an Array that I can then display in a TableView ?
Any response is much appreciated. Thanks.
var postsCommentsDict : NSMutableDictionary = NSMutableDictionary()
var userNameArray : [String] = [String]()
var userCommentArray : [String] = [String]()
FIRDatabase.database.reference().child("Posts").observeEventType(.Value, withBlock: {(Snapshot) in
if Snapshot.exists(){
let imageD = Snapshot.value
let imageD_ID = imageD.key
//Retrieving the email and image name
let imageName = imageD["userImage"] as! String
let userEmail = imageD["userEmail"] as! String
//Here you are accessing each image ID
//First Question Alternative Completed
//To answer the second Question :-
FIRDatabase.database.reference().child("Posts").child(imageD_ID).child("comments").observeEventType(.Value, withBlock: {(Snapshot) in
if let commentsDictionary = Snapshot.value {
for each in commentsDictionary{
postsCommentsDict.setObject(each["userName"] as! String , forKey : each["userComment"] as! String)
//Saving the userName : UserComment in a dictionary
userNameArray.append(each["userName"] as! String)
userCommentArray.append(each["userComment"] as! String)
//Saving the details in arrays
//Prefer dictionary over Arrays
}
} else {
//no comments to append the arrays
}
})
}
})
Once you are Done Saving the Comments dictionary : How to read it : -
for each in postsCommentsDict as! NSDictionary{
let userNm = each.key
let userComment = each.value
//username and userComment's retrieved
}
Please ignore the Typos, if any!...hope this helps..

Populating a global dictionary from a loop

I'm trying to loop through some parsed JSON from an API and build a global dictionary that can be accessed throughout the app. I'm getting an error when trying to set the dictionary item.
The global var is set as
var propListArray = [Int : [String : String]] ()
//LOOP THROUGH PROPERTIES
let itemArray = dataDictionary["properties"] as! NSArray //HAVE DATA HERE JUST FINE
var i = 0
for item in itemArray {
let propertyID = item["id"]! as! String
print(propertyID) //THIS PRINTS FINE IN CONSOLE
propListArray[i]!["propertyID"] = propertyID //THIS THROWS AN ERROR ON EXECUTION
i++
}
I want to end up with an array like this
propertyListArray[0]["propertyID"] = "16001"
propertyListArray[1]["propertyID"] = "16001"
propertyListArray[2]["propertyID"] = "16001"
propertyListArray[3]["propertyID"] = "16001"
There will be other vars per item as well such as title, etc. But just trying to get at least the one var in on each item.
Any help would be amazing!! Thank you.
propListArray is empty so trying to get the dictionary at any index will return nil, Then when you try to set a value it will cause the error.
You can fix it by creating the dictionary then assigning it to you global dictionary at the correct index.
var propListArray = [Int : [String : String]] ()
let itemArray = dataDictionary["properties"] as! NSArray
for (index, item) in itemArray.enumerate() { {
let propertyID = item["id"]! as! String
let data = ["propertyID": propertyID]
propListArray[index] = data
}
Quick fix:
var propListArray = [Int : [String : String]] ()
let itemArray = dataDictionary["properties"] as! NSArray
var i = 0
for item in itemArray {
let propertyID = item["id"]! as! String
propListArray[i] = ["propertyID": propertyID]
i++
}
However, i++ within the for loop is not idiomatic Swift. In fact, i++ and C-style for loops are going to be removed in Swift 3. It is better to use enumerate():
var propListArray = [Int : [String : String]] ()
let itemArray = dataDictionary["properties"] as! NSArray
for (i, item) in itemArray.enumerate() {
let propertyID = item["id"]! as! String
propListArray[i] = ["propertyID": propertyID]
}
propListArray[0]?["propertyID"]