Data retrieval using Parse in Swift 2 - ios

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

Related

How do I manipulate the parse data accordingly?

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
}

Swift: Trying to displaying only the users data in one page

I've created a profile page to display all of the users blog post. In my viewController I've used a PFQueryTableViewControllerto query the users blogs. The problem I'm having is when I run my app to see the current users blogs, I see the current users post first in the order it was created, then under I see everyone else's blogs that is coming from the className I created in Parse. The post are also repeating when I'm on this page. Is there something I need to do in my code to only show the current signed in users blogs instead of all of the post from Parse? I've pasted my code below to get a better idea.
import UIKit
import Parse
import ParseUI
class ProfileVC: PFQueryTableViewController {
var profilePage:NSMutableArray! = NSMutableArray()
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.parseClassName = "BlogPost"
self.textKey = "blogging"
self.pullToRefreshEnabled = true
self.objectsPerPage = 200
}
override func viewDidLoad() {
super.viewDidLoad()
let user = PFObject(className:"BlogPost")
user["writer"] = PFUser.currentUser()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func objectsDidLoad(error: NSError?) {
super.objectsDidLoad(error)
profilePage = NSMutableArray(array: objects!)
self.tableView.reloadData()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let query = PFQuery(className: "BlogPost")
if let user = PFUser.currentUser() {
query.whereKey("writer", equalTo: PFUser.currentUser()!.username!)
query.addAscendingOrder("createdAt")
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil{
for object in objects!{
let blog : PFObject = object as! PFObject
self.profilePage.addObject(blog)
}
let array : NSArray = self.profilePage.reverseObjectEnumerator().allObjects
self.profilePage = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
}
}
// MARK: - Table view data source
override func objectAtIndexPath(indexPath: NSIndexPath!) -> PFObject? {
var obj : PFObject? = nil
if(indexPath.row < self.profilePage.count){
obj = self.profilePage[indexPath.row] as? PFObject
}
return obj
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return profilePage.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 110
}
else {
return 90
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath?) -> PFTableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("PCell", forIndexPath: indexPath!) as! ProfileCell
if let object : PFObject = self.profilePage.objectAtIndex(indexPath!.row) as? PFObject {
cell.WritersName.text = object["writer"] as? String
cell.WritersBlog.text = object["Blog"] as? String
let dateCreated = object.createdAt! as NSDate
let date = NSDateFormatter()
dateFormat.dateFormat = "h:mm a"
cell.timeProfile.text = NSString(format: "%#", date.stringFromDate(dateCreated)) as String
}
return cell
}
// }
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
}
I can see a couple of potential problems with your code.
First, you are adding to the same array every time you perform a query.
If you initialize your array at the time you perform the query, the array will be limited to the current query's results and will not include results from previous fetches.
To do this, add an initialization statement into the section where you are setting up your query.
if let user = PFUser.currentUser() {
profilePage = NSMutableArray() // Reset the profile page array.
query.whereKey("writer", equalTo: PFUser.currentUser()!.username!)
query.addAscendingOrder("createdAt")
...
Additionally, the code in objectsDidLoad: may be overwriting the results that you are creating through your query.
Try disabling the assignment to profilePage in there if you are still not getting the correct results.
override func objectsDidLoad(error: NSError?) {
super.objectsDidLoad(error)
// profilePage = NSMutableArray(array: objects!)
self.tableView.reloadData()
}

Tableview list is empty causes by findObjectInBackgroundWithBlock return nil

These are my code in swift
This is the code of retrieving the current user's friend list object with parse
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
}
and this is the code of saving current user's friend when the current user add them via username with parse
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")
}
}
}
}
}
I want to retrieve current user's friend list to show it in tableview but the tableview won't update to show current user's friend list, It's empty and there's no user list in tableview at all. I've tried to fix it and check if method get any object.
The problem is when I use println(usernames) ,It prints "nil" which the method doesn't get any object at all. First I use username as NSArray then I changed it into NSMutableArray and it doesn't have append method like NSArray did so I did a research and add the "add object" line of code in it and change a few things. Right now I'm not sure at all what's wrong with my code and I've been stuck at this for a week now, If my code's wrong somehow can you please guide me where? or fix it would be great. Any help is appreciated
here's the screenshot of my User's class table in parse
https://www.dropbox.com/s/6xp48v3yn0l2hje/Screen%20Shot%202015-06-03%20at%202.10.13%20PM.png?dl=0
here's the screenshot of my current user's friend in parse which is saveก with PFRelation method as seen above
https://www.dropbox.com/s/pd8mt8sf35u1m0v/Screen%20Shot%202015-06-03%20at%202.10.55%20PM.png?dl=0
Thanks in advance!!

Retrieve data of users from parse to show in tableview with swift

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.

Swift Converting PFQuery to String Array for TableView

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

Resources