Table View Cell not loading - swift

I'm trying to populate custom UITableViewCell inside UITableView but it's not loading the data in the cell. I have created an array of Recipes and populate the array with data from API call. after debugging the code, it seems that the array count is 0 hence not loading the data in the cell although I'm calling getRecipes() method to populate the array.. any idea on what's causing this or how to fix it??
Below is my code:
class MainPageViewController: UIViewController
{
//declare variables
#IBOutlet weak var recipeTableView: UITableView!
var recipes: [Recipe] = []
override func viewDidLoad()
{
recipeTableView.delegate = self
recipeTableView.dataSource = self
self.recipeTableView.reloadData()
recipes = self.getRecipes()
print("array: \(recipes.count)")
super.viewDidLoad()
}
}
//ui table view functions
extension MainPageViewController: UITableViewDataSource, UITableViewDelegate
{
//set the number of items in the table view to the array of objects
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
print("array count: \(recipes.count)")
return recipes.count
}
override func viewDidAppear(_ animated: Bool) {
recipeTableView.reloadData()
super.viewDidAppear(animated)
}
//fetch the data in the array and set it in the table view cells
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
print("code here")
let recipe = self.recipes[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "RecipeCell")
as! UIRecipeCell
print("code here")
cell.setRecipe(recipe: recipe)
return cell;
}
func getRecipes() -> [Recipe]
{
var recipesTemp: [Recipe] = []
// Hit Spoonacular endpoint using Moya as the middleman
let provider = MoyaProvider<SpoonacularAPI>()
provider.request(.getRecipes(limitLicense: true, number: 10, tags: "vegetarian, dessert"))
{
switch $0
{
case .success(let response):
do {
// Only allow successful HTTP codes
_ = try response.filterSuccessfulStatusCodes()
// Parse data as JSON
let json = try JSON(data: response.data)
print("json log: \(json)")
// Parse each recipe's JSON
recipesTemp = json["recipes"].arrayValue.map({ Recipe(json: $0) })
print("array count: \(recipesTemp.count)")
print("array : \(recipesTemp)")
}
catch {
print(error.localizedDescription)
}
case .failure(let error):
print(error.localizedDescription)
}
self.recipeTableView.reloadData()
}
return recipesTemp
recipeTableView.reloadData()
}
}

Your API to get the recipes works asynchronously.
You cannot return anything from a method which contains an asynchronous task.
In viewDidLoad call only the method.
In getRecipes remove the return value, it's pointless.
In the asynchronous closure assign the result to the data source array and reload the table view.
And you might reload the table view on the main thread.
Alternatively use a completion handler.
override func viewDidLoad()
{
recipeTableView.delegate = self
recipeTableView.dataSource = self
getRecipes()
}
func getRecipes()
{
// Hit Spoonacular endpoint using Moya as the middleman
let provider = MoyaProvider<SpoonacularAPI>()
provider.request(.getRecipes(limitLicense: true, number: 10, tags: "vegetarian, dessert"))
{
switch $0
{
case .success(let response):
do {
// Only allow successful HTTP codes
_ = try response.filterSuccessfulStatusCodes()
// Parse data as JSON
let json = try JSON(data: response.data)
print("json log: \(json)")
// Parse each recipe's JSON
self.recipes = json["recipes"].arrayValue.map({ Recipe(json: $0) })
print("array count: \(recipesTemp.count)")
print("array : \(recipesTemp)")
DispatchQueue.main.async {
self.recipeTableView.reloadData()
}
}
catch {
print(error.localizedDescription)
}
case .failure(let error):
print(error.localizedDescription)
}
}
}
And be aware you can not do something with recipes at the end of viewDidLoad.

the issue here is that your request function return a result before the actual request hit the response
You should modify the logic with a completion handler instead
func getRecipes(complition: #escaping ((_ response: [Recipe]) -> ())) {
// Your request logic
// onSuccess return the array like this
// complition(resultArray)
}

