Unable to load and display data from parse - swift

var findPublisher:PFQuery = PFUser.query()!
findPublisher.whereKey("objectId", equalTo: quote.objectForKey("publisher")!)
findPublisher.findObjectsInBackgroundWithBlock{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFUser] {
for object in objects {
//println(object.objectId)
let user:PFuser = (objects as NSArray).lastObject as PFUser
cell.publisherLabel.text = user.username
}
}
}
// Configure the cell...
}
The code here is supposed to query for the objectId and display the username instead of the label. I am getting an error that says use of undeclared type of 'PFUser'... I used "println" right after the error == nil statement and it logs correctly so the error definitely occurs after there.

if you are using a TableViewController, you don't need to create an Outlet of the tableview. So you need to query all the objects from the _User class into an array. So it is up to you to know where you want to place this code either in the ViewDidLoad or ViewWillAppear.
var arrayOFUser :NSMutableArray = []
var findPublisher:PFQuery = PFQuery(className:"_User")
findPublisher.findObjectsInBackgroundWithBlock{ (objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil{
if let objects = objects as? [PFObject] {
for object in objects {
var getusername = object["username"] as! String
self.arrayOFUser.addObject(getusername)
self.tableview.reloadData()
}
}
}
}
// return the count of user into the each cell in the tableview
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayOFUser.count
}
then you go into the ** cellForRowAtIndexPath** method
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = self.tableview.dequeueReusableCellWithIdentifier("CellSubtitle", forIndexPath: indexPath) as! UITableViewCell
let name = self.arrayOFUser[indexPath.row] as! String
cell.textlabel?.text = name
return cell
}
QuickNote "CellSubtitle" is the name of the cell in the tableview so go into the storyboard in change it.

Related

Swift: Bool if true, doesn't display image

I'm a beginner so please be patient explaining, Thanks.
So, basically I have a bool column in parse and I want to display an image if it's false and don't display anything if its true.
here are my codes:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("todayCell", forIndexPath: indexPath) as! reqTodaysCell
let cellDataParse: PFObject = self.dataparse.objectAtIndex(indexPath.row) as! PFObject
var newReadQuery = PFQuery(className: "request")
newReadQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
if object["reqRead"] as! Bool == true {
myCell.isRead.image = nil //here is where I say pic to be nil but what happens is that if the first one is true then it will remove the pic for all of them.
// and if its not true it should display the pic
} else {
myCell.isRead.image = UIImage(named: "newReq")
print("user not read")
}
}
}
})
If I don't explain properly please let me know and I will try my best to explain again.
This sounds like an ideal use case for a ternary operator. As per my example below, you use the ? : syntax following a Bool, if the bool is true it will return the first case and if it's false it will return the second case.
newReadQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
let reqRead = object["reqRead"] as! Bool
cell.image.image = reqRead ? nil : UIImage(named: "newReq")
}
}
})
UPDATE
The above may not have worked as the Parse call might not be completed before the cells are loaded.
Create a global variable (outside of any function):
var reqRead = [Bool]()
In ViewDidLoad you can create an array of the bools.
var newReadQuery = PFQuery(className: "request")
newReadQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
reqRead.append(object["reqRead"] as! Bool)
}
tableView.reloadData()
}
})
Then in your CellForRow:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("todayCell", forIndexPath: indexPath) as! reqTodaysCell
let cellDataParse: PFObject = self.dataparse.objectAtIndex(indexPath.row) as! PFObject
cell.image.image = reqRead[indexPath.row] ? nil : UIImage(named: "newReq")
return cell
}
There's a possibility that it will try to populate the cells before the array is loaded but let me know if this works for you.
if object["reqRead"] as! Bool == false {
myCell.isRead.image = nil
myCell.isRead.hidden = false
} else {
myCell.isRead.hidden = true
}

UITableView in swift

can anyone tell me what's wrong with my code i always get the same data repeated in all cells
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
let query = PFQuery(className:"book")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
var contentString:String = String()
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects {
let a:String = object.objectForKey("title") as! String
contentString = a
}
}
cell.textLabel!.text = contentString
}}
return cell
}
It will be better to query all your data into viewDidLoad() or any life cycle you would like.
var contentString = [String]() //<-- use an array of string instead of a string variable
override func viewDidLoad()
{
super.viewDidLoad()
let query = PFQuery(className:"book"){ query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects
{
let value = object["title"] as! String
self.contentString.append(value) //<-- save the query value to your array
}
self.tableView.reloadData() //<--- then you reload your UI
}
}}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
cell.textLabel!.text = self.contentString[indexPath.row] //<-- then assign the value into your cell
return cell
}
content inside your loop should be like this.
let a:String = object.objectForKey("title") as! String
contentString += a
and i noticed your block calls for same query always. can you tell me whats the different there
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
var contentString:String = String()
if error == nil {
print("Success retrieved \(objects!.count) scores.")
if let objects = objects {
for object in objects {
let a:String = object.objectForKey("title") as! String
contentString = a
}
}
cell.textLabel!.text = contentString
}}
The query in cellForRowAtIndex is trouble. Imagine, every time a cell comes into view, the code asks for every book from the server.
Put the query outside the datasource method (viewWillAppear, for example). When the query is complete, initialize an array property with the results (e.g. self.bookObjects = objects).
Then in cellForRowAtIndex...
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.textColor = UIColor.whiteColor()
// this is the important idea...
let object = self.bookObjects[indexPath.row]
let a:String = object.objectForKey("title") as! String
cell.textLabel!.text = a
return cell

