So basically I am trying to fetch data from parse and show the data accordingly.
How do I view the information and also add information to the tableview of my items.
I have a reservedList class in parse which gives out the userid and username of the person who confirmed a list.
I am not sure how to display the items on the view controller. Everytime i try to print the usernames to the label i get a blank label. and i would like to know how to implement the UITableView to show my data –
gettting error
"Could not cast value of type '__NSArrayM' (0x103cbb8d8) to
'NSString' (0x10412fb20)." when i print out the items.
I have a reservedCust class in parse which contains the following
this it the format I would like to view the data in
var usernames = [String]()
var userids = [String]()
var times = [String]()
var items = [String]()
#IBOutlet var reserveTime: UILabel!
#IBOutlet var reserveUser: UILabel!
#IBOutlet var reservedItems: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let reserveList = PFQuery(className: "reservedList")
reserveList.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
self.usernames.removeAll(keepCapacity: true)
self.times.removeAll(keepCapacity: true)
for object in objects {
if let username = object["username"] as? String {
self.usernames.append((object["username"] as? String)!)
}
var reservedUser = object["userid"] as? String
var query = PFQuery(className: "reservedCust")
query.whereKey("userid", equalTo: reservedUser!)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
if let time = object["time"] as? String {
self.times.append((object["time"] as? String)!)
}
if let item = object["items"] {
self.items.append(object["items"] as! (String))
}
}
print(self.usernames)
print(self.times)
print(self.items)
}
})
}
}
}
// Do any additional setup after loading the view.
}
First declare two class variables.
var countOfObjects : Int! // Holds count for query objects from Parse
var allObjects : NSArray! // All queried objects from Parse
Than in your viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
getDataFromParse() // A helper method to fetch data from Parse
// Initialize for countOfObjects to 0 on viewDidLoad
countOfObjects = 0
}
func getDataFromParse() {
let query = PFQuery(className:"YourClassName")
query.findObjectsInBackgroundWithBlock { (object : [PFObject]?, error : NSError?) -> Void in
print(object!.count)
//set count Of Objects
self.countOfObjects = object?.count
// Set allObjects
self.allObjects = object
//Reload TableView after query
self.YouRTableView.reloadData()
}
}
// MARK: - TableView DataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return countOfObjects
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(YourCellIdentifier, forIndexPath: indexPath) as! YourTableViewCell
if let object = allObjects {
let currentObject = object.objectAtIndex(indexPath.row)
cell.textLabel?.text = currentObject.valueForKey("somekey") // Assign label text from parse.
}
return cell
}
Related
I did this for fetching data and showing it in a table view
but it's not showing anything.
I used this code:
import UIKit
import Parse
import Bolts
class Parsedata: UIViewController, UITableViewDelegate, UITableViewDataSource {
//#IBOutlet var NTableView: UITableView!
#IBOutlet var NTableView: UITableView!
var NArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.NTableView.delegate = self
self.NTableView.dataSource = self
// retrieve notification from parse
self.RetrieveN()
NSLog("Done with it")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func RetrieveN () {
//create a pfquery
var query:PFQuery = PFQuery(className: "Notification")
//call findobject in background
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
//clear the Narray
self.NArray = [String]()
//loop through the objects array
for Nobject in objects!{
//retrieve the text column value of each PFobject
let Ntext:String? = (Nobject as! PFObject) ["Text"] as? String
// assign it into your Narray
if Ntext != nil {
self.NArray.append(Ntext!)
}
}
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) Notifications.")}
//reload the table view
self.NTableView.reloadData()
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.NTableView.dequeueReusableCellWithIdentifier("NCell") as UITableViewCell?
cell?.textLabel?.text = self.NArray[indexPath.row]
return cell!
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return NArray.count
}
}
It's working fine because it's showing that 3 objects were retrieved on the LOG container.
Unless you have more code than what's posted here, you also need to implement numberOfSectionsInTableView and return 1
I have just learnt how to do this myself, this is how you can load data from parse and save it as a NSMutableArray then use that data to populate your table view.
let NArray : NSMutableArray = NSMutableArray()
then you can use your query you made with
var query:PFQuery = PFQuery(className: "Notification")
query.findObjectsInBackgroundWithBlock( { (AnyObject objects, NSError error) in
if error == nil {
self.NArray = NSMutableArray(array: objects!)
self.NTableView.reloadData()
} else {
print(error?.localisedDescription)
})
this will load all your content into the variable NArray, which you can then use in your tableView function with indexPath. That line of code inside your tableView cellForRowAtIndexPath would be
cell?.textLabel?.text = self.NArray[indexPath.row] //you may have to cast this as? String
Like i said this is how i am loading my data, i am using this to load PFUser usernames, profile pictures etc and displaying them in a custom table view cell.
You may have to slightly tweak these methods but the base methods are there
I am receiving a JSON file from a remote server and I can display the result in a label. The JSON data is working fine when I call function processJSONData() and the tableview works fine with a simple array. How can I incorporate both to display the result from the JSON file in the tableview? Kindly look at the code below and edit. Many thanks:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var countryLabel: UILabel!
#IBOutlet weak var capitalLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//processJSONData()
self.myTableView.registerClass(UITableViewCell.self,forCellReuseIdentifier: "cell")
self.myTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func processJSONData(){
let urlPath = "http://dubaisinan.host22.com/service1.php"
let url : NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url,completionHandler: {(data, respose, error) -> Void in
if error != nil {
println(error)
}
else {
self.abc(data)
}
})
task.resume()
}
func abc(data:NSData)
{
var parseError: NSError?
let result:AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &parseError);
if(parseError == nil){
if let dictResult = result as? NSArray{
dispatch_async(dispatch_get_main_queue()) {
self.countryLabel.text = dictResult[2]["Capital"] as? String
}
}
}
}
#IBOutlet weak var myTableView: UITableView!
var items = ["One","Two", "Three","Four"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.myTableView
.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
}
I don't see you assign your parsing result to global "items" and reload tableview with new data anywhere.
could be done here
if let dictResult = result as? NSArray{
self.items = dictResult
self.myTableView.reloadData()
///the rest of the code
}
You have to save the JSON data into a class-level variable, which you will define outside of any function, similar to how you defined "items". Assuming you have a list of countries with the capital of each, this might look like so:
var countryAndCapitalData = [(country: String, capital: String)]()
This could be improved by first defining a struct to contain your data:
struct CountryInfo
{
name: String
capital: String
init(name:String, capital:String)
{
self.name = name
self.capital = capital
}
}
which lets you define your data array as an array of CountryInfo:
var countryAndCapitalData = [CountryInfo]()
Then in your "abc" function (which I insist you rename to something like processCountryData), store the pairs of country name + capital name strings in countryAndCapitalData. For example:
countryAndCapitalData.append(CountryInfo(countryName, capitalName))
Use a For loop to loop through values in dictResult. Creating countryName and capitalName depends on the structure of your JSON, but from your example it might look like this:
for countryDictionary in dictResult[2]
{
if let countryName = countryDictionary["country"], let capitalName = countryDictionary["capital"]
{
countryAndCapitalData.append(CountryInfo(countryName, capitalName))
}
}
Then in tableView.cellForRowAtIndexPath, populate the cell label(s) with countryAndCapitalData[indexPath.row].name and countryAndCapitalData[indexPath.row].capital.
And finally, be sure to reload the table after the loop (thanks Eugene):
dispatch_async(dispatch_get_main_queue()) {
self.myTableView.reloadData()
}
Apologies for any compilation errors, as I'm typing this from a Windows machine.
You should update your items property in abc method call and then refresh the table:
func abc(data: NSData) {
// Do something with data
items = .. // processed data
}
var items: [String]? {
didSet {
NSOperationQueue.mainQueue.addOperationWithBlock {
self.tableView.reloadData()
}
}
}
This is my code in swift
class UserViewController: UITableViewController {
var userArray: [String] = []
#IBOutlet weak var friendListTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
retrieveMessages()
}
func retrieveMessages() {
var userArray: [String] = []
var query:PFQuery = PFQuery(className: "User")
var currentUser = query.whereKey("username", equalTo: PFUser.currentUser())
currentUser.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
for object in objects! {
let username:String? = (object as PFObject)["Friends"] as? String
if username != nil {
self.userArray.append(username!)
}
}
}
self.friendListTableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return userArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Update - replace as with as!
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = userArray[indexPath.row]
return cell
}
This is my user's table https://www.dropbox.com/s/6xp48v3yn0l2hje/Screen%20Shot%202015-06-03%20at%202.10.13%20PM.png?dl=0
This is my current user's friend list in Parse Relation https://www.dropbox.com/s/pd8mt8sf35u1m0v/Screen%20Shot%202015-06-03%20at%202.10.55%20PM.png?dl=0
I've saved current user's friend list with PFRelation in class "User" in column "Friends" and I want to retrieve current user's friend list to show it in tableview but The problem is I can't update tableview to show current user's friend list, It's empty and there's no user list in tableview at all.
Is my code correct for this method? If not please help me correct this code.
Thank you!
You are updating the table before you receive the list from Parse, try this:
func retrieveMessages() {
var userArray: [String] = []
var query:PFQuery = PFQuery(className: "User")
var currentUser = query.whereKey("username", equalTo: PFUser.currentUser())
currentUser.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
for object in objects! {
let username:String? = (object as PFObject)["Friends"] as? String
if username != nil {
self.userArray.append(username!)
}
}
self.friendListTableView.reloadData()
}
}
The only difference is that I move the reloadData function inside the completition block so it will happen after the data is returned from parse
You have to call reloadData from inside the findObjectsInBackgroundWithBlock block.
Right now you are calling reloadData before your data is fetched.
This is my code in swift
class UserViewController: UITableViewController {
var userArray: NSMutableArray = []
#IBOutlet weak var friendListTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
retrieveMessages()
}
func retrieveMessages() {
var query = PFUser.query()
if let username = PFUser.currentUser().username {
query.whereKey("username", equalTo: username)
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
for object in objects! {
let usernames:String? = (object as PFObject)["Friends"] as? String
println(usernames) // It prints nil
if usernames != nil {
self.userArray.addObject(usernames!)
}
}
dispatch_async(dispatch_get_main_queue()) {
self.friendListTableView.reloadData()
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return userArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Update - replace as with as!
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = userArray[indexPath.row] as? String
return cell
}
I've saved current user's friend list with PFRelation in class "User" in column "Friends", here's how I save it
class addUserViewController: UIViewController {
#IBOutlet weak var usernameTextField: UITextField!
#IBAction func addUser(sender: AnyObject) {
var query = PFUser.query()
query.whereKey("username", equalTo: usernameTextField.text)
println("Pass")
query.getFirstObjectInBackgroundWithBlock{ (object:PFObject!, error: NSError!) -> Void in
if error == nil {
let currentUser = PFUser.currentUser()
let friendList = currentUser.relationForKey("Friends")
var addFriend = object
if addFriend != nil {
friendList.addObject(addFriend)
println("added")
}
PFUser.currentUser().saveInBackgroundWithBlock{
(succeeded: Bool!, error: NSError!) in
if error != nil {
println("Error")
}
else {
println("saved")
}
}
}
}
}
and now I want to retrieve current user's friend list to show it in tableview but The problem is I can't update tableview to show current user's friend list, It's empty and there's no user list in tableview at all. Is my code correct for this method? If not please help me correct this code
here's the screenshot of my User's class table in parse
here's the screenshot of my current user's friend in parse which is save with PFRelation
Any help is appreciated, Thank you!
I haven't used Parse in a while, but if I'm not mistaken, the first query (in the first chunk of code) isn't built correctly. Should be like this:
var query:PFQuery = PFQuery(className: "User")
if let username = PFUser.currentUser().username {
query.whereKey("username", equalTo: username)
query.findObjectsInBackgroundWithBlock {....}
}
The difference here is that you query the current user's username and not the object itself. Does this help?
Change the array to NSMutableArray , and check if it appends the data.
var userArray: NSMutableArray = []
In retrieveMessages when trying to query the Parse "User" table use
var query = PFUser.query()
and then you are not passing the username as String
try
query.whereKey("username", equalTo: PFUser.currentUser().username)
I am trying to query all of the Parse users in my database and then display each individual user in their own cell in a tableview. I have set up my tableview, but I'm stuck on saving the user query to a string array that can be used within the tableview. I have created a loadParseData function that finds the objects in the background and then appends the objects queried to a string array. Unfortunately I am given an error message on the line where I append the data.
Implicit user of 'self' in closure; use 'self.' to make capture semantics explicit' This seems to me that it is suggestion that I use self. instead of usersArray. because this is within a closure, but I'm given another error if I run it that way, *classname* does not have a member named 'append'
Here is my code:
import UIKit
class SearchUsersRegistrationViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var userArray = [String]()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadParseData(){
var query : PFQuery = PFUser.query()
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if error != nil{
println("\(objects.count) users are listed")
for object in objects {
userArray.append(object.userArray as String)
}
}
}
}
let textCellIdentifier = "Cell"
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return usersArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as SearchUsersRegistrationTableViewCell
let row = indexPath.row
//cell.userImage.image = UIImage(named: usersArray[row])
//cell.usernameLabel?.text = usersArray[row]
return cell
}
}
The problem is that userArray is an NSArray. NSArray is immutable, meaning it can't be changed. Therefore it doesn't have an append function. What you want is an NSMutableArray, which can be changed and has an addObject function.
var userArray:NSMutableArray = []
func loadParseData(){
var query : PFQuery = PFUser.query()
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
self.userArray.addObject(object)
}
}
self.tableView.reloadData()
} else {
println("There was an error")
}
}
}
Also, because objects are returned as 'AnyObject' you will have to cast them as PFUsers at some point in order to use them as such. Just something to keep in mind
For getting the user's username and displaying it
// Put this in cellForRowAtIndexPath
var user = userArray[indexPath.row] as! PFUser
var username = user.username as! String
cell.usernameLabel.text = username