How to retrieve data from parse server? - ios

Im trying to make a chat app so i almost finish my woking. But i don't know how to get my data from parse to my code back. I tried once but it isn't working there is an error coming when type "query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in" that i want to know how i'm gonna fix this issue.
#IBOutlet var chatTextField: UITextField!
#IBOutlet var DockHight: NSLayoutConstraint!
#IBOutlet var SendButton: UIButton!
#IBOutlet var messageTableview: UITableView!
var messagesArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.messageTableview.delegate = self
self.messageTableview.dataSource = self
self.chatTextField.delegate = self
let tappGesture:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tableViewTapped")
self.messageTableview.addGestureRecognizer(tappGesture)
//retrive
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func SendButton(sender: UIButton) {
//send button is stoped
//end edding methode for the text
self.chatTextField.endEditing(true)
self.chatTextField.enabled = false
self.SendButton.enabled = false
//create a PFobject
var message = PFObject(className:"Message")
message["Text"] = "\(chatTextField.text)"
message.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success == true) {
NSLog("The Message has been sent")
} else {
NSLog(error!.description)
}
self.SendButton.enabled = true
self.chatTextField.enabled = true
}
}
func retrieveMessage() {
var query:PFQuery = PFQuery(className: "Message")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
}
}
func tableViewTapped(){
self.chatTextField.endEditing(true)
}
//textfield deligate methode
func textFieldDidBeginEditing(textField: UITextField) {
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.2, animations: {
self.DockHight.constant = 350
self.view.layoutIfNeeded()
}, completion: nil)
}
func textFieldDidEndEditing(textField: UITextField) {
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.3, animations: {
self.DockHight.constant = 44
self.view.layoutIfNeeded()
}, completion: nil)
}
//makrk tableview delegate methode
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.messageTableview.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.messagesArray[indexPath.row]
return cell
}
var window: UIWindow?
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messagesArray.count
}
}

Parse documentation is showing this way to get data:
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// Do something with the found objects
if let objects = objects {
for object in objects {
print(object.objectId)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
The problem is that you are using objects: [AnyObject]! instead of objects: [PFObject]?
Edit:
also you can write like this (objects, error) -> Void in

You need to use [PFObject]? instead of [AnyObject]!

Updated for Swift 3
How to retrieve data from parse?
If you want to use findObjectsInBackgroundWithBlock
For example you can write this:
query.findObjectsInBackground { (objects, error) in
if let objects = objects {
for object in objects {
print(object.objectId)
}
} else {
NSLog("Error: \(error!)")
}
}

Related

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!
}

Table view not populating upon view first loading (Swift2 and parse)

Whenever I run my app, the first time the view containing the tableview loads, the table view does not get populated. But once i switch tabs (i am using a tab bar controller), and then switch back, the table view becomes populated. Does anyone have any ideas on how to fix this?
Here is the code:
import UIKit
import Parse
class NotesViewController: UITableViewController {
var notes = [PFObject]()
var cacheNotes = Bool()
#IBOutlet var showContentTableView: UITableView!
func findNotes() {
if let user = PFUser.currentUser()?.username! {
let network = Reachability.isConnectedToNetwork()
let query = PFQuery(className: "notes")
query.whereKey("username", equalTo: user)
if network == true {
print("connected to network")
} else {
("not connected to network")
query.fromLocalDatastore()
}
query.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
self.notes = objects!
for object in objects! {
if self.cacheNotes == true && network == true {object.pinInBackground()}
}
}
})
}
showContentTableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// 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()
if NSUserDefaults.standardUserDefaults().objectForKey("cacheNotes") == nil {
NSUserDefaults.standardUserDefaults().setObject(true, forKey: "cacheNotes")
}
}
override func viewDidAppear(animated: Bool) {
cacheNotes = NSUserDefaults.standardUserDefaults().objectForKey("cacheNotes") as! Bool
print(cacheNotes)
findNotes()
showContentTableView.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 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 notes.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
// Configure the cell...
cell.textLabel?.text = notes[indexPath.row]["title"] as? String
return cell
}
}
When you retrieve data from Parse using findObjectsInBackgroundWithBlock the network operation happens in the background, while the rest of the function keeps executing. So, the showContentTableView.reloadData() happens immediately, before the data has been returned. You need to reload the table data once the network operation has completed, that is, inside the block/closure
func findNotes() {
if let user = PFUser.currentUser()?.username! {
let network = Reachability.isConnectedToNetwork()
let query = PFQuery(className: "notes")
query.whereKey("username", equalTo: user)
if network == true {
print("connected to network")
} else {
("not connected to network")
query.fromLocalDatastore()
}
query.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
self.notes = objects!
showContentTableView.reloadData()
for object in objects! {
if self.cacheNotes == true && network == true {object.pinInBackground()}
}
}
})
}
}
Also, I would suggest that you call findNotes from viewWillAppear rather than viewDidAppear - it will get a head start on populating the data before the table is onscreen.

