swift uitableview show only different value of an user Array - swift

I'm working on a message app with parse.
I would like to filter by sender the result of query but it duplicate sender for each messages.
I think it is possible to find same value on a array? (in this exemple clientsArray)
Any idea?
Below the code that I used.
var clientName = ""
var clientsArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
//Message List Query
let messages = PFQuery(className:"Message")
messages.whereKey("user", equalTo:PFUser.currentUser()!["retailer"]!)
messages.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
print("Successfully retrieved \(objects!.count) scores.")
if let objects = objects as? [PFObject] {
self.clientName.removeAll()
for object in objects {
if let clientName = object["clientName"] as? String {
self.clientsArray.append(clientName)
}
self.tableView.reloadData()
print(self.clientsArray)
}
}
} else {
print(error)
}
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return clientsArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("clientsCell", forIndexPath: indexPath)
let clientName = clientsArray[indexPath.row]
if let clientNameLabel = cell.viewWithTag(301) as? UILabel {
clientNameLabel.text = clientName
}
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showChat" {
if let destination = segue.destinationViewController as? newChatViewController {
destination.clientName = clientsArray[(tableView.indexPathForSelectedRow?.row)!]
//self.hidesBottomBarWhenPushed = true
}
}
}

It's really hard to answer without seeing what the data structure looks like. But I can tell you the problem with your code.
if let clientName = object["clientName"] as? String {
self.clientsArray.append(clientName)
}
Your if-let statement is simply getting the object of ["clientName"], which is just your clients name. Then you're appending your clients name to your clientsArray object.
This is why you're just seeing luke.
I can help resolve the problem, but I need to know what your data's structure looks like. Can you print out an entire object?

Related

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.

fatal error: unexpectedly found nil while unwrapping an Optional value (lldb) in logged in app with no data on Parse