Related

use func to delete a specific item from core data binary data

I am trying to delete binary data from core data. I am using a var int 'place' to determine what specific item I am trying to delete I am getting a runtime error under helpImage.shareInstance.deleteInfo(info: place) which is below.
Cannot convert value of type 'Int' to expected argument type 'Info'
What can I do to delete the 1st item saved in a core data binary attribute?
import UIKit;import CoreData
class ViewController: UIViewController {
var place = 0
override func viewDidLoad() {
super.viewDidLoad()
let gwen = UIImage(named: "unnamed.jpg")
if let imageData = gwen.self?.pngData() {
helpImage.shareInstance.saveImage(data: imageData)
}
let alz = UIImage(named: "alba.jpeg")
if let imageData = alz.self?.pngData() {
helpImage.shareInstance.saveImage(data: imageData)
}
}
#objc func deleteM(){
helpImage.shareInstance.deleteInfo(info: place)
}
}
class helpImage: UIViewController{
private class func getContext() -> NSManagedObjectContext {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
static let shareInstance = helpImage()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func saveImage(data: Data) {
let imageInstance = Info(context: context)
imageInstance.img = data
do {
try context.save()
} catch {
print(error.localizedDescription)
}
}
func deleteInfo(info: Info) {
do {
try context.delete(info)
} catch {
print(error.localizedDescription)
}
}
}
I'm also a newbie in swift and learning so if anyone has feedback, I'm more than happy to implement.
here is stroryBoard: on "Save" button click, we will save images in CoreData and on "Show" button click, we will display a tableView with our images fetched from CoreData
here is coreData: don't forget to check Manual/None in Codegen in coreData Class
then manually add coreData NSManagedObject SubClass files (there will be two files).
To generate the class and properties files initially:
source: https://developer.apple.com/documentation/coredata/modeling_data/generating_code
From the Xcode menu bar, choose Editor > Create NSManagedObject Subclass.
Select your data model, then the appropriate entity, and choose where to save the files. Xcode places both a class and a properties file into your project.
// this is how your "Picture+CoreDataClass.swift" looks like
import Foundation
import CoreData
#objc(Picture)
public class Picture: NSManagedObject {
}
// this how your "Picture+CoreDataProperties.swift" looks like
import Foundation
import CoreData
extension Picture {
#nonobjc public class func fetchRequest() -> NSFetchRequest<Picture> {
return NSFetchRequest<Picture>(entityName: "Picture")
}
#NSManaged public var pic: String?
#NSManaged public var id: Int64
}
extension Picture : Identifiable {
}
I have used below extension to get currentTimeStamp as we will need unique ID for each of our coreData object, we will pass currentTimeStamp as ID to be unique.
// MARK: - Get the Current Local Time and Date Timestamp
source: https://stackoverflow.com/questions/46376823/ios-swift-get-the-current-local-time-and-date-timestamp
extension Date {
static var currentTimeStamp: Int64{
return Int64(Date().timeIntervalSince1970 * 1000)
}
}
I have made CRUD functions in DataBaseHelper.swift file
// this "DataBaseHelper" Class
import Foundation
import UIKit
import CoreData
class DataBaseHelper {
// MARK: - Get Context
class func getContext() -> NSManagedObjectContext{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
return appDelegate.persistentContainer.viewContext
}
static let shareInstance = DataBaseHelper()
let context = getContext()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Picture")
// MARK: - Save Images
func saveImage(picString: String, id: Int64 = Date.currentTimeStamp) {
// here I have passed id = Date.currentTimeStamp, as we need unique ID for each of our object in coreData and Date.currentTimeStamp will always give unique integer. we will use this ID to update and delete particular object.
let entity = NSEntityDescription.entity(forEntityName: "Picture", in: context)!
let image = NSManagedObject(entity: entity, insertInto: context)
image.setValue(picString, forKey: "pic") // key should be same as the attributes taken in coreData Table.
image.setValue(id, forKey: "id") // key should be same as the attributes taken in coreData Table.
do {
try context.save()
print("Images saved in coreData")
print("imageString: \(picString), id: \(id)") // this will print your entered (saved) object in coreData
} catch let error {
print("Could not save images: \(error.localizedDescription)")
}
}
// MARK: - fetch Images
func fetchImages() -> [Picture] {
var arrImages = [Picture]()
fetchRequest.returnsObjectsAsFaults = false
do {
arrImages = try context.fetch(fetchRequest) as? [Picture] ?? [Picture]()
print("Images while fetching from coreData: \(arrImages)") // this will print all objects saved in coreData in an array form.
} catch let error {
print("Could not fetch images: \(error.localizedDescription)")
}
return arrImages
}
// MARK: - fetch Images by ID
func fetchImagesByID(id: Int64) -> Picture {
fetchRequest.returnsObjectsAsFaults = false
let predicate = NSPredicate(format: "id == \(id)")
fetchRequest.predicate = predicate
let result = try? context.fetch(fetchRequest)
return result?.first as? Picture ?? Picture()
}
// MARK: - Update Image
func updateImage(object: Picture) {
let image = fetchImagesByID(id: object.id) // we will first fetch object by its ID then update it.
image.pic = object.pic
do {
try context.save()
print("Image updated in CoreData")
print("after updating Picture --> \(object)")
} catch let error {
print("Could not update Picture: \(error.localizedDescription)")
}
}
// MARK: - Delete Image
func deleteImage(id: Int64) {
let image = fetchImagesByID(id: id) // we will first fetch object by its ID then delete it.
context.delete(image)
do {
try context.save()
print("Image deleted from CoreData")
} catch let error {
print("Could not delete Image --> \(error.localizedDescription)")
}
}
}
here is our ViewController:
I have added 4 images in Assets folder.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var btnSaveImages: UIButton!
#IBOutlet weak var tableViewPicture: UITableView!
#IBOutlet weak var btnShowImages: UIButton!
var resultImages = [Picture]() // this an an instance of our model class (coreData)
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "CoreData Demo"
setUpTableView()
}
// MARK: - Save Images
func saveImagesInCoreData() {
// I have added 4 images in Assets folder, here we will save 3 images in CoreData
let image1 = "flower1"
let image2 = "flower2"
let image3 = "flower3"
DataBaseHelper.shareInstance.saveImage(picString: image1)
DataBaseHelper.shareInstance.saveImage(picString: image2)
DataBaseHelper.shareInstance.saveImage(picString: image3)
}
// MARK: - Fetch Images
func fetchImagesFromCoreData() {
resultImages = DataBaseHelper.shareInstance.fetchImages() // this will give fetched images
}
// MARK: - Set Up TableView
func setUpTableView () {
tableViewPicture.delegate = self
tableViewPicture.dataSource = self
}
// MARK: - Button Save Images Event
#IBAction func btnSaveImages_Event(_ sender: UIButton) {
saveImagesInCoreData() // save images in CoreData
}
// MARK: - Button Show Images Event
#IBAction func btnShowImages_Event(_ sender: UIButton) {
fetchImagesFromCoreData() // fetch Images from CoreData
self.tableViewPicture.reloadData() // reload tableView
}
}
// MARK: - Extesnion TableViewDelegate and TableViewDataSource
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return resultImages.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell") ?? UITableViewCell()
cell.imageView?.image = UIImage(named: resultImages[indexPath.row].pic ?? "")
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
let editAction = UITableViewRowAction(style: .default, title: "Edit") { (action, indexPath) in
print("Action Edit")
// here we will edit image of selected row in our tableView, we will update selected row with new image that is "flower4".
let image4 = "flower4"
self.resultImages[indexPath.row].pic = image4
DataBaseHelper.shareInstance.updateImage(object: self.resultImages[indexPath.row]) // update image of selected row in tableView
self.tableViewPicture.reloadData()
}
editAction.backgroundColor = .lightGray
let deleteAction = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
print("Action Delete")
// here we will delete an object of selected row in our tableView.
DataBaseHelper.shareInstance.deleteImage(id: self.resultImages[indexPath.row].id) // delete object of selected row in tableView
self.resultImages.remove(at: indexPath.row) // remove from resultImages array
self.tableViewPicture.reloadData()
}
return [deleteAction, editAction]
}
}
if you have doubt feel free to ask !

