Append Firebase Data into [String]() in Swift - swift

I have data like below
I want to get the value of all objectIds and append it to a [String]() in Swift. Though when I use the append function, it first adds one, then two, and then three and so on. Below is the code I'm using right now.
var ObjectID: [String]?
override func viewDidLoad() {
super.viewDidLoad()
self.ObjectID = [];
let ref = Firebase(url:"https://blazing-heat-3676.firebaseio.com/results")
ref.queryOrderedByChild("objectId").queryLimitedToLast(201).observeEventType(.ChildAdded) { (snap: FDataSnapshot!) -> Void in
let objectId = snap.value["objectId"] as! String
self.ObjectID?.append(objectId)
print(self.ObjectID)
}
}
What modifications should I make for all objectIds to be in the array.

Firebase have no arrays but if the data looks like an array, Firebase clients will render it as an array. Therefore you can simply convert the result into an array and work with each individual object of this array.
let firebase = Firebase(url: "https://blazing-heat-3676.firebaseio.com/results")
firebase.observeSingleEventOfType(.Value) { (snapshot: FDataSnapshot!) -> Void in
guard let jsonArray: [JSON] = snapshot.value as? [JSON] else {
return
}
var objectIds: [String] = []
for json in jsonArray {
if let id = json["objectId"] as? String {
objectIds.append(id)
}
}
// Print result
print(objectIds)
}
Where JSON is
public typealias JSON = [String : AnyObject]

As an alternative solution - you can model this into query but you get the idea.
var myString: String = ""
ref.observeEventType(.Value, withBlock: { snapshot in
for child in snapshot.children {
let name = child.value.objectForKey("ObjectId") as! String
myString += name
}
print(myString)
})
Also, you may want to re-think your keys (node names) as numeric sequential indexes are hard to work with. You should check into childByAutoId.
Also, Firebase does support arrays via NSArray however, there are usually much better alternatives.

Related

How to work with Firebase Asynchronously? Database reading giving odd results

I have written the following function to search through my Firebase database and I have also looked into using debug statements and tested with breakpoints to see this function is pulling the correct data and it is. But when I return the array at the end, the array is empty. As far as I understand this is due to the asynchronous nature of firebase. The function is getting to the end before the data is being added to the array. How do I fix this so it can work as intended, I want to return an array of items which I can then use for other functions.
static func SearchPostsByTags(tags: [String]) -> [Post]{
var result = [Post]()
let dbref = FIRDatabase.database().reference().child("posts")
dbref.observeSingleEvent(of: .value, with: { snap in
let comps = snap.value as! [String : AnyObject]
for(_, value) in comps {
let rawTags = value["tags"] as? NSArray
let compTags = rawTags as? [String]
if compTags != nil {
for cTag in compTags! {
for tag in tags {
if (tag == cTag) {
let foundPost = Post()
foundPost.postID = value["postID"] as! String
foundPost.title = value["title"] as! String
result.append(foundPost)
}
}
}
}
}
})
return result
}
}
You are returning your array before the async call ends. You should fill your array inside the async call and call then another method, which provides the results.
static func SearchPostsByTags(tags: [String]) {
let dbref = FIRDatabase.database().reference().child("posts")
dbref.observeSingleEvent(of: .value, with: { snap in
let comps = snap.value as! [String : AnyObject]
var result = [Post]()
for(_, value) in comps {
let rawTags = value["tags"] as? NSArray
let compTags = rawTags as? [String]
if compTags != nil {
for cTag in compTags! {
for tag in tags {
if (tag == cTag) {
let foundPost = Post()
foundPost.postID = value["postID"] as! String
foundPost.title = value["title"] as! String
result.append(foundPost)
}
}
}
}
}
// Call some func to deliver the finished result array
// You can also work with completion handlers - if you want to try have a look at callbacks / completion handler section of apples documentation
provideTheFinishedArr(result)
})
}

Retrieving data from Firebase with Swift 3.0 from a random child path