Note code in Swift

I have seen a similar request but did not respond to my problem.
I am building a simple app notes but when I make the login, the data saved on Parse appear for a few seconds on the TableView and then disappear. What am I doing wrong?
thank you all
import UIKit
class MasterTableViewController: UITableViewController, PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate {
var noteObjects: NSMutableArray! = NSMutableArray()
override func viewDidLoad() {
super.viewDidLoad()
// 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()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.loginSetup()
}
// Parse - Login
func logInViewController(logInController: PFLogInViewController, shouldBeginLogInWithUsername username: String, password: String) -> Bool {
if (!username.isEmpty || !password.isEmpty) {
return true
} else {
return false
}
}
func logInViewController(logInController: PFLogInViewController, didLogInUser user: PFUser) {
self.dismissViewControllerAnimated( true, completion: nil )
}
func logInViewController(logInController: PFLogInViewController, didFailToLogInWithError: NSError?)
{
println("Faild to log in..")
}
// Parse - sign up
func signUpViewController(signUpController: PFSignUpViewController, shouldBeginSignUp info: [NSObject : AnyObject]) -> Bool {
if let password = info["password"] as? String {
return count(password.utf16) >= 8
} else {
return false
}
}
func signUpViewController(signUpController: PFSignUpViewController, didSignUpUser user: PFUser) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func signUpViewController(signUpController: PFSignUpViewController, didFailToSignUpWithError error: NSError?) {
println("Faild to sign up")
}
func signUpViewControllerDidCancelSignUp(signUpController: PFSignUpViewController) {
println("User dismissed sign up")
}
// Parse - logout
#IBAction func logoutAction(sender: AnyObject) {
PFUser.logOut()
self.loginSetup()
}
func loginSetup() {
if (PFUser.currentUser() == nil) {
var logInViewController = PFLogInViewController()
logInViewController.delegate = self
var signUpViewController = PFSignUpViewController()
signUpViewController.delegate = self
logInViewController.signUpController = signUpViewController
self.presentViewController(logInViewController, animated: true, completion: nil)
}else {
self.fetchAllObjectsFromLocalDatastore()
self.fetchAllObjects()
}
}
/*
func fetchAllObjectsFromLocalDatastore() {
var query: PFQuery = PFQuery(className: "Note")
//query.cachePolicy = .CacheElseNetwork
query.fromLocalDatastore()
query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if (error == nil) {
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
}
}
//var temp: PFObject = PFObject()
//self.noteObjects = temp.mutableCopy() as! NSMutableArray
//println(self.noteObjects)
self.tableView.reloadData()
}else {
println(error!.userInfo)
}
}
}
func fetchAllObjects() {
PFObject.unpinAllObjectsInBackgroundWithBlock(nil)
var query: PFQuery = PFQuery(className: "Note")
//query.cachePolicy = .CacheElseNetwork
query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if (error == nil) {
PFObject.pinAllInBackground(objects, block: nil)
self.fetchAllObjectsFromLocalDatastore()
}else {
println(error!.userInfo)
}
}
}
*/
func fetchAllObjectsFromLocalDatastore() {
var query: PFQuery = PFQuery(className: "Note")
query.fromLocalDatastore()
query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
//var temp: NSArray = objects as! [NSArray]
var temp: NSArray = objects! as NSArray
self.noteObjects = temp.mutableCopy() as! NSMutableArray
self.tableView.reloadData()
}else {
println(error!.userInfo)
}
}
}
func fetchAllObjects() {
PFObject.unpinAllObjectsInBackgroundWithBlock(nil)
var query: PFQuery = PFQuery(className: "Note")
query.whereKey("username", equalTo: PFUser.currentUser()!.username!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
PFObject.pinAllInBackground(objects, block: nil)
self.fetchAllObjectsFromLocalDatastore()
}else {
println(error!.userInfo)
}
}
}
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 noteObjects!.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MasterTableViewCell
var object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
cell.masterTitleLabel?.text = object["title"] as? String
cell.masterTextLabel?.text = object["text"] as? String
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("editNote", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var upcoming: AddNoteTableViewController = segue.destinationViewController as! AddNoteTableViewController
if (segue.identifier == "editNote") {
let indexPath = self.tableView.indexPathForSelectedRow()!
var object: PFObject = self.noteObjects.objectAtIndex(indexPath.row) as! PFObject
upcoming.object = object;
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
/*
// 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.
}
*/
}

Cannot invoke 'findObjectsInBackgroundWithBlock' with an argument list of type '(([AnyObject]!, NSError!) -> Void)'

I'm following a tutorial called How to Build a Simple iOS Chat App on Youtube which made by a channel called Code With Chris. I followed all his type and I got the following error in Xcode:
/Users/David/Documents/360Drive/Xcode/Try/Learn With Chris/ChatApp/ChatApp/ChatApp/ViewController.swift:53:15: Cannot invoke 'findObjectsInBackgroundWithBlock' with an argument list of type '(([AnyObject]!, NSError!) -> Void)'
Here's my code:
//
// ViewController.swift
// ChatApp
//
// Created by David Chen on 15/4/12.
// Copyright (c) 2015 cwsoft. All rights reserved.
//
import UIKit
import Parse
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
var messagesArray:[String] = [String]()
#IBOutlet weak var MessageTableView: UITableView!
#IBOutlet weak var ButtonSend: UIButton!
#IBOutlet weak var DockViewHeightConstraint: NSLayoutConstraint!
#IBOutlet weak var MessageTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//Set delegate
self.MessageTableView.delegate = self
self.MessageTableView.dataSource = self
self.MessageTextField.delegate = self
let tapGesture:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tableViewTapped")
self.MessageTableView.addGestureRecognizer(tapGesture)
self.messagesArray.append("Test 1")
self.messagesArray.append("Test 2")
self.messagesArray.append("Test 3")
}
#IBAction func ButtonSendPressed(sender: UIButton) {
self.MessageTextField.endEditing(true)
var newMessageObject:PFObject = PFObject(className: "Message")
newMessageObject["Text"] = self.MessageTextField.text
newMessageObject.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success == true) {
NSLog("Success")
} else {
NSLog("Error")
}
}
}
func retrieveMessages() {
var query:PFQuery = PFQuery(className: "Messages")
query.findObjectsInBackgroundWithBlock {
(object: [AnyObject]!, error: NSError!) -> Void in
self.messagesArray = [String]()
for messageObject in objects {
let messageText:String? = (messageObject as PFObject)["Text"] as? String
if messagetext != nil {
self.messagesArray.append(messageText!)
}
}
}
self.MessageTableView.reloadData()
}
func tableViewTapped() {
self.MessageTextField.endEditing(true)
}
//MARK : TextField Delegage Methods
func textFieldDidBeginEditing(textField: UITextField) {
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5, animations: {
self.DockViewHeightConstraint.constant = 320
self.view.layoutIfNeeded()
}, completion: nil)
}
func textFieldDidEndEditing(textField: UITextField) {
self.view.layoutIfNeeded()
UIView.animateWithDuration(0.5, animations: {
self.DockViewHeightConstraint.constant = 60
self.view.layoutIfNeeded()
}, completion: nil)
}
//MARK : Table View Delegate Methods
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.MessageTableView.dequeueReusableCellWithIdentifier("MessageCell") as! UITableViewCell
cell.textLabel?.text = self.messagesArray[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messagesArray.count
}
}
Here's the link of the tutorial
link
Thanks for any helpful suggestions :)
There have been many changes with the last xCode update. I can not really explain why exactly some changes need to be done. You better read the changeLogs! So will I later on :)
In the meantime try this:
func retrieveMessages() {
var query:PFQuery = PFQuery(className: "Messages")
query.findObjectsInBackgroundWithBlock {
(object, error) -> Void in
self.messagesArray = [String]()
for messageObject in object! {
let messageText:String? = (messageObject as! PFObject)["Text"] as? String
if messageText != nil {
self.messagesArray.append(messageText!)
}
}
}
self.MessageTableView.reloadData()
}
It seems that in some cases you don't need to specify the type anymore. In other cases you need to though. In this case, there is no need but you need unwrap your object array.