errors in swift Value of type 'URLSession' has no member 'request'

I am receiving three errors in my viewController and I can not figure out how to fix them these errors are 1.) extension Declaration is only valid at file scope, 2.)Value of type 'Unable to infer type of a closure parameter 'result' in the current context ' 3.) URLSession has no member 'request'. None of these errors make any sense to me because I have already defined result as a member of URLSession. Im not sure if Xcode is glitching, or if these errors are present in my code and if so can anyone point them out and how to fix?
import UIKit
import Foundation
enum NetworkError: Error {
case badRequest
case decodingError
}
struct Category: Codable {
let CategoryId: String
let CategoryThumb: String
let CategoryDescription: String
let categories: [Category]
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
struct Constants {
static let categoriesurl = URL(string: "https://www.themealdb.com/api/json/v1/1/categories.php")
static let filterListurl = URL(string: "https://www.themealdb.com/api/json/v1/1/filter.php?c=Beef")
static let mealByIdurl = URL(string: "https://www.themealdb.com/api/json/v1/1/lookup.php?i=52874")
}
//create table view to test results from API endpoint
let table: UITableView = {
let table = UITableView()
table.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
return table
}()
private var categories: [Category] = []
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(table)
table.delegate = self
table.dataSource = self
fetch()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
table.frame = view.bounds
}
func fetch() {
URLSession.shared.request(url: Constants.categoriesurl, returning: [Category].self
) {[weak self] result in
switch result {
case.success(let category):
DispatchQueue.main.async {
self?.category = category
self?.table.reloadData()
}
case.failure(let error):
print(error )
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categories.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = categories[indexPath.row].CategoryId
return cell
}
}
extension URLSession {
func request<T: Codable>(url: URL?,returning: T.Type,completion: #escaping (Result<T, Error>) -> Void) {
guard let url = url else {
//we create a enum for network error that will return an error if the API end point is a bad request,or if unable decoding the Json data
//Create a urls that fetches the data from each API end points
NetworkError.badRequest
return
}
let task = dataTask(with: url) {data, _, error in
guard let data = data else {
if let error = error {
NetworkError.badRequest
} else {
NetworkError.decodingError
}
return
} //if your data is return sucessfully from the API
do {
let Result = try! JSONDecoder().decode(returning, from: data)
completion(.success(Result))
}
catch {
NetworkError.badRequest
} //if the data does not return an error will be met
}
task.resume()
}
}
}
You're declaring an extension within the scope of a struct declaration. Your extension has to be declared outside of any other scope.
Because you extension was rejected, The system doesn't know what kind of parameter request should take and since you haven't declared the type of result inside the closure, it has no way to infer what what type it should have and the error message tells you just that
URLSession does not have a member named request because your extension was rejected (because of error #1).
The first step to fix this would be to move your extension outside of the scope of struct Category
extension Declaration is only valid at file scope -
Extension go inside a struct or a class, here you are declaring urlSession extension inside Category struct, please declare it outside.
Value of type 'Unable to infer type of a closure parameter 'result' in the current context ' - Please let us know the line of error, mostly this type of error would require to handle do-try-catch.
When the extension is placed outside the struct, this error would go.

How to binding data in swift?

I'm going to show the view the data I got from the server. An error occurred while developing using Rxswift and MVVM. The id value must be received from the product model, and an error occurs in this part.
extension SelectViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print("Tap")
let detailVC = DetailViewController()
detailVC.product = products[indexPath.row]
detailVC.productId = products[indexPath.row].id
self.navigationController?.pushViewController(detailPassVC, animated: true)
}
}
This is the code for the part that passes the id value. detailVC.product = products[indexPath.row]An error occurs in this area. error message is "Thread 1: Fatal error: Index out of range"
var products:[ProductModel] = []
var product = ProductModel()
var productId = Int()
func initViewModel() {
let input = DetailViewModel.Input(loadDetailData: getData.asSignal(onErrorJustReturn: ()), id: productId)
let output = viewModel.transform(input: input)
output.loadDetail.asObservable().bind(onNext: { data in
self.infoLabel.text = data?.detailDescription
self.passView.setData(data!)
self.secondView.setData(data!)
self.fareView.setData(data!)
self.totalLabel.text = totalPrice(data!)
}).disposed(by: disposeBag)
}
This is the code for the part where the view model is bound.
And This is my viewmodel code
class DetailViewModel: BaseViewModel {
private let repo = ProductRepository()
private let disposeBag = DisposeBag()
struct Input {
let loadDetailData: Signal<Void>
let id: Int
}
struct Output {
let loadDetail: Driver<DetailModel?>
let error: Driver<String?>
}
func transform(input: Input) -> Output {
let loadDetail = PublishSubject<DetailModel?>()
let msg= PublishSubject<String?>()
input.loadDetailData.asObservable()
.flatMap { self.productRepo.detailProduct(input.id)}
.subscribe(onNext: { data in
switch data {
case let .success(detail):
loadDetail.onNext(detail)
default:
errorMessage.onNext("load fail")
}
}).disposed(by: disposeBag)
return Output(loadDetail: loadDetail.asDriver(onErrorJustReturn: nil),error: msg.asDriver(onErrorJustReturn: nil))
}
}
How can I send the ID value?

