Gets number of rows but doesn't print - ios

I have a program written in Swift 3, that grabs JSON from a REST api and appends it to a table view.
Right now, I'm having troubles with getting it to print in my Tableview, but it does however understand my count function.
So, I guess my data is here, but it just doesn't return them correctly:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, HomeModelProtocal {
#IBOutlet weak var listTableView: UITableView!
func itemsDownloaded(items: NSArray) {
feedItems = items
self.listTableView.reloadData()
}
var feedItems: NSArray = NSArray()
var selectedLocation : Parsexml = Parsexml()
override func viewDidLoad() {
super.viewDidLoad()
self.listTableView.delegate = self
self.listTableView.dataSource = self
let homeModel = HomeModel()
homeModel.delegate = self
homeModel.downloadItems()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier: String = "BasicCell"
let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
let item: Parsexml = feedItems[indexPath.row] as! Parsexml
myCell.textLabel!.text = item.title
return myCell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return feedItems.count
}
override func viewDidAppear(_ animated: Bool) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Are you by any chance able to see the error that I can't see?
Note. I have not added any textlabel to the tablerow, but I guess that there shouldn't be added one, when its custom?

Try this code:
override func viewDidLoad() {
super.viewDidLoad()
print(yourArrayName.count) // in your case it should be like this print(feedItems.count)
}

Related

Getting a EXC_BAD_ACCESS when trying to initialize my custom Cell in TableViewController

My application fetches data from a mock API.
Using a custom cell, I display the names of authors on my landing page viewController.
When I click on a cell, it takes that author's book information to display on a 2nd TableViewController.
But even though the implementation is the same as for the landing page. My app freezes until I get a EXC_BAD_ACCESS error
It seems like it's stuck in an infinite loop, but without a proper error, it's hard to know why.
Infinite Loop?
I can get this to work without using a custom cell, but then I cannot display all the information I want (only book title or release date), so the data is there.
import UIKit
class BooksTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var pages: UILabel!
#IBOutlet weak var release: UILabel!
// #IBOutlet var coverImage: UIImageView!
static let cellIdentifier = "BooksTableViewCell"
//
override func awakeFromNib() {
super.awakeFromNib()
}
static func nib() -> UINib {
return UINib(nibName: "BooksTableViewCell", bundle: nil)
}
//MARK: configure
public func configure(with viewModel: BooksCellViewModel) {
name.text = viewModel.name
pages.text = String(viewModel.pages)
release.text = viewModel.release
// coverImage.image = viewModel.image
}
}
import UIKit
class BooksTableViewController: UITableViewController {
var books: [Book] = []
var authorName: String = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(BooksTableViewCell.nib(), forCellReuseIdentifier: BooksTableViewCell.cellIdentifier)
tableView.delegate = self
tableView.dataSource = self
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return authorName
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return books.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("Hello1")
let cell = tableView.dequeueReusableCell(withIdentifier: BooksTableViewCell.cellIdentifier, for: indexPath) as! BooksTableViewCell
print("Hello2")
let model = books[indexPath.row]
cell.configure(with: BooksCellViewModel(name: model.title, pages: model.pages, release: model.releaseDate))
return cell
}
}
The landing page controller and cell is similar but works with no problems
import UIKit
class LandingTableViewController: UITableViewController {
let parser = DataAPI()
var authors = [Author]()
var books = [Book]()
var authorName = ""
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(AuthorTableViewCell.nib(), forCellReuseIdentifier: AuthorTableViewCell.cellIdentifier)
tableView.delegate = self
tableView.dataSource = self
parser.getData {
data in
self.authors = data
//Reload UI on Main thread:
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "List of Authors"
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return authors.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: AuthorTableViewCell.cellIdentifier, for: indexPath) as! AuthorTableViewCell
let model = authors[indexPath.row]
cell.configure(with: AuthorCellViewModel(name: model.authorName))
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
books = authors[indexPath.row].books
authorName = authors[indexPath.row].authorName
performSegue(withIdentifier: "Show Books", sender: nil)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if (segue.identifier == "Show Books") {
let showBooksViewController: BooksTableViewController = segue.destination as! BooksTableViewController
showBooksViewController.books = books
showBooksViewController.authorName = authorName
}
}
}
I was able to fix the issue by correctly naming my variables. I needed to be using releaseDate not release as per my model object.