Filter result from parse query

Hi Im developing a chat app with parse and I have one group-chat tab. What I would like to accomplish Is that when the user registers he/she can choose from a list of "tags" for example, "cats", "dogs" and "cars". Then when the user is signed in the groups tab only shows group-chats associated to the chosen tags. Right now i have a function where the user can create a group-chat but If possible i want to remove that and use my idea that I explained above.
Here's my code for the group's tab:
import UIKit
// Parse loaded from SwiftParseChat-Bridging-Header.h
class GroupsViewController: UITableViewController, UIAlertViewDelegate {
var groups: [PFObject]! = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if PFUser.currentUser() != nil {
self.loadGroups()
}
else {
Utilities.loginUser(self)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadGroups() {
var query = PFQuery(className: PF_GROUPS_CLASS_NAME)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) in
if error == nil {
self.groups.removeAll()
self.groups.extend(objects as [PFObject]!)
self.tableView.reloadData()
} else {
ProgressHUD.showError("Network error")
println(error)
}
}
}
#IBAction func newButtonPressed(sender: UIBarButtonItem) {
self.actionNew()
}
func actionNew() {
var alert = UIAlertView(title: "Please enter a name for your group", message: "", delegate: self, cancelButtonTitle: "Cancel", otherButtonTitles: "OK")
alert.alertViewStyle = UIAlertViewStyle.PlainTextInput
alert.show()
}
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
if buttonIndex != alertView.cancelButtonIndex {
var textField = alertView.textFieldAtIndex(0);
if let text = textField!.text {
if countElements(text) > 0 {
var object = PFObject(className: PF_GROUPS_CLASS_NAME)
object[PF_GROUPS_NAME] = text
object.saveInBackgroundWithBlock({ (success: Bool, error: NSError!) -> Void in
if success {
self.loadGroups()
} else {
ProgressHUD.showError("Network error")
println(error)
}
})
}
}
}
}
// MARK: - TableView Data Source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.groups.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
var group = self.groups[indexPath.row]
cell.textLabel?.text = group[PF_GROUPS_NAME] as? String
var query = PFQuery(className: PF_CHAT_CLASS_NAME)
query.whereKey(PF_CHAT_GROUPID, equalTo: group.objectId)
query.orderByDescending(PF_CHAT_CREATEDAT)
query.limit = 1000
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
if let chat = objects.first as? PFObject {
let date = NSDate()
let seconds = date.timeIntervalSinceDate(chat.createdAt)
let elapsed = Utilities.timeElapsed(seconds);
let countString = (objects.count > 1) ? "\(objects.count) meddelanden" : "\(objects.count) meddelande"
cell.detailTextLabel?.text = "\(countString) \(elapsed)"
} else {
cell.detailTextLabel?.text = "0 meddelanden"
}
cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
}
return cell
}
// MARK: - TableView Delegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
var group = self.groups[indexPath.row]
let groupId = group.objectId as String
Messages.createMessageItem(PFUser(), groupId: groupId, description: group[PF_GROUPS_NAME] as String)
self.performSegueWithIdentifier("groupChatSegue", sender: groupId)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "groupChatSegue" {
let chatVC = segue.destinationViewController as ChatViewController
chatVC.hidesBottomBarWhenPushed = true
let groupId = sender as String
chatVC.groupId = groupId
}
}
}
It sounds like you want to query a class (the one containing chats) with the constraint that an array column property of that class (the one listing each chat's tags) contains some list of tags related to the current user. PFQuery has a method called whereKey:containsAllObjectsInArray: which does exactly that.
To make it work, you need to be clear about whether the list of tags is an array of pointers to tag objects, or an array of strings that are tag names. Naturally, if tags on chats are stored as pointers to objects, then the second parameter should be an array of PFObject, and if they are strings, then the array parameter must be an array of NSString.
Unrelated to the semantics of the query, but important: Doing an unguarded, asynch query for anything in cellForRowAtIndexPath: will be unproductive. This method is called every time a cell scrolls into view, which happens arbitrarily often, and arbitrarily rapidly. Use another method to fetch the table's datasource, then reload the table once the data arrives.
(I think the post has been given a close vote because it asks a specific question, then presents the reader with a lot of code, much of it unrelated, leaving the reader to find the relevant query, and showing no indication of what's been tried so far. The site will work better for you if you give maximum help to those who might answer an otherwise good question).

Resources