From server Class into an array Swift - swift

I want to display my data I parse from server into my view collection, so I used PFQuery as the following
func LoadData(){
let query = PFQuery(className: "AntStore")
query.findObjectsInBackground {(returned, error) -> Void in
if error != nil {
print(error!)
} else {
if let data = returned {
for object in data {
self.TitlesArray.append(object.object(forKey: "Title") as! String)
print(self.TitlesArray)
}
}
}
}
}
I can't put it in a single array to send it to the view collection variable!! Any help ?

You are printing inside the loop, move the print statement outside the loop as follows:
func LoadData(){
let query = PFQuery(className: "AntStore")
query.findObjectsInBackground {(returned, error) -> Void in
if error != nil {
print(error!)
} else {
if let data = returned {
for object in data {
self.TitlesArray.append(object.object(forKey: "Title") as! String)
}
print(self.TitlesArray) //Moved print outside the loop
}
}
}
}

Related

How do I get data out of a firebase snapshot in Swift using a function in a struct?

I'm getting data from Cloud Firestore to populate a ListView. I've managed to get the data into an array, but when I return the array, it shows up empty.
//Edit
I've implemented a completion handler, works perfectly for 'Test Code', but when called in 'func industryPosts' and passed into 'myArray', it returns nil. While 'Test Code' returns data. I'm new to completion handlers, and Swift in general. Kindly let me know what I'm missing. Thanks.
//Edit
I was not able to return the values, but calling industryPosts where I needed to use it worked!
import Foundation
import SwiftUI
class IndustryData {
var _snapshotArray : Array<Any>?
func getSnapshotArray(collectionRef: String, completionHandler: #escaping (Array<Any>?, NSError?) -> ()){
if let snapArray = self._snapshotArray {
completionHandler(snapArray, nil)
} else {
var snapArray : Array<Any> = []
db.collection(collectionRef).getDocuments { (snapshot, error) in
guard let snapshot = snapshot else {
print("Error - > \(String(describing: error))")
return
}
for document in snapshot.documents {
let item = Industry(avatar: document.get("avatar") as! String, name:document.documentID, tags: document.get("tags") as! String)
snapArray.append(item)
}
self._snapshotArray = snapArray
completionHandler(snapArray, error as NSError?)
}
}
}
}
Then calling the below function where needed
func getposts()-> [Industry] {
let data = IndustryData()
data.getSnapshotArray(collectionRef: "industry") { (snapshotArray, error) in
if snapshotArray != nil {
self.myArray = snapshotArray!
}
}
return myArray as! [Industry]
}
myArray returned Industry Array!

Is there a way to use my array of type Music, in another scope?

