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

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.

Related

Pass Firebase data from UITableViewCell to ViewController

First post so apologies for anything I do wrong here.
I've been stuck on this for awhile now. I think the problem is pretty straight forward, but I seem to be missing something. The code below is from my homeVC which has a tableview. I created a tableViewCell as well. I have firebase hooked up and the data saves properly. Overall goal is to create a recipe manager. Home screen has a list of recipes, you can add and edit. When you click on the recipe name in the homeVC table you are taken to ShowDataVC. I am able to load the recipe name into the tableview but cant seem to get it to load when selected to the ShowDataVC. Ultimately I think I want to be able to use the UUID I created for each recipe to display all info, handling edits, handling error state if no recipe is found for that ID.
Thanks in advance!
struct RecipeData {
let user: String
let recipeName: String
let ingredientsText: String?
let directionsText: String?
let servingsNumber: Int?
let id = UUID().uuidString
}
import UIKit
import Firebase
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var table: UITableView!
#IBOutlet weak var logout: UIBarButtonItem!
#IBOutlet weak var add: UIBarButtonItem!
let db = Firestore.firestore()
var id = UUID().uuidString
var data = [RecipeData]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .gray
table.delegate = self
table.dataSource = self
navigationItem.hidesBackButton = true
table.register(UINib(nibName: D.cellNibName, bundle: nil), forCellReuseIdentifier: D.cellIdentifier)
loadRecipeNames()
}
func loadRecipeNames() {
db.collection(D.FStore.collectionName)
.addSnapshotListener { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
let data = document.data()
if let user = data[D.FStore.userField] as? String,
let recipeNameLabels = data[D.FStore.recipeTextField] as? String {
//print("This is = \(document.documentID) => \(document.data())")
let newRecipe = RecipeData(user: user, recipeName: recipeNameLabels, ingredientsText: nil, directionsText: nil, servingsNumber: nil)
self.data.append(newRecipe)
DispatchQueue.main.async {
self.table.reloadData()
let indexPath = IndexPath(row: self.data.count - 1, section: 0)
self.table.scrollToRow(at: indexPath, at: .top, animated: true)
}
}
}
}
}
}
#IBAction func logoutPressed(_ sender: UIBarButtonItem) {
do {
try Auth.auth().signOut()
navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
}
}
#IBAction func addPressed(_ sender: UIBarButtonItem) {
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: D.addRecipeSegue) as! AddRecipeViewController
navigationController?.pushViewController(vc, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = data[indexPath.row]
let cell = table.dequeueReusableCell(withIdentifier: D.cellIdentifier, for: indexPath) as! RecipeNameCell
cell.label.text = data.recipeName
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ShowSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowSegue" {
if let indexPath = table.indexPathForSelectedRow {
let vc = segue.destination as! ShowRecipeDataViewController
vc.newData = data[indexPath.row]
}
}
}
}
import UIKit
import Firebase
class AddRecipeViewController: UIViewController, UIImagePickerControllerDelegate & UINavigationControllerDelegate {
#IBOutlet weak var recipeNameTextField: UITextField!
#IBOutlet weak var ingredientsTextField: UITextView!
#IBOutlet weak var directionsTextField: UITextView!
#IBOutlet weak var stepper: UIStepper!
#IBOutlet weak var numServingLabel: UILabel!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var takePicture: UIButton!
#IBOutlet weak var saveButton: UIBarButtonItem!
let db = Firestore.firestore()
var data: [RecipeData] = []
var stepperValue: Int = 0
var id = UUID().uuidString
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .lightGray
}
#IBAction func savePressed(_ sender: UIBarButtonItem) {
if let text = recipeNameTextField.text, !text.isEmpty {
saveData(text: text)
print("Data successfully saved!")
}
}
func saveData(text: String) {
if let recipeName = recipeNameTextField.text,
let addedIngredients = ingredientsTextField.text,
let directionsText = directionsTextField.text,
let servingsNum = numServingLabel.text,
let user = Auth.auth().currentUser?.email {
let newRecipeRef = db.collection(D.FStore.collectionName).document(id)
newRecipeRef.setData([
D.FStore.recipeTextField: recipeName,
D.FStore.ingredientsText: addedIngredients,
D.FStore.directionsText: directionsText,
D.FStore.numberServings: servingsNum,
D.FStore.userField: user,
D.FStore.id: id
]) { err in
if let err = err {
print("Error adding document: \(err)")
} else {
print("Document added with ID:\(newRecipeRef)")
}
}
}
}
#IBAction func takePicturePressed(_ sender: UIButton) {
let picker = UIImagePickerController()
picker.sourceType = .camera
picker.delegate = self
picker.allowsEditing = true
present(picker, animated: true, completion: nil)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
picker.dismiss(animated: true, completion: nil)
guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else {
return
}
guard let imageData = image.pngData() else {
return
}
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
#IBAction func stepperPressed(_ sender: UIStepper) {
stepperValue = Int(sender.value)
numServingLabel.text = "\(stepperValue)"
}
}
import UIKit
import Firebase
class ShowRecipeDataViewController: UIViewController {
#IBOutlet weak var recipeNameLabel: UILabel!
#IBOutlet weak var ingredientsText: UILabel!
#IBOutlet weak var directionsText: UILabel!
#IBOutlet weak var numServings: UILabel!
#IBOutlet weak var logout: UIBarButtonItem!
let db = Firestore.firestore()
var newData = [RecipeData]()
var data: [RecipeData] = []
var id = UUID().uuidString
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemOrange
}
#IBAction func logoutPressed() {
do {
try Auth.auth().signOut()
navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
}
}
}
Update
You'll need to assign the values to your outlets. You can do that like so.
class ShowRecipeDataViewController: UIViewController {
#IBOutlet weak var recipeNameLabel: UILabel!
#IBOutlet weak var ingredientsText: UILabel!
#IBOutlet weak var directionsText: UILabel!
#IBOutlet weak var numServings: UILabel!
#IBOutlet weak var logout: UIBarButtonItem!
let db = Firestore.firestore()
var newData: RecipeData? = nil
var data: [RecipeData] = []
var id = UUID().uuidString
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemOrange
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let newData = newData else {
return
}
recipeNameLabel.text = newData.recipeName
ingredientsText.text = newData.ingredientsText
directionsText.text = newData.directionsText
numServings.text = "\(newData.servingsNumber)"
}
#IBAction func logoutPressed() {
do {
try Auth.auth().signOut()
navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
}
}
}
Original Answer
You'll need to share your ShowRecipeDataViewController code to get a better answer. But, the problem is probably there. But if I had to guess you'll need to add the code to tell the textField or Label to have the data in it.
Often, people do that in the ViewDidLoad function like:
// inside ShowRecipeDataViewController
override func viewDidLoad() {
super.viewDidLoad()
recipeLabel.text = data.recipeName
ingredientsTextField.text = data.ingredients
}
// etc.,