My custom cells are not showing up in my tableview

So I have been trying to get my custom cells to show up on this tableview, but I am not sure as to why they are not showing up
I have already checked other stack overflow questions and tried their fixes, to no avail. Please ignore the aws stuff as you can see I have the text hard coded so I can just get them to appear for now.
This is the code within the class holding the tableview
import Foundation
import AWSDynamoDB
import AWSCognitoIdentityProvider
import UIKit
// this will be the main feed class showing the user data
class UserDetailTableViewController : UITableViewController {
// attributes for the custome cell
#IBOutlet weak var testing: UITextField!
#IBOutlet var Table: UITableView!
var response: AWSCognitoIdentityUserGetDetailsResponse?
var user: AWSCognitoIdentityUser?
var pool: AWSCognitoIdentityUserPool?
var questiondata : Array<Phototext> = Array()
override func viewDidLoad() {
tableView.delegate = self
tableView.dataSource = self
super.viewDidLoad()
self.pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey)
if (self.user == nil) {
self.user = self.pool?.currentUser()
}
// grabbing data from our aws table
updateData()
self.refresh()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setToolbarHidden(true, animated: true)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setToolbarHidden(false, animated: true)
}
#IBAction func Questions(_ sender: Any) {
performSegue(withIdentifier: "ask", sender: self)
}
// MARK: - IBActions
#IBAction func signOut(_ sender: AnyObject) {
self.user?.signOut()
self.title = nil
self.response = nil
self.refresh()
}
// reloads the prior view
func refresh() {
self.user?.getDetails().continueOnSuccessWith { (task) ->
AnyObject? in
DispatchQueue.main.async(execute: {
self.response = task.result
self.title = self.user?.username
// saving the user name from the main menu
username123 = self.user?.username! ?? "broken"
})
return nil
}
}
// function that calls to our aws dynamodb to grab data from the
// user
//and re update questions
// the array list
func updateData(){
let scanExpression = AWSDynamoDBScanExpression()
scanExpression.limit = 20
// testing to grabt the table data upon startup
let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
dynamoDBObjectMapper.scan(Phototext.self, expression:
scanExpression).continueWith(block: {
(task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Any? in
if let error = task.error as NSError? {
print("The request failed. Error: \(error)")
} else if let paginatedOutput = task.result {
// passes down an array of object
for Photo in paginatedOutput.items as! [Phototext] {
// loading in the arraylist of objects
// adding the objects to an arraylist
self.questiondata.append(Photo)
}
DispatchQueue.main.async {
//code for updating the UI
}
}
return ()
})
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// returning the number of rows
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:
"Questionpost", for: indexPath) as! QuestionCell
cell.QuestionText.text = "call it"
cell.Subject.text = "a day"
return cell
}
}
}
Here is the code for the QuestionCell class
import UIKit
class QuestionCell: UITableViewCell {
#IBOutlet weak var Subject: UILabel!
#IBOutlet weak var QuestionText: UITextView!
}
The cell class is called QuestionCell and the identifier I left on the cell in the storyboard is Questionpost
Here is a photo of my story board:
I have fixed it by declaring an extension with the proper types.
extension UserDetailTableViewController: UITableViewDataSource,UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// returning the number of rows
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Questionpost", for: indexPath) as! QuestionCell
cell.QuestionText.text = "call it"
cell.Subject.text = "a day"
return cell
}}
good explanation of what's going on, you need to conform to the UITableViewDataSource and UITableViewDelegate when you inbed a tableview.
Redundant conformance of TableView to protocol UITableViewDataSource with Xib Files

How to Update UITableView With Swift?

