How to pass data from ViewModel Layer to View Layer - ios

I don't know how to pass data from my viewModel to my view and finally show the data in the view, my view model class is:
class MainViewModel {
let sessionController: SessionController
weak var mainViewCoordinator: MainViewCoordinator?
public var fakeUsers: [User]?
init(sessionController: SessionController = SessionController()) {
self.sessionController = sessionController
}
func viewDidLoad() {
Service.instance.execute(resource: User.fake) { (result) in
print("\n result \(result)\n")
self.fakeUsers = result.value
}
}
}
I'm using Unbox Swift JSON decoder, and the printed result is is and array of User objects something like this:
([
User(id: "5851ac2615801e2348e4ea07",
birthDate: "2016-09-17T07:22:09.985Z",
msisdn: "912 065 979",
email: "rosa_bravo#yahoo.com",
profileImageUrl: "https://s3.amazonaws.com/...",
repPoints: 41607,
created: "2016-12-14T20:31:34.185Z",
displayName: "Victoria Escobedo"),
User(id: "5851ac2615801e2348e4ea09",
birthDate: "2016-05-06T11:38:23.678Z",
msisdn: "958842030",
email: "francisca_barrios#gmail.com",
profileImageUrl: "https://s3.amazonaws.com/...",
repPoints: 71408,
created: "2016-12-14T20:31:34.198Z",
displayName: "Gonzalo Rascón"),
User(id: "5851ac2615801e2348e4ea08",
birthDate: "2016-05-29T18:12:32.423Z",
msisdn: "905534639",
email: "ral0#gmail.com",
profileImageUrl: "https://s3.amazonaws.com/...",
repPoints: 24164,
created: "2016-12-14T20:31:34.195Z",
displayName: "Ramiro Dueñas"),
...
])
And I would like to pass the result to the View Layer (MainViewController) to show each User in table view cells:
class MainViewController: UIViewController, UITableViewDataSource {
#IBOutlet var tableview:UITableView!
var viewModel: MainViewModel = MainViewModel()
override func viewDidLoad() {
super.viewDidLoad()
viewModel.viewDidLoad()
self.tableview?.reloadData()
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Action", style: .plain, target: self, action: #selector(action))
}
func action() {
viewModel.userDidSelectItem(identifier: "xxxx")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.fakeUsers?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "fakeUserObjectCell") as! MainTableViewCell
cell.fakeUserObject = viewModel.fakeUsers?[(indexPath as NSIndexPath).row]
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detailSegue" {
let detailMainViewController = segue.destination as! DetailMainViewController
if let indexPath = tableview.indexPath(for: sender as! MainTableViewCell) {
detailMainViewController.id = viewModel.fakeUsers?[(indexPath as NSIndexPath).row].id
}
}
}
}
I know I have to implement self.tableview?.reloadData() to show the fakeusers but I don't know how to pass the data and finally show it.

The following Service.instance.execute() in viewModel.viewDidLoad() is a async call. It have not completed the fetching and you have call self.tableview?.reloadData() Therefore this likely resulted in 0 rows.
I would suggest to change ViewModel viewDidLoad() to a completion call
func viewDidLoad() {
Service.instance.execute(resource: User.fake) { (result) in
print("\n result \(result)\n")
self.fakeUsers = result.value
}
}
Like this:
func loadUsers(completion: () -> ()) {
Service.instance.execute(resource: User.fake) { (result) in
print("\n result \(result)\n")
self.fakeUsers = result.value
completion()
}
}
Therefore in the MainViewController, viewDidLoad, you can change the call to only reloadData() when is ready.
override func viewDidLoad() {
super.viewDidLoad()
viewModel.loadUsers {
self.tableview?.reloadData()
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Action", style: .plain, target: self, action: #selector(action))
}

Declare a public var public var fakeUsers: [User]? in MainViewModel
Update fakeUsers in MainViewModel's viewDidLoad()
No need of a fakeUsers var in MainViewController
numberOfRowsInSection in MainViewController now returns the count of fakeUsers set by MainViewModel like:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.fakeUsers?.count ?? 0
}
Similarly, for cellForRowAt indexPath:
EDIT:
The Service.instance.execute API call won't return immediately, but when it does, the data array should be updated with new content & the table requested to be refreshed.
But now the problem is that we cannot have table access in MainViewModel. So, when the Service fetch completes, we can notify MainViewController to perform a table.reloadData()
I hope you can come up with the code for this bit, you'll need to start here:
class MainViewModel {
...
func viewDidLoad() {
Service.instance.execute(resource: User.fake) { (result) in
print("\n result \(result)\n")
self.fakeUsers = result.value
// Edu, the table refresh notification is to be fired from here
}
}
}