Cannot transfer Data from VC1 to VC2 using protocols in Swift

well, im using 2 VCs, one with a textField where the user inputs the CityName, and another VC where it takes care of all the UI elements(like the temp, cityname, etc..), now I use also a NetWorkManager to take care of all the networking&JSON stuff.
the problem is im trying to transfer the data from the NetWorkManager to VC1 but for some reason the delegate aint working :( - basically the road should be like this : VC2 -> NetWorkManager -> VC1.
Here's my Code:
import Foundation
protocol NetworkManagerDelegate {
func didUpdateWeather(weather: WeatherModel)
}
struct NetworkManager {
let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=2da9980c9a43e21c2cdb1f28316d151d&units=metric"
var delegate: NetworkManagerDelegate?
func fetchWeather(cityName: String) {
let urlString = "\(weatherURL)&q=\(cityName)"
performRequest(urlString: urlString)
}
func performRequest(urlString: String) {
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, respone, error) in
if error != nil {
print(error!)
}
if let safeData = data {
if let weather = self.parseJSON(weatherData: safeData) {
print("Im not nil")
self.delegate?.didUpdateWeather(weather: weather)
}
}
}
task.resume()
}
}
func parseJSON(weatherData: Data) -> WeatherModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(WeatherDataModel.self, from: weatherData)
let id = decodedData.weather[0].id
let cityName = decodedData.name
let temp = decodedData.main.temp
let weather = WeatherModel(conditionId: id, cityName: cityName ,temperatrue: temp)
print("Temp is: \(weather.temperatrueString)")
return weather
} catch {
print(error)
return nil
}
}
}
VC2:
import UIKit
import Foundation
class WeatherByCityController: UIViewController, UITextFieldDelegate {
// func didUpdateWeather(weather: WeatherModel) {
// print("Hi")
// }
//
#IBOutlet weak var cityTextField: UITextField!
#IBOutlet weak var updateWeatherBtn: UIButton!
var netWorkManager = NetworkManager()
override func viewDidLoad() {
super.viewDidLoad()
// netWorkManager.delegate = self
cityTextField.delegate = self
}
#IBAction func closeButtonTapped(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
#IBAction func updateWeatherByCityTapped(_ sender: UIButton) {
//Calling delegate to update the City:
//Dismiss the VC:
dismiss(animated: true, completion: nil)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
cityTextField.endEditing(true)
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
if let city = cityTextField.text {
netWorkManager.fetchWeather(cityName: city)
}
cityTextField.text = ""
}
}
VC1:
import UIKit
import Foundation
import CoreLocation
class WeatherScreen: UIViewController,NetworkManagerDelegate {
//Objects outlets:
#IBOutlet weak var conditionIcon: UIImageView!
#IBOutlet weak var tempLabel: UILabel!
#IBOutlet weak var cityLabel: UILabel!
//TableView Outlet:
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var segeControl: UISegmentedControl!
var models = [DailyWeatherEntry]()
var hourlyModels = [HourlyWeatherEntry]()
var netWorkManager = NetworkManager()
override func viewDidLoad() {
netWorkManager.delegate = self
tableView.register(HourlyTableViewCell.nib(), forCellReuseIdentifier: HourlyTableViewCell.identifier)
tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
// Load things once the view will appear
}
#IBAction func locationBtnTapped(_ sender: UIButton) {
//Asking the user for a permission for using his location:
}
func didUpdateWeather(weather: WeatherModel) {
print("Hi")
}
}
extension WeatherScreen: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//creating the cell:
let cell = tableView.dequeueReusableCell(withIdentifier: "weatherCell", for: indexPath) as! HourlyTableViewCell
//Cell Configure:
cell.textLabel!.font = UIFont.systemFont(ofSize: 10)
return cell
}
}
Where is the code for the VC1 ? Without the code for VC 1 it is hard to give an answer. However i'll try to answer as this might be the scenario.
So basically what you are trying to do is make a network call from the VC2 and whatever the response it should be updated in VC1 which is already active somewhere else. Here you just have to set the delegate of the NetworkManger to the VC1 instance. So you have to get the instance of VC1 in VC2.
var netWorkManager = NetworkManager()
//Get this instance in your code
var vc1: UIViewController!
override func viewDidLoad() {
super.viewDidLoad()
// Here you will be setting the delegate
// to VC1 where you will be having the delegate methods
netWorkManager.delegate = vc1
cityTextField.delegate = self
}
While this method works I would not recommend using the network manager in such a way. Try to use completion handlers instead of delegates to get the data and then pass that values between the view controllers.
Edited:
Pass completion like this in the Network Manager performRequest function.
func performRequest(urlString: String, completion: #escaping (Bool, String?, Error?) -> Void) {
guard let url = URL(string: urlString) else {
completion(false, nil, NSError(domain: "URLString is not a valid URL", code: 100, userInfo: nil))
return
}
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (data, respone, error) in
guard let safeData = data, let weather = self.parseJSON(weatherData: safeData) else {
print("Empty data or JSON parse error")
completion(false, nil, error)
}
print("Im not nil")
completion(true, weather, nil)
}
task.resume()
}
And call the api request in the VC2.
#IBAction func updateWeatherByCityTapped(_ sender: UIButton) {
//Calling the api request. Pass your url string here
self. netWorkManager.performRequest(urlString: "") { (success, weather, error) in
guard success else {
print(error as Any)
return
}
// Here you have got the weather data.
// Don't know what is weather model. so simply passing the weather string.
self.delegate.didUpdateWeather(weather: weather)
//Dismiss the VC:
dismiss(animated: true, completion: nil)
}
}
Here adopt the NetworkManagerDelegate to VC1 and before presenting the VC2 set the delegate to VC1. Or if you are not presenting the VC2 from VC1 then use UserNotifications to send the weather data to the VC1.
This line of code var netWorkManager = NetworkManager() creates a new instance of network manager each time it is invoked.
In your case, the network manager in VC1 will not get called when the network manager you created in VC2 receives a network response. They are two separate entities.
There a few things you can think about:
If I understand your scenario correctly, your VC2 is used to get a city name from the user. Does VC2 really need to make a network call? You could restrict VC2 to only fetch the city name.
Make the networkManager a singleton. You can then call it from multiple places in your code. The networkManger can have method to 'fetch' and it can take in a completionHandler (as #Raja Vijaya kumar) had suggested.

How to print data in empty array

I'm trying to print the chat array that is declared as a empty global variable in a table. The data that I'm trying to print is received using web sockets. I'm assigning the data in the messageReceived function, and I know that the data is getting to the program because I'm printing in a label, but the moment that I'm trying to print it in the table is simple not working. All of this is in the ViewController.swift:
import UIKit
import Starscream
var messagetext: String = ""
var tabletext: String = ""
var chat = [String] ()
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
var socket = WebSocket(url: URL(string: "ws://localhost:1337/")!, protocols: ["chat"])
#IBOutlet weak var chatMessage: UILabel!
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var tableView: UITableView!
#IBAction func buttonClick(_ sender: Any) {
messagetext = textField.text!
sendMessage(messagetext)
}
override func viewDidLoad() {
super.viewDidLoad()
self.textField.delegate = self
socket.delegate = self
socket.connect()
navigationItem.hidesBackButton = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldDidEndEditing(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return (true)
}
deinit{
socket.disconnect(forceTimeout: 0)
socket.delegate = nil
}
}
// MARK: - FilePrivate
fileprivate extension ViewController {
func sendMessage(_ messager: String) {
socket.write(string: messager)
}
func messageReceived(_ message: String) {
chatMessage.text = message
chat.append(message)
}
}
// MARK: - WebSocketDelegate
extension ViewController : WebSocketDelegate {
public func websocketDidConnect(_ socket: Starscream.WebSocket) {
}
public func websocketDidDisconnect(_ socket: Starscream.WebSocket, error: NSError?) {
performSegue(withIdentifier: "websocketDisconnected", sender: self)
}
public func websocketDidReceiveMessage(_ socket: Starscream.WebSocket, text: String) {
// 1
guard let data = text.data(using: .utf16),
let jsonData = try? JSONSerialization.jsonObject(with: data),
let jsonDict = jsonData as? [String: Any],
let messageType = jsonDict["type"] as? String else {
return
}
// 2
if messageType == "message",
let messageData = jsonDict["data"] as? [String: Any],
let messageText = messageData["text"] as? String {
messageReceived(messageText)
}
}
public func websocketDidReceiveData(_ socket: Starscream.WebSocket, data: Data) {
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return(chat.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.text = chat[indexPath.row] as! String
return(cell)
}
}
Assuming that you are sure about there is data to be received by your view controller, The issue would be: the tableview data source methods are called before receiving any data, which means chat data source array is still empty, thus there is no data to display.
The solution for your case is to make sure to reload the tableview after receiving data (updating the value of chat data source array), which means in your case after appending a message to chat in messageReceived method by calling reloadData() UITableView instance method:
func messageReceived(_ message: String) {
chatMessage.text = message
chat.append(message)
// here we go:
tableView.reloadData()
}
In your message received handler, issue a tableview.reloadData()
Cheers!
You need to tell the tableview that there is new data. You also need to allow for the fact that the network operation probably occurred on a background queue and UI updates must be on the main queue:
func messageReceived(_ message: String) {
DispatchQueue.main.async {
let newRow = IndexPath(row: chat.count, section:0)
chatMessage.text = message
chat.append(message)
tableView.insertRows(at:[newRow],with: .automatic)
}
}

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

How to retrieve data from parse server?

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

Resources