I'm trying to populate a table view from a SQlite database. Tickets get printed in the console, but nothings shows up on the table view. What's the proper way to update and refresh? Here is my code. Thanks!
import UIKit
import SQLite
class TicketTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tickets = [String]()
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let dm = DatabaseManager.shared
let db = dm.db!
do {
for row in try db.prepare(dm.tickets) {
let ticket = row[dm.pick]
tickets.append(ticket)
debugPrint(ticket)
}
table.reloadData()
} catch {}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tickets.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ticket")!
cell.detailTextLabel!.text = tickets[indexPath.row]
return cell
}
}
Dynamic table views needs to know their delegate and datasource. If you didn't set the delegate and datasource, you can add them programmatically in your viewDidLoad function. Like this:
override func viewDidLoad() {
super.viewDidLoad()
//Set delegate and datasource
table.delegate = self
table.dataSource = self
let dm = DatabaseManager.shared
let db = dm.db!
do {
for row in try db.prepare(dm.tickets) {
let ticket = row[dm.pick]
tickets.append(ticket)
debugPrint(ticket)
}
table.reloadData()
} catch {}
}

Error while trying to download Image URL from Firebase database using Swift3

Would you please help me to find the error in my code? I have an image URL in my database and I'm trying to download it and display it in a TableView, but it shows nil value.
This is my Class:
class Post : NSObject {
var Posts : String!
var Image : String!
}
and this is My TableView.
import UIKit
import FirebaseDatabase
import SDWebImage
class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate {
#IBOutlet weak var MyImageView: UIImageView!
#IBOutlet weak var tableView: UITableView!
var Ref:FIRDatabaseReference?
var Handle:FIRDatabaseHandle?
var myarray = [Post]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.delegate = self
tableView.dataSource = self
}
override func viewDidAppear(_ animated: Bool) {
Ref=FIRDatabase.database().reference()
Handle = Ref?.child("Posts").observe(.childAdded ,with: { (snapshot) in
let post = snapshot.value as? Post
self.myarray.append(post!)
self.tableView.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return myarray.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as? TableViewCell {
// cell?.textLabel?.text = PostData[indexPath.row]
let url = URL(string : self.myarray [(indexPath as NSIndexPath).row].Image!)
cell.MyImage.sd_setImage(with: url)
return cell
}else{
let cell = TableViewCell()
let url = URL(string : self.myarray [(indexPath as NSIndexPath).row].Image!)
cell.MyImage.sd_setImage(with: url)
return cell
}
}
}

How to add a cell to my Table View dynamically using a button

I am trying to add a cell to my table view with a button. Everything I have read and watched suggests that what I have written should work, but it doesn't. Any suggestions?
import UIKit
class RootViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
private var cellPointSize: CGFloat!
private var albumsList: AlbumList!
private var albums:[Album]!
private let albumCell = "Album"
#IBOutlet var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
let preferredTableViewFont = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cellPointSize = preferredTableViewFont.pointSize
albumsList = AlbumList.sharedAlbumList
albums = albumsList.albums
self.myTableView.dataSource = self
self.myTableView.delegate = self
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return albums.count
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Albums"
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCellWithIdentifier(albumCell, forIndexPath: indexPath) as! UITableViewCell
//cell.textLabel?.font = fontForDisplay(atIndexPath: indexPath)
cell.textLabel?.text = albums[indexPath.row].name
cell.detailTextLabel?.text = albums[indexPath.row].artist
return cell
}
#IBAction func addNewAlbumAction(sender: UIBarButtonItem) {
var newAlbum = Album(nameIn: "New Title", yearIn: "New Year", artistIn: "New Artist", labelIn: "New Label")
albumsList.addAlbum(newAlbum)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.myTableView.reloadData()
})
}
func saveData(albumObject: Album) {
var archiveArray = NSMutableArray(capacity: albums.count)
for a in albums {
var albumEncodedObject = NSKeyedArchiver.archivedDataWithRootObject(a)
archiveArray.addObject(albumEncodedObject)
}
var userData = NSUserDefaults()
userData.setObject(archiveArray, forKey: "albums")
userData.synchronize()
}
My albums array is adding the data correctly. I can see the albums in the debugger. The delegate methods are never being called after the first time when the app loads. Any ideas?
in tableView:numberOfRowsInSection:, it returns albums.count
but when the button is pressed, you add the new album to albumsList
The problem is, albums will not get update.
So I think you should return albumsList.albums.count instead.
and in tableView:cellForRowAtIndexPath:, you modify the cell correspond to albumsList.albums[indexPath.row]

Resources