querying parse, how can I print the data within a tableView cell in Swift?

Hi guys I'm trying to print my query which Ive created in Parse, here it is
this works fine and does what i need it to
//store my currentLocations here
var locations : [PFObject] = []
PFGeoPoint.geoPointForCurrentLocationInBackground { (geoPoint:
PFGeoPoint?, error: NSError?) -> Void in
if geoPoint != nil {
var geoPointLon = geoPoint?.longitude
var geoPonitLan = geoPoint?.latitude
var currentLocation = PFGeoPoint(latitude: geoPonitLan!, longitude: geoPointLon!)
var query = PFQuery(className: "User")
query.whereKey("currentLocation", nearGeoPoint: currentLocation, withinKilometers: 5.0)
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
if let myObject = objects as? [PFObject] {
for objects in myObject {
self.locations.append(objects)
}
}
self.tableView.reloadData()
})
}
}
this is my tableview cell and number of rows
func tableView(tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return self.locations.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "test"
return cell
}
when running my app "test" does print the correct number of entries so I know my query is working.
My question is how can I print the actual locations from my class "User", column named "currentLocation" within Parse?
if you need any other info just let me know thanks
Assuming your "currentLocation" column is a string, that's how you get it back.
if it is not a string, then you might need to convert it.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = self.locations["currentLocation"]
return cell
}

Populate table with username of other followed users

class FollowingTableTableViewController: UITableViewController {
let usernames = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
getUsernames()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
func getUsernames() {
var user1 = PFUser.currentUser()
var findUsernames:PFQuery = PFQuery(className: "FollowRequests")
findUsernames.whereKey("from", equalTo: user1!)
findUsernames.includeKey("to")
findUsernames.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in
var myObjects = objects as! [PFObject]
//Solve this part. Need to get all of the users from the "to" field in FollowRequests.
//If No error
if (error == nil) {
for myObjects in objects! {
var user2 = PFUser()
user2.objectForKey("to")
self.usernames.addObject(user2.username!)
println(user2.username)
}
self.tableView.reloadData()
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return self.usernames.count
}
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let item: AnyObject = self.usernames[indexPath.row]
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = (usernames[indexPath.row] as! String)
return cell
}
I keep getting the fatal error:
unexpectedly found nil while unwrapping an Optional value.
What do I need to do?
Hoping to find where I messed up.
There is a lot of ? in your code:
First: are you trying to query using the currentUser(username ) or (objectID)
Second: in the findObjectsInBackgroundWithBlock method
you need to check if there is an error first then convert the array of any object to PFObject
if error == nil{
if let objects = objects as! [PFObject]{
for oneSpecificObject in objects{
var data = oneSpecificObject["to"] as! String
self.usernames.addObject(data)
}
self.tableView.reloadData()
}
}
Third: In the cellForRowAtIndexPath method
why you have that extra line
let item: AnyObject = self.usernames[indexPath.row]
//review carefully your code then if you still have problem let me know.

Swift: UICollectionView & UIImage fatal error: Array index out of range

Hi Im new to swift and need some help thank you. The program worked once, tried to run it again then it crashed. The items are in the array when I debugged but when I try to display the images I get the fatal error.
// Get Brands
func getBrand () {
// Create PFQuery
var query:PFQuery = PFQuery(className: "BrandInfo")
// Call findobjects
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]?, error: NSError?) -> Void in
// refresh array
self.brands = [String]()
self.pics = [UIImage]()
// loop through array
for brandObject in objects! {
// get PFObjects
let brandName:String? = (brandObject as! PFObject)["Name"] as? String
if brandName != nil {
self.brands.append(brandName!)
}
let brandPicture = brandObject["Image"] as! PFFile
brandPicture.getDataInBackgroundWithBlock({ (imageData:NSData?, error:NSError?) -> Void in
if(error == nil){
let brandImage = UIImage(data: imageData!)
self.pics.append(brandImage)
println(self.pics.count)
}
})
}
// Refresh CollectionView
self.collectionView.reloadData()
}
}
// Setting up collection view
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.brands.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:collectionViewCell = self.collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! collectionViewCell
// Get elements
let picToDisplay:UIImage? = pics[indexPath.row] // this is the error line
let dataToDisplay:String = brands[indexPath.row]
let imageView:UIImageView? = cell.viewWithTag(2) as? UIImageView
// Set labels
cell.brandImage.image = picToDisplay
cell.brandLabel.text = dataToDisplay
return cell
}
///////////////////////////////
struct brandCollection {
var brandText:[String] = [String]()
var brandImage:[UIImage?] = [UIImage]()
}
You have brands.count items, and you need brand.count images. But you are using a different array pics which will fail if it has less elements than brands. Looking at your code, there are several possibilities why this could happen.
This is bad design. You should have a data array that encapsulates all the information you need. Each image should be connected to its object (the brand), not held in some other array.