Getting data out of a struct for use in a table view

I'm unable to get a struct containing vars loaded from JSON into a format suitable for a table view
I've been playing around with this code for a while, done plenty of reading but I'm just plain stuck. I can get data from the server fine and print it to the console. I notice that the data is printed as KEY: "value" rather than "KEY":"value" and that might have something to do with it. Also as the code is right now I can count the number of rows correctly and display the value of FIRST in the table view. What I can't figure out is how to access the other variables for display. Any help is greatly appreciated!
import Cocoa
class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
static var globalPatientInstance: [Patient] = []
var gotJSON: ([Patient], Error?) -> Void = { (patients, error) in
print("patients from gotJSON: \(patients)")
globalPatientInstance = patients
// this returns an error: "Type 'Patient' does not conform to protocol 'Sequence'"
/*
for (key, value) in patients[0] {
println("\(key) -> \(value)")
tableArray.append(Objects(sectionName: key, sectionObjects: value))
}
*/
print("patients from gotJSON: \(globalPatientInstance[0])")
}
#IBOutlet var tableView: NSTableView!
#IBAction func button(_ sender: Any) {
self.tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.delegate = self as NSTableViewDelegate
self.tableView.dataSource = self
let url = URL(string: "http://172.16.1.25/backend/returnA")
let returnA = URLRequest(url: url!)
retrieveJSON(with: returnA, completionHandler: gotJSON)
self.tableView.reloadData()
}
func retrieveJSON(with request: URLRequest, completionHandler: #escaping ([Patient], Error?) -> Void) {
// set up the session
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
// make the request
let task = session.dataTask(with: request as URLRequest) {
// completion handler argument
(data, response, error) in
// completion handler
guard let data = data else {
print("Did not recieve data")
completionHandler([], error)
return
}
do {
let decoder = JSONDecoder()
let patients = try decoder.decode(Array<Patient>.self, from: data)
// print(Patient)
completionHandler(patients, error)
}
catch let err {
print("Err", err)
completionHandler([], error)
}
}
task.resume()
}
func numberOfRows(in tableView: NSTableView) -> Int {
return ViewController.globalPatientInstance.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
var result: NSTableCellView
result = tableView.makeView(withIdentifier: (tableColumn?.identifier)!, owner: self) as! NSTableCellView
result.textField?.stringValue = ViewController.globalPatientInstance[row].FIRST
return result
}
}
This code runs fine. The array contains three structs and the value of FIRST is successfully displayed in the table view when the button is pressed.

