UITablecontroller and UIViewController issues - Swift - ios

I am new here and to coding and I need some help with a project that I'm currently stuck on.
I have built an app containing UITableView that first displays body areas (Gastro, cardio, respiratory, etc), the second displays more detailed features on the first (in gastro the table will display stomach, small intestine, colon, etc) and then the the UIViewController will have the more detailed info on the stomach etc.
I have this working all ok but one problem has arose. The UIViewController, regardless of which option is selected in the first table, displays the same info, i.e I get results for gastro even after selecting cardio etc.
The UIviewcotrollers have the storyboards identifiers G1, G2 etc as shown in 'Subchapters' under identities.
I want G1 and the rest of the G series to only display gastro info and then create new view controllers for cardio, C1, C2 etc and so on for the rest of the chapters.
Below is my code. I hope someone could help with this. I would really appreciate it!
import UIKit
class Chapters: UITableViewController {
var ChaptersArray = [String]()
var SubchaptersArray = [secondTable]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// chapter names
ChaptersArray = ["Gastrointestinal","Cardiovascular","Respiratory","Central Nervous System", "Infections"]
// subcharpter names
SubchaptersArray = [secondTable(SecondTitle: ["Gas1", "Gas2", "Gas3", "Gas4"]),
secondTable(SecondTitle: ["Card1", "Card2", "Card3", "Card4"]),
secondTable(SecondTitle: ["Res1", "Res2", "Res3", "Res4"])]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell!
cell.textLabel?.text = ChaptersArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ChaptersArray.count
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let destViewController = segue.destinationViewController as! Subchapters
var secondTableArrayTwo : secondTable
secondTableArrayTwo = SubchaptersArray[indexPath.row]
destViewController.SubChaptersArray = secondTableArrayTwo.SecondTitle
}
}
import UIKit
class Subchapters: UITableViewController {
var SubChaptersArray = [String]()
var identities = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
identities = ["G1", "G2", "G3", "G4"]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SubChaptersArray.count
}
override func tableView(tableview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCellWithIdentifier("SecondCell") as UITableViewCell!
cell.textLabel?.text = SubChaptersArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let vcName = identities[indexPath.row]
let viewcontroller = storyboard?.instantiateViewControllerWithIdentifier(vcName)
self.navigationController?.pushViewController(viewcontroller!, animated: true)
}
}
I have searched google and here for an answer but could find nothing to help, so any explanations as to how to fix this problem would be great and much appreciated.
Thanks
Mark

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.

SWIFT 4 Detail Disclosure