Related

Passing Information from one view Controller to another

This my main veiw controller code where I populate table veiw with JSON data which I decoded and i have prepare for segue function that i need help with. I want to know to pass title of the movie and overview to next view controller:
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var name = [String]()
var dis = [String]()
let urls = "https://api.themoviedb.org/3/movie/top_rated?api_key=964086a2711d5d6f3fa828013fd5c3b0&language=en-US&page=1"
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "Mov", bundle: nil), forCellReuseIdentifier: "hello")
session()
// Do any additional setup after loading the view.
}
func session(){
let session = URLSession(configuration: .default, delegate: nil, delegateQueue: .main)
let url = URL(string: urls)!
let task = session.dataTask(with: url, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
if (error != nil){
print(error!)
return
}
if let safeData = data{
self.parseJSON(movieData:safeData)
}
})
task.resume()
}
func parseJSON (movieData :Data){
let decoder = JSONDecoder()
do{
let decodeData = try decoder.decode(MovieData.self, from: movieData)
for movie in decodeData.results {
self.name.append(movie.title)
self.dis.append(movie.overview)
self.tableView.reloadData()
//print(movie.overview)
self.tableView.reloadData()
}
// print("\(self.name)")
//print(self.name.count)
}catch{
print(error)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let des = segue.destination as! DetViewController
}
}
extension FirstViewController:UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print(name.count)
return name.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "hello", for: indexPath) as! Mov
cell.topLabel.text = self.name[indexPath.row]
cell.bottomLabel.text=self.dis[indexPath.row]
return cell
}
}
extension FirstViewController:UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "dhruv", sender: self)
}
}
This code below is the struct that i am using to decode my JSON data :
import UIKit
struct MovieData:Decodable {
var results : [Result]
}
struct Result:Decodable {
var title : String
var overview:String
}
And lastly I have my destination veiw controller which were I am tryong to pass my information too such as movie title and overview;
import UIKit
class DetViewController: UIViewController {
var movie : MovieData
override func viewDidLoad() {
super.viewDidLoad()
print(movie)
// Do any additional setup after loading the view.
}
}
So if would help i would appreciate it. The main purpiose for this is that at end if someone click on the cell with name of the movie i want to display the name and overveiw of the movie in to the screen . I am able to get to new view Controller when i press on one of the cell in the table view i just figure how to pass the value.
You need to declare a variable of type MovieData to hold your decoded data. Let's call it movieData and make sure you declare it at the top of your ViewController:
var movieData: MovieData?
Inside of your parseJSON() function, you want to assign the decoded data to your movieData variable.
movieData = decodeData
According to your code and your question, I'm pretty sure you are trying to pass the info about the movie selected and not the whole results array. So, if that's the case, inside DetViewController, change the type of movie to Result, since you are only interested in a specific movie.
var movie: Result
In prepareForSegue, assign the value of the selected movie to your DetViewController's movie property (and that's how you pass data to your next ViewController):
if let indexPath = tableView.indexPathForSelectedRow {
des.movie = movieData.results[indexPath.row]
}
Now inside your DetViewController, you can access title and overview as follows: movie.title and movie.overview
A piece of advice:
Instead of naming your structs MovieData and Result, consider naming them MovieArray and Movie. Instead of naming your MovieData property results, consider naming it movies.

Protocol function sends the value back to the first VC but does not set it to the variables