Can't access array values outside of function - Swift

I'm trying to query my Parse database in order to search for a username and show all posts related to the username. The posts are split into two fields and I "paste" them back together inside the function.
func searchDataBase() -> ([String]) {
if let username = PFUser.currentUser()?.username {
userHeading.text = username + "'s Profile"
var query = PFQuery(className:"Wish")
query.whereKey("user", equalTo:username)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) wishes.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
//println(object.objectId)
var parseID = object.objectId!
var query = PFQuery(className:"Wish")
query.getObjectInBackgroundWithId(parseID) {
(detailedWish: PFObject?, error: NSError?) -> Void in
if error == nil {
let partOne = detailedWish!["wishFieldOne"] as! String
let partTwo = detailedWish!["wishFieldTwo"] as! String
let fullWish = "I wish I " + partOne + " when I " + partTwo
self.wishes.append(fullWish)
} else {
println(error)
}
}
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
} else {
println("No user logged in")
}
return wishes
}
After the function above runs, I want to place the user's posts inside a UITableView:
//TABLE VIEW FUNCTIONS
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
searchDataBase()
return wishes.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = recentPosts.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! UITableViewCell
searchDataBase()
let row = indexPath.row
cell.textLabel?.text = wishes[row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
recentPosts.deselectRowAtIndexPath(indexPath, animated: true)
searchDataBase()
let row = indexPath.row
println(wishes[row])
}
When I build the app the UITableView doesn't show the posts I queried in the searchDataBase function. If I println(wishes) immediately after the array is appended, it works, but when I print the array outside of the function it is empty. How can I make the contents of the wishes array accessible outside the function - after the query is successful?
Thanks for your help!
This is an odd approach. Your calling searchDataBase() on every tableView method. You surely dont want to make a call to parse every time? Also your searchDataBase() method doesnt need to return an array. You can simply just append the results to this array and reload your table when complete. Im assuming this would be a much better approach for you.
So, my solution to you would be to remove your searchDatabase() function call from all your tableView methods and to place it inside your viewDidLoad(). Also you should change you searchDataBase() to look like so
func searchDataBase(){
if let username = PFUser.currentUser()?.username {
userHeading.text = username + "'s Profile"
var query = PFQuery(className:"Wish")
query.whereKey("user", equalTo:username)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) wishes.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
//println(object.objectId)
var parseID = object.objectId!
var query = PFQuery(className:"Wish")
query.getObjectInBackgroundWithId(parseID) {
(detailedWish: PFObject?, error: NSError?) -> Void in
if error == nil {
let partOne = detailedWish!["wishFieldOne"] as! String
let partTwo = detailedWish!["wishFieldTwo"] as! String
let fullWish = "I wish I " + partOne + " when I " + partTwo
self.wishes.append(fullWish)
} else {
println(error)
}
}
}
}
self.tableView.reloadData() // <- This will populate your tableView with your wishes
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
} else {
println("No user logged in")
}
}
You can't do what you are trying to do that way.
What you need to do is to rewrite your searchDataBase method to take a completion closure as a parameter. Then in the completion block to your call to query.getObjectInBackgroundWithId, build your result array and pass to the searchDataBase completion closure.
searchDataBase() performs the returns the array. Where's the variable wishes that you're accessing?
Instead:
let wishes = searchDataBase()
and then you'll have the array for your table view delegate functions.