I'm trying to retrieve an array of items from a directory with a random folder using an existing array of strings as reference
My data looks like this:
Items
- RandomID
-title : "text"
-subtitle: "text"
So far this is what I have tried, but it isn't working:
var array = [String]() //array to use as reference
var returnedItems = [Item]() //array of item objects
func retrieveData()
{
for i in array
{
let ref = main.child("Items")
let query = ref.queryEqual(toValue: i)
query.observeSingleEvent(of: .value, with: { (snapshot) in
let item = Item!
if snapshot.hasChild("title")
{
item.title = (snapshot.value as! NSDictionary)["title"] as? String
}
if snapshot.hasChild("subtitle")
{
item.subtitle = (snapshot.value as! NSDictionary)["subtitle"] as? String
}
returnedItems.append(item)
self.tableView.reloadData()
print("Item: \(self.returnedItems.map { $0.title})")
})
}
}
Any help will be greatly appreciated!
Thanks in advance ;)
If you're trying to retrieve all children, you can just use a single listener (modeled after this example in the documentation):
var array = [String]() //array to use as reference
var returnedItems = [Item]() //array of item objects
func retrieveData() {
query.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let item = Item!
if child.hasChild("title") {
item.title = (snapshot.value as! NSDictionary)["title"] as? String
}
if child.hasChild("subtitle") {
item.subtitle = (snapshot.value as! NSDictionary)["subtitle"] as? String
}
returnedItems.append(item)
self.tableView.reloadData()
print("Item: \(self.returnedItems.map { $0.title})")
})
}
// returnedItems will still be empty here, since the data hasn't
// been loaded yet. See the note after this code snippet.
}
But note that reading the data will still happen asynchronously here, so returnedItems will still be empty when retrieveData returns.

Problems Retrieving Data from Firebase in Swift 3