I am learning IOS, and I have three view controllers A, B and C, and I can access C from B and B from A, then I send back data using this delegate method from C to A then I want to use these received data in A, and finally update the text in the textView of VC A, but it always updates the textView using the default values not the received ones.
class A
protocol isAbleToReceiveData{
func pass(book: String, chapter: Int)
}
class AViewController: UIViewController, isAbleToReceiveData{
var verses: [DBTVerse] = []
var text: String = ""
var currentBook: String = "Test"
var currentChapter: Int = 1
#IBOutlet weak var TextView: UITextView!
func pass(book: String, chapter: Int) {
self.currentBook = book
self.currentChapter = chapter
print(currentBook, currentChapter)
// current output is ok "the received data"
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
getVerses(book: self.currentBook, Chapter: NSNumber(value: self.currentChapter))
print(currentBook, currentChapter)
// current output "test" "1" while it should be the received data
}
func data(verses: [DBTVerse]) {
for verse in verses{
if let chapter: Int = verse.verseId?.intValue{
text.append(String(chapter))
text.append(verse.verseText)
}
}
updateData(text: text)
}
func updateData(text: String){
if let textView = self.versesTextView {
textView.text = text
textView.setNeedsDisplay()
}
}
func getVerses(book: String, Chapter: NSNumber) {
DBT.getTextVerse(withDamId: "ARBWTCO1ET", book: book, chapter: Chapter, verseStart: nil, verseEnd: nil, success: { (verse) in
if let verse = verse {
self.verses = verse as! [DBTVerse]
self.data(verses: self.verses)
}
}) { (error) in
if let error = error {
print("Error \(error)")
}
}
}
}
class C
class CTableViewController: UITableViewController {
var currentBook: String = ""
var chapters: [DBTChapter] = []
var AVC = AViewController()
var delegate: isAbleToReceiveData?
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = AVC
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let selectedChapter = Int(chapters[indexPath.row].chapterId) {
doDismiss(book: currentBook, chapter: selectedChapter)
}
}
func doDismiss(book: String, chapter: Int) {
if let delegate = self.delegate{
delegate.pass(book: book, chapter: chapter)
}
// Use presentingViewController twice to go back two levels and call
// dismissViewController to dismiss both viewControllers.
self.presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
So in general A receives the data but it does not override it to the variable so I can use it later or in the viewWillAppear.
You have to tell to next Viewcontroller who is it delegate like so if you are in A VC ande B goes trhow a segue then add in A viewController
class AViewController: UIViewController, isAbleToReceiveData{
//all class details
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToClassB"{
let vc = segue.destination as! bViewController
vc.delegate = self
}
}
in class B then you have a new property like c with
class b: UIVIewcontroller{
var delegate: isAbleToReceiveData?
So in the func to segue to next viewController c VC add this func
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToClassC"{
let vc = segue.destination as! CTableViewController
vc.delegate = self.delegate
}
}

Get IndexPath from a UITableViewCell in a multiple sections UITableView to respond a Notification

I have a tableView with multiple sections and i want to show in a cell (via notification) the progress of a download that is being handle by Alamofire.
Right now, i already have the notification post working and passing as info, an episode object, like this:
let info = ["episode": episode, "progress": progress.fractionCompleted] as [String : Any]
NotificationCenter.default.post(name: .downloadProgress, object: nil, userInfo: info)
Each of cells have an episode object. So i want to find the IndexPath of a cell that have an episode object that matches with the episode object that is being passed from a notification.
I can't figure out how can loop through my cells to find which one have that episode and get it's indexPath so i can respond to the notification properly.
I tried to get the index of the array that is being dataSource but as the tableView has multiple sections, this is not working.
Can someone help me? Thanks
My TableViewController:
//
// EpisodesViewController.swift
// Podee
//
// Created by Vinícius Barcelos on 21/07/18.
// Copyright © 2018 Vinícius Barcelos. All rights reserved.
//
import UIKit
import RealmSwift
import Kingfisher
class EpisodesTableViewController: UITableViewController {
//MARK:- Variables
var episodes: Results<Episode> = RealmService.shared.read(object: Episode.self).sorted(byKeyPath: "pubDate", ascending: true)
let episodesCellId = "episodesCellId"
var notificationToken: NotificationToken?
var episodesDictionary = Dictionary<Date, [Episode]>()
var dateDays = [Date]()
//MARK:- Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
setupObservers()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
deinit {
self.notificationToken?.invalidate()
//NotificationCenter.default.removeObserver(self, name: NSNotification.Name.downloadProgress, object: nil)
}
//MARK:- Setup
fileprivate func setupObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(handleDownloadProgressNotification(notification:)), name: .downloadProgress, object: nil)
}
}
#objc func handleDownloadProgressNotification(notification:Notification) {
////////
}
//MARK:- Tableview methods
override func numberOfSections(in tableView: UITableView) -> Int {
return episodesDictionary.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let key = dateDays[section]
guard let datesValues = episodesDictionary[key] else {
return 0
}
return datesValues.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMMM"
return dateFormatter.string(from: dateDays[section])
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: episodesCellId, for: indexPath) as! EpisodesTableViewCell
let key = dateDays[indexPath.section]
if let podcastValues = episodesDictionary[key] {
cell.delegate = self
cell.progressBar.isHidden = true
cell.episode = podcastValues[indexPath.row]
}
return cell
}
}
Download code:
// Start download
Alamofire.request(episode.streamURL).downloadProgress { (progress) in
// Send a notification about the download progress
let info = ["episode": episode, "progress": progress.fractionCompleted] as [String : Any]
NotificationCenter.default.post(name: .downloadProgress, object: nil, userInfo: info)
//print(progress)
// Check data
}.responseData { (responseData) in ......
Modify your function of download and add the following parameters
func downloadFile(url: String,date: Date, index: Int){
let utilityQueue = DispatchQueue.global(qos: .utility)
Alamofire.download(url)
.downloadProgress(queue: utilityQueue) { progress in
let info: [String: AnyHashable] = ["date": date,
"index" : index,
"progress": progress.fractionCompleted
]
NotificationCenter.default.post(name: .downloadProgress, object: nil, userInfo: info)
}
.responseData { response in
......
}
}
In your viewcontroller, replace the function with following code:
#objc func handleDownloadProgressNotification(notification:Notification) {
var dateDays = [Date]()
guard let info = notification.userInfo,
let date = info["date"] as? Date,
let index = info["index"] as? Int,
let progress = info["progress"] as? Double,
let section = dateDays.index(where: {$0 == date})
else {return}
let indexPath = IndexPath(item: index, section: section)
}
In the download function we are passing the date and index of the row from where you started the download and you are returning it back with notification. you can also send section and row index to download function. it's mainly upto you how you want to track the row. you could've also set delegate instead of notification to track the download progress