I'm attempting to print/dump and array of type Music outside of a function it's created in. I can successfully dump the musicItems array inside of the getMusicData function but when I set the musicItems array outside of the scope, it won't print anything. What am I doing wrong with the scope here? I have a feeling it's super simple but I just can't figure it out. Thanks in advance for taking the time to read this.
edit: It's giving me "0 elements" in the console when I attempt to dump the musicItems array in the ViewController class. Well, the function is in the same class as well so I guess I don't know what to call the first array. The parent array?
struct MusicResults: Decodable {
let results: [Music]?
}
struct Music: Decodable {
let trackName: String?
let collectionName: String?
let artworkUrl30: String?
}
class ViewController: UITableViewController, UISearchBarDelegate {
var musicItems: [Music] = []
#IBAction func musicButton(_ sender: UIBarButtonItem) {
getMusicData()
dump(musicItems)
}
Here is the function.
func getMusicData() {
var musicItems: [Music] = []
guard let searchTerm = searchString else {return}
let newString = searchTerm.replacingOccurrences(of: " ", with: "+", options: .literal, range: nil)
let jsonUrlString = "https://itunes.apple.com/search?media=music&term=\(newString)"
guard let url = URL(string: jsonUrlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { return }
do {
let music = try JSONDecoder().decode(MusicResults.self, from: data)
for results in music.results! {
// print(results.trackName!)
musicItems.append(results)
}
//dump(musicItems)
self.musicItems = musicItems
// DispatchQueue.main.async {
// self.tableView.reloadData()
// }
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}
Fixed Code
#IBAction func musicButton(_ sender: UIBarButtonItem) {
getMusicData {
music in
dump(music)
}
function:
func getMusicData(completionHandler: #escaping (_ music: [Music]) -> ()) {
...
let music = try JSONDecoder().decode(MusicResults.self, from: data)
for results in music.results! {
musicItems.append(results)
}
completionHandler(musicItems)
...
Your 'getMusicData' function is asynchronous which means that when it executes, it queues data task in a background queue and proceeds the execution and since there are no more institutions it simply returns control to its calling site - 'musicButton()' action, which in its turn executes the next instruction - prints the 'musicItems' array which might (and most likely, is) still not populated as the network call haven’t yet completed. One of the options that you have here is to pass a completion block to your 'getMusicData' function, that runs it after data task gets the results.
Another option is to use Property Observers
var musicItems: [Music] = [] {
didSet {
dump(self.musicItems)
/// This is where I would do the...
// DispatchQueue.main.async {
// self.tableView.reloadData()
// }
}
}
and then
func getMusicData() {
guard let searchTerm = searchString else { print("no search"); return }
let newString = searchTerm.replacingOccurrences(of: " ", with: "+", options: .literal, range: nil)
let jsonUrlString = "https://itunes.apple.com/search?media=music&term=\(newString)"
guard let url = URL(string: jsonUrlString) else { print("url error"); return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else { print(err ?? "unknown"); return }
do {
let music = try JSONDecoder().decode(MusicResults.self, from: data)
if let results = music.results {
self.musicItems.append(contentsOf: results)
}
} catch let jsonErr {
print("Error serializing json:", jsonErr)
}
}.resume()
}

Swift [Error]: Object not found. (Code: 101, Version: 1.12.0)

I have been trying to change the content in an array called testArray in the class Collabs and then save it back to the parse server.
#IBAction func addToArray(_ sender: AnyObject) {
var objectToSave: PFObject?
let query = PFQuery(className: "Collabs")
query.getObjectInBackground(withId: collabID) { (object, error) in
if error != nil {
print(error)
} else if let content = object {
objectToSave = content
}
if objectToSave != nil {
objectToSave!["testArray"] = ["foo","bar","foobar"]
objectToSave!.saveInBackground(block: { (success, error) in
if error != nil {
print("ERROR")
} else {
print("SUCCESS")
}
})
}
}
I've seen quite a few posts that talk about access rights however, to the best of my knowledge, the class Collabs has public read and write enabled
sorry I didnt check it that deeply before, try this
var objectToSave: PFObject?
let query = PFQuery(className: "Collabs")
query.getObjectInBackground(withId: collabID) { (object, error) in
if error != nil {
print(error)
} else {
if let content = object {
objectToSave = content
}
if objectToSave != nil {
objectToSave!["testArray"] = ["foo","bar","foobar"]
objectToSave!.saveInBackground(block: { (success, error) in
if error != nil {
print("ERROR")
} else {
print("SUCCESS")
}
})
}
}
}

Swift and Parse findObjectsInBackgroundWithBlock not returning my Array

when the compiler reach the end of findObjectsInBackgroundWithBlock my coordinatesArray loses the values and the function returns a empty array. Can you help Please?
Thank you in advance
func getSquadMembersCoordinates() -> Array<PFGeoPoint> {
var coordinatesArray:[PFGeoPoint] = [PFGeoPoint]()
if user != nil {
let userSquad = PFUser.currentUser()?["inSquad"] as? String
let query = PFUser.query()
query?.whereKey("username", notEqualTo: (PFUser.currentUser()? ["username"])!)
query?.whereKey("inSquad", equalTo: userSquad!)
query?.whereKey("visible", notEqualTo: false)
query?.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if results?.count != 0 {
if let results = results {
for object in results {
coordinatesArray.append(object.objectForKey("location") as! PFGeoPoint)
}
}
} else {
print("No Squad Members or not visible")
}
} else {
print ("\(error)")
}
}
} else {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SquadVC")
self.presentViewController(viewController, animated: true, completion: nil)
})
}
print("\(coordinatesArray.count)")
return coordinatesArray
}
Your code reaches the return line before the fetching is complete. You need something like notification that will update your data after fetching is done.

In Swift, how do you check if pointer in Parse column is empty or not

Within my user object I added a column to add a users favorite team. The column is identified as favTeam and is a pointer to a teams class
Here is my code. I have populated my user with a favorite team however the logic is always showing that "favteam nil"
if let object = PFUser.currentUser()!["favTeam"] as? [PFObject]{
print("favteam not nil")
print(object)
let favTeam = PFUser.currentUser()!["favTeam"]
favTeamText.text = favTeam["Name"] as? String
if let favTeamImageView = favTeam["teamLogo"] as? PFFile {
favTeamImageView.getDataInBackgroundWithBlock { (imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
self.teamLogo.image = UIImage(data: imageData)
}
}
}
}
}
else {
print("favteam nil")
}
I can accomplish this by using a PFUser.query() as follows...
func fetchFavoriteTeam() {
let userQuery: PFQuery = PFUser.query()!
userQuery.whereKey("username", equalTo: (currentUser?.username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var favTeam = users!
if error == nil {
if favTeam != nil {
favTeamContainer = favTeam.valueForKey("favTeam") as! PFObject
}
} else {
print(error)
}
})
}