I'm trying to retrieve data from firebase, store it in an array which will then be used as a reference for another firebase query. Unfortunately, I can't seem to get it to work properly. The print function at the bottom is always empty. I have tried to call each successive function after the for loops, but I'm probably doing it wrong.
I have 2 branches in firebase that looks a bit like this:
-id
|
Group1
|
ID01: Created on 01.01.16
-idDetails
|
ID01
//name: name01
//description: description01
This is my code:
var array = [String]()
var id = [String]()
var items = [Item]() //Item Class Array
override func viewDidLoad() {
super.viewDidLoad()
getIdFromFirebase()
}
//first task
func getIdFromFirebase(){
for index in array //index is being used as part of path query
{
FireDbase_Main.child("Group1").child("id").child(index).observe(FIRDataEventType.childAdded, with: { (snapshot) in
self.id = (snapshot.key)
id.append(id)
})
getDataForItems()
}
}
//second task
func getDataForItems() {
let newItem = Item()
for index in id //i is being used as part of path query
{
FireDbase_Main.child("idDetails").child(index).observeSingleEvent(of: .value, with: { (snapshot) in
newItem.itemID = snapshot.key
newItem.name = (snapshot.value as! NSDictionary)["name"] as! String
newItem.desc = (snapshot.value as! NSDictionary)["description"] as! String
self.items.append(newItem)
}
printItemsArray(
}
//3rd Task: For now I have put a print here just as a placeholder task.
func printItemsArray(){
print(items.map {$0.itemID})
print(items.map {$0.name})
print(items.map {$0.desc})
}

converting AnyObject to Array list of Strings in swift

I'm new to swift and i'm extracting data from Parse database.
The data column is stored as array in the database
i managed to extract it as AnyObject and now i want to display each item. AnyObject is displaying as 1 entry instead of array list
class PeopleTable: UITableViewController {
//let textCellIdentifier = "TextCell"
//var window: UIWindow?
//let emptyArray: [AnyObject] = []
var userFriends: [AnyObject] = []
override func viewDidLoad() {
super.viewDidLoad()
queryForTable()
print(userFriends)
}
func queryForTable() {
let relationQuery = PFQuery(className:"User_info")
relationQuery.whereKey("userID", equalTo:"id123")
var userfrnds = try? relationQuery.findObjects()
for eachFriend in userfrnds! {
self.userFriends.append(eachFriend["friends"])
}
}
print(userFriends) command Out Put :
[(
Rudzani,
Terrence,
Thendelano,
"Big-T",
Smallboy
)]
i want the out put to be :
Rudzani,
Terrence,
Thendelano,
"Big-T",
Smallboy
How do i convert AnyObject to Array list of Strings
userFriends is an array in an array, the printed output is of type [[String]].
var userFriends = []
Then get the inner array
let users = userFriends[0]
and join the items
let users = userFriends[0].joinWithSeparator(", ")
As the type is distinct, any further type casting is not needed.
Edit: You have probably to cast the type after retrieving the object
do {
let userfrnds = try relationQuery.findObjects()
for eachFriend in userfrnds {
self.userFriends.append(eachFriend["friends"] as! [String])
}
} catch let error as NSError {
print(error)
}

Swift: Unable to get array values from singleton class

Hi I retrived value from JSON and stored in NSMutableArray. I have tried this like Singleton. I have used empty swift file for this. Datas successfully retrieved and stored in NSMutableArray which is already declared in mainViewController. Then, if I use that NSMutableArray value in mainViewController, it shows empty array.
My coding is below. Kindly guide me.
Empty Swift File
public class json_file{
var prod_Obj = product_mainVC()
class var shared: json_file
{
struct Static
{
static let instance: json_file = json_file()
}
return Static.instance
}
func dataFromJSON()
{
let url = NSURL(string: "http://........--...4900a20659")!
var data : NSData = NSData(contentsOfURL: url, options: NSDataReadingOptions.DataReadingMapped, error: nil)!
var dict: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
let dataArray = dict["data"] as [[String:AnyObject]] // The array of dictionaries
for object in dataArray {
let category_name = object["category_name"] as String
prod_Obj.ct_name_arr.addObject(category_name)
let category_child = object["category_child"] as [[String:AnyObject]]
for child in category_child {
let sub_category_name = child["sub_category_name"] as String
prod_Obj.sub_ct_name_arr.addObject(sub_category_name)
}
}
println(prod_Obj.ct_name_arr) //Here value is Getting
println(prod_Obj.sub_ct_name_arr) //Here value is Getting
}
}
viewDidLoad
{
json_file.shared.dataFromJSON()
println(ct_name_arr) //Prints Empty Array [Intially Declared as NSMutableArray]
println(sub_ct_name_arr) //Prints Empty Array [Intially Declared as NSMutableArray]
}
I was trying understand the problem, but I can't see the product_mainVC. Because this I remake your class with little modifications.
class JsonFile
{
private(set) var categoryNames:[String];
private(set) var subCategoryNames:[String];
class let shared:JsonFile = JsonFile();
private init()
{
self.categoryNames = [];
self.subCategoryNames = [];
}
func dataFromJson()
{
let url = NSURL(string: "http://........--...4900a20659")!
if let data : NSData = NSData(contentsOfURL: url, options: NSDataReadingOptions.DataReadingMapped, error: nil)
{
if let dict: NSDictionary! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary
{
if let dataArray = dict["data"] as? [[String:AnyObject]] // The array of dictionaries
{
for object in dataArray {
let category_id = object["category_id"] as Int
let category_name = object["category_name"] as String
categoryNames.append(category_name);
let category_child = object["category_child"] as [[String:AnyObject]]
for child in category_child {
let sub_category_id = child["sub_category_id"] as Int
let sub_category_name = child["sub_category_name"] as String
subCategoryNames.append(sub_category_name);
}
}
}
}
}
println(categoryNames);
println(subCategoryNames);
}
}
I did
Modify your way to do Singleton to a safe and more simple mode, create the arrays categoryNames and subCategoryNames internal in class because this is better to manipulate, and protect your fetch data to safe from possibles crash.
Implementation
JsonFile.shared.dataFromJson();
println("count categoryNames");
println(JsonFile.shared.categoryNames.count);
println("count subCategoryNames");
println(JsonFile.shared.subCategoryNames.count);
You need think about
This code is sync, and because this if you have a big data or request slow, the main thread from your application will freeze waiting return and it is bad for your user. Think if is necessary be sync.
let category_id = object["category_id"] as Int is never used. Why do you stay with this in code?