Im trying to make the login form as the main initial screen but i cant, all the time opens user list table first. I dont have any data on Parse but i have all the neccessary classes there. It looks like it have logged in as anonymous user or something and now it makes a lot of errors because there is no suitable code for unknown user? Can somebody help me please?
//
// FeedTableViewController.swift
// ParseStarterProject
//
// Created by Rob Percival on 19/05/2015.
// Copyright (c) 2015 Parse. All rights reserved.
//
import UIKit
import Parse
class FeedTableViewController: UITableViewController {
var messages = [String]()
var usernames = [String]()
var imageFiles = [PFFile]()
var users = [String: String]()
override func viewDidLoad() {
super.viewDidLoad()
var query = PFUser.query()
query?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let users = objects {
self.messages.removeAll(keepCapacity: true)
self.users.removeAll(keepCapacity: true)
self.imageFiles.removeAll(keepCapacity: true)
self.usernames.removeAll(keepCapacity: true)
for object in users {
if let user = object as? PFUser {
self.users[user.objectId!] = user.username!
}
}
}
var getFollowedUsersQuery = PFQuery(className: "followers")
getFollowedUsersQuery.whereKey("follower", equalTo: PFUser.currentUser()!.objectId!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
var followedUser = object["following"] as! String
var query = PFQuery(className: "Post")
query.whereKey("userId", equalTo: followedUser)
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.messages.append(object["message"] as! String)
self.imageFiles.append(object["imageFile"] as! PFFile)
self.usernames.append(self.users[object["userId"] as! String]!)
self.tableView.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 usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! cell
imageFiles[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
myCell.username.text = usernames[indexPath.row]
myCell.message.text = messages[indexPath.row]
return myCell
}
/*
// Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
// Delete the row from the data source
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
} else if editingStyle == .Insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
}
A PFUser's objectID is not stored on the device. You need to fetch it. The following is Objective-C but it should be easily converted to swift.
PFQuery *query = [PFUser query];
[query whereKey:#"username" equalTo:[[PFUser currentUser] objectForKey:#"username"]];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
if (objects.count) {
for (PFObject *object in objects) { // just to be safe, but there should only be one.
NSLog(#"Object ID: %#", object.objectId);
}
}
}
}
In Swift (because you asked politely)
var query = PFUser.query()
query.whereKey("username", equalTo:PFUser.currentUser().objectForKey("username"))
query.findObjectsInBackgroundWithBlock({(objects:NSArray, error:NSError) in
if error == nil {
if objects.count {
for var object in objects {
// here you can get object.objectID
}
}
}
})

why is my data not showing in the tableview?

Printing out the data in the console works just fine. In viewdidload method the array count is also fine. But if i use any of the code outside viewdidload its not working. Im trying to populate a table with two labels in each cell (airline and price) but none of the data is displaying and when i try out in the console arrayOfFlights.price.count (for example) it prints out 0 as if its empty.
Data:
import Foundation
class FlightDataModel {
var airline: String?
var price: String?
init(airline: String?, price: String?) {
self.airline = airline
self.price = price
}
}
controller.swift
import Foundation
import UIKit
class FlightsController: UITableViewController, UITableViewDataSource {
var arrayOfFlights : [FlightDataModel] = [FlightDataModel]()
var startpoint:String!
var endpoint:String!
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrayOfFlights.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as myCustomTableViewCell
cell.airlineLabel.text = arrayOfFlights[indexPath.row].airline
cell.priceLabel.text = arrayOfFlights[indexPath.row].price
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// json request to api
let qpxRequest = Router.QPXRequest()
request(qpxRequest).responseJSON { (request, response, json, error) -> Void in
if json != nil {
//insert airline data into arrayOfFlights
if let myJSON = json as? [String:AnyObject] {
if let trips = myJSON["trips"] as? [String:AnyObject] {
if let data = trips["data"] as? [String:AnyObject] {
if let carriers = data["carrier"] as? [[String:String]] {
for (index, carrierName) in enumerate(carriers) {
var myFlight = FlightDataModel(airline: carrierName["name"] as String!, price:nil)
self.arrayOfFlights.append(myFlight)
}
}
}
if let tripOptions = trips["tripOption"] as? [[String:AnyObject]] {
for (index, tripOption) in enumerate(tripOptions) {
self.arrayOfFlights[index].price = tripOption["saleTotal"] as String!
}
}
}
}
}
} // end api request
} //end viewdidload
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
}
Make sure your class is set as dataSource of your tableView
And call the method tableView.reloadData() when you are done with the data parsing.

Query an image using Parse

I am using parse with Swift and I am trying to bring up and post an image from Parse on to my tableView but I keep receiving in the log
fatal error: unexpectedly found nil while unwrapping an Optional
value
here's my code for querying the image:
import UIKit
import Parse
class HomePage: UITableViewController {
var images = [UIImage]()
var titles = [String]()
var imageFiles = [PFFile]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
println(PFUser.currentUser())
var query = PFQuery(className:"Post")
//query.whereKey("username", equalTo:followedUser)
query.findObjectsInBackgroundWithBlock {(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
for object in objects! {
// Update - replaced as with as!
self.titles.append(object["Title"] as! String)
// Update - replaced as with as!
self.imageFiles.append(object["imageFile"] as! PFFile)
self.tableView.reloadData()
}
} else {
// Log details of the failure
println(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titles.count
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 500
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var myCell:cell = self.tableView.dequeueReusableCellWithIdentifier("myCell") as! cell
myCell.rank.text = "21"
myCell.votes.text = "4012"
myCell.postDescription.text = titles[indexPath.row]
return myCell
}
}
Also I get the one line of code highlighted in green which is this :
self.imageFiles.append(object["imageFile"] as! PFFile)
What am I doing wrong and what can I do to make the the code pull up the image from Parse?
now its no longer giving me the error unwrapped nil but it still shows
self.imageFiles.append(object["imageFile"] as! PFFile)
in green highlighting and the app keeps crashing when i open it.
this is my parse backend in case that might be an issue:
i solved the issue by adding in the ovveride func UITableviewCell
imageFile[indexPath.row].getDataInBackgroundWithBlock { (data, error) -> Void in
if let downloadedImage = UIImage(data: data!) {
myCell.postedImage.image = downloadedImage
}
}
i think this worked because i got rid of the if error == nil and now its working great for me.

Why is my array always nil?

I really don't know whats going on and Im really confused why this happens. I might be doing something wrong but when i try to access my array out of the function, there is nothing in it. If anyone can help me please tell me.
import UIKit
class withFriendsView: UITableViewController {
var withFriendsArray:NSMutableArray = NSMutableArray()
var friendImg = [PFFile]()
var friendusername = [String]()
var friendName = [String]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
loadWithFriends()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friendusername.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:WithFriendsCell = tableView.dequeueReusableCellWithIdentifier("withFriends", forIndexPath: indexPath) as! WithFriendsCell
friendImg[indexPath.row].getDataInBackgroundWithBlock {
(data:NSData?, error:NSError?) -> Void in
let img = UIImage(data: data!)
cell.friendsImage.image = img
}
return cell
}
func loadWithFriends() {
var channelQuery = ChannelQuery.query()!
var activityQuery = ActivityQuery.query()!
channelQuery.whereKey("Host", matchesKey: "ActChannel", inQuery: activityQuery)
channelQuery.whereKey("Host", equalTo: "kia495")
var data = channelQuery.findObjects()
if data!.count != 0 {
for objects in data! {
let username = objects["Users"]!!.objectId
let predicate = NSPredicate(format: "objectId == %#", username!!)
var userQuery = PFQuery(className: "_User", predicate: predicate)
var objects = userQuery.findObjects()
for object in objects! {
friendImg.append(object.objectForKey("profileImage") as! PFFile)
}
}
}
}
}
You should reload the table after adding an element to the array
First move loadWithFriends() from viewDidAppear to viewDidLoad
in this line, you are returning another array, try returning friendImg.count
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friendusername.count
}
This findObjectsInBackgroundWithBlock looks like an async method, which will immediately return. The code in the block will be executed only when the data is ready. So when you try to access the data from friendImg, it may not be ready and you will get nil.
If the data is not very large, you can use sync method to do this.