I'm new to programming and have just started with a deep dive into SWIFT and iOS development.
I've been stuck on a problem for over a few hours now and would be much obliged if someone could answer it. The assignment is bucket list and we have to built a basic app that uses two Table views (one dynamic and one static) to display a list of "bucket list" items using navigator controllers and modal display. In our first assignment, we were allowed to use two segues for the edit and save functionality but in the new assignment, we are being asked to refactor and use one segue with the hint being that we should use sender information. The present code uses two segues as I have not figured out how to refactor. As a note, we are using the accessory Detail Disclosure to bring up list items for edit. This is where I am getting stuck. From what I've been able to read, I understand the Disclosure Detail button is not a "true button" rather it is part of the index path. While I think I understand what needs to be done from a conceptual level, I am having a hell of a time actually solving the problem. Thanks in advance.
import UIKit
class BucketListViewController: UITableViewController,
AddItemTableViewControllerDelegate {
var items = ["awesome","lessawesome","great"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("selected")
}
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
performSegue(withIdentifier: "EditItemSegue", sender: indexPath)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
items.remove(at: indexPath.row)
tableView.reloadData()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddItemSegue"{
let navigationController = segue.destination as! UINavigationController
let addItemTableViewController = navigationController.topViewController as! AddItemTableViewController
addItemTableViewController.delegate = self
}else if segue.identifier == "EditItemSegue"{
let navigationController = segue.destination as! UINavigationController
let AddItemTableViewController = navigationController.topViewController as! AddItemTableViewController
AddItemTableViewController.delegate = self
let indexPath = sender as! NSIndexPath
let item = items[indexPath.row]
AddItemTableViewController.item = item
AddItemTableViewController.indexPath = indexPath
}
}
func cancelButtonPressed(by controller: AddItemTableViewController) {
dismiss(animated: true, completion: nil)
}
func itemSaved(by controller: AddItemTableViewController, with text:String, at indexPath: NSIndexPath?) {
if let ip = indexPath {
items[ip.row] = text
}else{
items.append(text)
}
tableView.reloadData()
dismiss(animated: true, completion: nil)
}
}
AddItemTableViewControllerDelegate
import Foundation
import UIKit
protocol AddItemTableViewControllerDelegate: class {
func itemSaved(by controller: AddItemTableViewController, with text:String, at indexPath: NSIndexPath?)
func cancelButtonPressed(by controller: AddItemTableViewController)
}
AddItemTableViewController
import UIKit
class AddItemTableViewController: UITableViewController {
weak var delegate: AddItemTableViewControllerDelegate?
var item: String?
var indexPath: NSIndexPath?
#IBOutlet weak var itemTextField: UITextField!
#IBAction func cancelButtonPressed(_ sender: UIBarButtonItem) {
delegate?.cancelButtonPressed(by: self)
}
#IBAction func saveButtonPressed(_ sender: UIBarButtonItem) {
let text = itemTextField.text!
delegate?.itemSaved(by: self, with: text, at: indexPath)
}
override func viewDidLoad() {
super.viewDidLoad()
itemTextField.text = item
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

UiTableView to UiTableView to UiViewcontroller swift

I am new here and to coding and I need some help with a project that I'm currently stuck on.
I have built an app containing UITableView the first displays body areas (Gastro, cardio, respiratory, etc), the second displays more detailed features on the first (in gastro the table will display stomach, small intestine, colon, etc) and then the the UIViewController will have the more detailed info on the stomach etc.
I have this working all ok but one problem has arose. The UIViewController, regardless of which option is selected in the first table, displays the same info, i.e I get results for gastro even after selecting cardio etc.
Below is my code. I hope someone could help with this. I would really appreciate it!
import UIKit
class Chapters: UITableViewController {
var ChaptersArray = [String]()
var SubchaptersArray = [secondTable]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// chapter names
ChaptersArray = ["Gastrointestinal","Cardiovascular","Respiratory","Central Nervous System", "Infections"]
// subcharpter names
SubchaptersArray = [secondTable(SecondTitle: ["Gas1", "Gas2", "Gas3", "Gas4"]),
secondTable(SecondTitle: ["Card1", "Card2", "Card3", "Card4"]),
secondTable(SecondTitle: ["Res1", "Res2", "Res3", "Res4"])]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell!
cell.textLabel?.text = ChaptersArray[indexPath.row]
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ChaptersArray.count
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let destViewController = segue.destinationViewController as! Subchapters
var secondTableArrayTwo : secondTable
secondTableArrayTwo = SubchaptersArray[indexPath.row]
destViewController.SubChaptersArray = secondTableArrayTwo.SecondTitle
}
}
import UIKit
class Subchapters: UITableViewController {
var SubChaptersArray = [String]()
var identities = [String]()
var data = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
identities = ["G1","G2","G3","G4"]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SubChaptersArray.count
}
override func tableView(tableview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCellWithIdentifier("SecondCell") as UITableViewCell!
cell.textLabel?.text = SubChaptersArray[indexPath.row]
return cell
}
// ignore
// override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// let destViewController = segue.destinationViewController as! DrugNotes
// destViewController.FirstString = "drug data: need to seperate out to seperate pages" }
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let vcName = identities[indexPath.row]
let viewcontroller = storyboard?.instantiateViewControllerWithIdentifier(vcName)
self.navigationController?.pushViewController(viewcontroller!, animated: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

UITableView Segue To View Controller NOT Working

In my app I have a table view that lists out friend's names and when you click on the names in the table view it is supposed to perform a segue into another view controller that stores this friends information. Although I can click on the rows, it is not performing the segue into the friend information view controller. Any ideas on how to fix this? Thanks in advance! :)
#IBOutlet weak var tableView: UITableView!
var friends = ["A","B","C","D"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.dataSource = self
self.tableView.dataSource = self
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.friends.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let friend = self.friends[indexPath.row]
cell.textLabel!.text = friend
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("detailSegue", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let listVC = segue.destinationViewController as! FriendDetailViewController
}
You should assign in the tableView delegate to the view controller
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after
loading the view, typically from a nib.
self.tableView.dataSource = self
self.tableView.delegate = self
}
And of course add this :
class ViewController : ... , UITableViewDelegate

Display 2nd 'column' value of array in separate screen based on selected row in swift

I just started to learn swift and trying to make a simple app in which I have created a UITableView with terms
('Term 1' till 'Term 15') and want to display a detail description of the term
('Detail 1' till 'Detail 15') when selected in the table in a separate view.
Using the available online tutorials, I've created the code below but have difficulties to complete and am only able to display a fixed string.
Any suggestions how best to proceed are welcome:
import UIKit
class FirstTableViewController: UITableViewController{
let Datasource = [("Term 1","Detail 1"),("Term 2","Detail 2"),("Term 3","Detail 3"),("Term 4","Detail 4"),("Term 5","Detail 5"),("Term 6","Detail 6"),("Term 7","Detail 7"),("Term 8","Detail 8"),("Term 9","Detail 9"),("Term 10","Detail 10"),("Term 11","Detail 11"),("Term 12","Detail 12"),("Term 13","Detail 13"),("Term 14","Detail 14"),("Term 15","Detail 15")]
//MARK -> Table Structure
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.Datasource.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var Cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
var (Id, Detail) = Datasource[indexPath.row]
Cell.textLabel?.text = Id
return Cell
}
//MARK -> Link to view term details on seperate screen
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var DestinationViewController = segue.destinationViewController as! DetailedTableViewController
DestinationViewController.DetailedTerm = "DISPLAY 2ND COLUMN OF DATASOURCE ARREY"
}
//MARK -> Standard methods
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

Resources