How to print data in empty array

I'm trying to print the chat array that is declared as a empty global variable in a table. The data that I'm trying to print is received using web sockets. I'm assigning the data in the messageReceived function, and I know that the data is getting to the program because I'm printing in a label, but the moment that I'm trying to print it in the table is simple not working. All of this is in the ViewController.swift:
import UIKit
import Starscream
var messagetext: String = ""
var tabletext: String = ""
var chat = [String] ()
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
var socket = WebSocket(url: URL(string: "ws://localhost:1337/")!, protocols: ["chat"])
#IBOutlet weak var chatMessage: UILabel!
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var tableView: UITableView!
#IBAction func buttonClick(_ sender: Any) {
messagetext = textField.text!
sendMessage(messagetext)
}
override func viewDidLoad() {
super.viewDidLoad()
self.textField.delegate = self
socket.delegate = self
socket.connect()
navigationItem.hidesBackButton = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldDidEndEditing(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return (true)
}
deinit{
socket.disconnect(forceTimeout: 0)
socket.delegate = nil
}
}
// MARK: - FilePrivate
fileprivate extension ViewController {
func sendMessage(_ messager: String) {
socket.write(string: messager)
}
func messageReceived(_ message: String) {
chatMessage.text = message
chat.append(message)
}
}
// MARK: - WebSocketDelegate
extension ViewController : WebSocketDelegate {
public func websocketDidConnect(_ socket: Starscream.WebSocket) {
}
public func websocketDidDisconnect(_ socket: Starscream.WebSocket, error: NSError?) {
performSegue(withIdentifier: "websocketDisconnected", sender: self)
}
public func websocketDidReceiveMessage(_ socket: Starscream.WebSocket, text: String) {
// 1
guard let data = text.data(using: .utf16),
let jsonData = try? JSONSerialization.jsonObject(with: data),
let jsonDict = jsonData as? [String: Any],
let messageType = jsonDict["type"] as? String else {
return
}
// 2
if messageType == "message",
let messageData = jsonDict["data"] as? [String: Any],
let messageText = messageData["text"] as? String {
messageReceived(messageText)
}
}
public func websocketDidReceiveData(_ socket: Starscream.WebSocket, data: Data) {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return(chat.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.text = chat[indexPath.row] as! String
return(cell)
}
}
Assuming that you are sure about there is data to be received by your view controller, The issue would be: the tableview data source methods are called before receiving any data, which means chat data source array is still empty, thus there is no data to display.
The solution for your case is to make sure to reload the tableview after receiving data (updating the value of chat data source array), which means in your case after appending a message to chat in messageReceived method by calling reloadData() UITableView instance method:
func messageReceived(_ message: String) {
chatMessage.text = message
chat.append(message)
// here we go:
tableView.reloadData()
}
In your message received handler, issue a tableview.reloadData()
Cheers!
You need to tell the tableview that there is new data. You also need to allow for the fact that the network operation probably occurred on a background queue and UI updates must be on the main queue:
func messageReceived(_ message: String) {
DispatchQueue.main.async {
let newRow = IndexPath(row: chat.count, section:0)
chatMessage.text = message
chat.append(message)
tableView.insertRows(at:[newRow],with: .automatic)
}
}

Getting an Array From Parse into a Table View (Swift 2)

I am trying to pull an array of strings in the from "my_classes" in the "User" class in Parse. I want each individual string within the array to become a separate cell in a tableview when I tap on the search button. This is my array in "my_classes" : ["Physics","Economics","Pre Calculus"]. I want "Physics" as it's own cell, "Economics" as its own cell, etc.
import UIKit
import Parse
class CardSetClassTableViewController: UITableViewController, UISearchBarDelegate {
// MARK: Outlets
#IBOutlet var searchBar: UISearchBar!
#IBOutlet var resultsTableView: UITableView!
// MARK: Variables
var searchResults = [String]()
// MARK: Actions
#IBAction func newClassBarButtonItemPressed(sender: AnyObject) {
self.performSegueWithIdentifier("newClassSegue", sender: self)
}
// MARK: Functions
override func viewDidLoad() {
super.viewDidLoad()
self.searchBar.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func displayAlert(title: String, message: String) {
let alert = UIAlertController(title: title, message: message, preferredStyle:UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil)
}
func searchBarSearchButtonClicked(searchBar: UISearchBar)
{
if reachabilityStatus == kNOTREACHABLE {
self.displayAlert("No Internet Connection", message: "Please connect to the internet before continuing.")
} else {
searchBar.resignFirstResponder()
print("Search word = \(searchBar.text!)")
let classNameQuery = PFQuery(className:"_User")
classNameQuery.whereKey("my_classes".lowercaseString, equalTo: searchBar.text!.lowercaseString)
let query = PFQuery.orQueryWithSubqueries([classNameQuery])
query.findObjectsInBackgroundWithBlock {
(results: [PFObject]?, error: NSError?) -> Void in
if error != nil {
self.displayAlert("Error", message: error!.localizedDescription)
return
}
if let objects = results {
self.searchResults.removeAll(keepCapacity: false)
for object in objects {
let className = object.valueForKey("my_classes") as! String
self.searchResults.append(className)
}
dispatch_async(dispatch_get_main_queue()) {
self.resultsTableView.reloadData()
self.searchBar.resignFirstResponder()
}
}
}
}
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return searchResults.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = searchResults[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let classIndexPath = tableView.indexPathForSelectedRow!
let selectedCell = tableView.cellForRowAtIndexPath(classIndexPath)! as UITableViewCell
let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
spinningActivity.labelText = "Loading"
if reachabilityStatus == kNOTREACHABLE {
spinningActivity.hide(true)
self.displayAlert("No Internet Connection", message: "Please connect to the internet before continuing.")
} else {
// let className : String = String(selectedCell.textLabel!.text!)
self.performSegueWithIdentifier("addCardSet", sender: self)
}
searchBar.resignFirstResponder()
}
}
Thanks!
Try the following...
Edit
var songsArray = [String]()
func fetchUsers() {
let userQuery: PFQuery = PFUser.query()!
//search users by the sepcified username, returns a users! object
//make an array to put the values from the users! array object into
//then append those from your "middle-man" array into your destination array,
//in this example songArray is destination array and songsFromParse is "middle-man" array
userQuery.whereKey("username", equalTo: (username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var songsFromParse = users!
if error == nil {
if songsFromParse.count != 0 {
self.songsArray = (songsFromParse[i].valueForKey("CurrentSongURLArray") as! Array)
}
self.tableView.reloadData()
} else {
print(error)
}
})
}
You then take your new array that contains the objects that you retrieved, in this example songsArray and use it to populate your tableView. In cellForRowAtIndexPath ...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell ID")
cell?.textLabel?.text = songsArray[indexPath]
return cell!
}

Resources