swift code error - swift

import UIKit
class ViewController: UITableViewController {
var animals = [Animal]()
override func viewDidLoad() {
super.viewDidLoad()
self.animals = [Animal(name: "개"),Animal(name: "강아지"),Animal(name: "고양이"),Animal(name: "멍멍이"),Animal(name: "물어")]
// 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 5
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
var animal = Animal.self
animal = animals[indexPath.row] //1
cell.textLabel?.text = animal.name //2
return cell //3
}
}
I am getting the following errors:
error is cannot assign value of type 'Animal' to type 'Animal Type'
error is instance member 'name' cannot be used on type 'Animal
unexpected non-void return value in void function

In your code above, "didSelectRowAtIndexPath" is called after you select certain cell, and it does not return anything. Instead, if you want to display the cell, use "cellForRowAtIndexPath".
class Animal {
var name: String
init(name: String) {
self.name = name
}
}
class ViewController: UIViewController {
var animals = [Animal]()
override func viewDidLoad() {
super.viewDidLoad()
self.animals = [Animal(name: "개"),Animal(name: "강아지"),Animal(name: "고양이"),Animal(name: "멍멍이"),Animal(name: "물어")]
}
}
extension ViewController: UITableViewDataSource {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
// This would works on your table view
var animal = animals[indexPath.row]
cell.textLabel?.text = animal.name
return cell
}
}

Related

Swift - when is data actually loaded in TableViewController

I'm very much a Swift beginner - am populating a table view from Firebase data.
In the table footer I want to display some calculated totals under the table columns. However when calling footerCell.configure(priceLines, isPortrait: isPortrait) the priceLines dictionary is still empty.
How to remedy this?
Thanks in advance, André Hartman, Belgium
import UIKit
import FirebaseDatabase
class ListTableViewController: UITableViewController {
var priceLines = [NSDictionary]()
var isPortrait = false
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ListTableViewController.rotated), name: UIDeviceOrientationDidChangeNotification, object: nil)
loadDataFromFirebase()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return priceLines.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("profileCell", forIndexPath: indexPath) as! PriceTableViewCell
cell.configure(priceLines, row: indexPath.row, isPortrait: isPortrait, source: "intraday")
return cell
}
override func tableView(tableView: UITableView,viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCellWithIdentifier("HeaderCell") as! CustomHeaderCell
headerCell.configure(isPortrait)
return headerCell
}
override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerCell = tableView.dequeueReusableCellWithIdentifier("FooterCell") as! CustomFooterCell
footerCell.configure(priceLines, isPortrait: isPortrait)
return footerCell
}
override func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 30.0
}
override func tableView (tableView:UITableView, heightForHeaderInSection section:Int) -> CGFloat
{
return 50.0;
}
// MARK:- Load data from Firebase
func loadDataFromFirebase() {
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
refInter.observeEventType(.Value, withBlock: { snapshot in
var tempItems = [NSDictionary]()
for item in snapshot.children {
let child = item as! FIRDataSnapshot
let dict = child.value as! NSDictionary
tempItems.append(dict)
}
self.priceLines = tempItems
self.tableView.reloadData()
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
})
}
func rotated()
{
let newDisplay = (UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation))
if(newDisplay != isPortrait){
self.tableView.reloadData()
}
isPortrait = newDisplay
}
}
The documentation clearly says that
When the table view is about to appear the first time it’s loaded, the
table-view controller reloads the table view’s data.
So, it will reload the table automatically somewhere between viewDidLoad and viewWillAppear. Your priceLines is empty at this point and will be populated with data only when the closure in the method loadDataFromFirebase is fired. I'm not sure when it happens in your case, but as you call implicitly reloadData then you should have already priceLines nonempty (of course if the results in the closure have some data)

Call dictionary in tableView of swift

How to call Dictionary values in tableView..
Getting error
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
#IBOutlet var tblView: UITableView!
var AnimalName = ["e":["Elephant","EEE"","l":["Lion","LL"],h":["Horse",huh"]]
var initial = Array(AnimalName.alKeys) //error in this line
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return AnimalName.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = AnimalName[indexPath.row] //how to call the cell
return cell
}
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
return initial // not getting output
}
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
return index // How to select
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{
#IBOutlet var tblView: UITableView!
var AnimalName = ["e":["Elephant","EEE"], "l":["Lion","LL"], "h":["Horse", "huh"]]
var initial: [String] = [] //error in this line
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.initial.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let animalsOfSection = self.AnimalName[self.initial[section]] {
return animalsOfSection.count
}
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
if let animal = self.AnimalName[self.initial[indexPath.section]]?[indexPath.row] {
cell.textLabel?.text = animal //how to call the cell
}
return cell
}
func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
return self.initial // not getting output
}
func tableView(tableView: UITableView, sectionForSectionIndexTitle title: String, atIndex index: Int) -> Int {
if let index = self.initial.indexOf(title) {
return index // How to select
}
return 0
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.initial = Array(self.AnimalName.keys).sort(<)
}
}
["Horse",huh"] should be ["Horse","huh"]
"EEE"" should be "EEE"]
"LL"],h" should be "LL"],"h"
var initial = Array(AnimalName.alKeys)
should be
var initial = Array(AnimalName.keys)
You shouldn't need SO to find and fix typos. Also, try Ctrl+Space after a period, it will propose the appropriate function names and help you avoid misnaming them.

When I click UISegmentedControl, make it change to UITableViewCell

How to call method
internal func segconChanged(segcon: UISegmentedControl, var text:String){
switch segcon.selectedSegmentIndex {
case 0:
print("whoo")
return text = "clicked Trainings"
case 1:
print("yeahh")
return text = "clicked Daily"
default:
break
}
}
from
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
?
I am beginner of swift.
I am using UISegmentedControl, and UITableView.
When I click UISegmentedControl, make it change to UITableViewCell.
Please look at inside of func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
I added segconChanged(UISegmentedControl(), text: "") to call method,
but I think this is wrong and actually doesnt work.
Please give me advice.
This is all code.
import UIKit
class TrainingLogViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTableView: UITableView!
#IBOutlet weak var segment: UISegmentedControl!
let tabLog: NSArray = ["Trainings", "Daily"]
override func viewDidLoad() {
super.viewDidLoad()
myTableView.delegate = self
myTableView.dataSource = self
segment.addTarget(self, action: "segconChanged:", forControlEvents: UIControlEvents.ValueChanged)
}
var text: String = ""
internal func segconChanged(segcon: UISegmentedControl, var text:String){
switch segcon.selectedSegmentIndex {
case 0:
print("whoo")
return text = "clicked Trainings"
case 1:
print("yeahh")
return text = "clicked Daily"
default:
break
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 10
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let text: String = ""
*segconChanged(UISegmentedControl(), text: "")
let cell = UITableViewCell(style: .Subtitle, reuseIdentifier: "LogTraining")
cell.textLabel?.text = text
cell.detailTextLabel?.text = "subtitle"
return cell
}
}
You dont need to call segconChanged() function manually as it will automatically be called when segment is changed. So just reload your tableview when segment is changed, check its index and populate data acccordingly i.e. in cellForRowAtIndexPath method.
Try this code :
import UIKit
class TrainingLogViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTableView: UITableView!
#IBOutlet weak var segment: UISegmentedControl!
let tabLog: NSArray = ["Trainings", "Daily"]
override func viewDidLoad() {
super.viewDidLoad()
myTableView.delegate = self
myTableView.dataSource = self
segment.addTarget(self, action: "segconChanged:", forControlEvents: UIControlEvents.ValueChanged)
}
func segconChanged(segcon: UISegmentedControl){
self.myTableView.reloadData()
switch segcon.selectedSegmentIndex {
case 0:
print("clicked Trainings")
case 1:
print("clicked Daily")
default:
break
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCellWithIdentifier("LogTraining", forIndexPath: indexPath)
cell.textLabel?.text = (self.segment.selectedSegmentIndex == 0) ? tabLog[0] : tabLog[1]
cell.detailTextLabel?.text = "subtitle"
return cell
}
}

Dynamic datasource/delegates for UITableView in swift

I need to set up different objects based on certain conditions as the datasource & delegate for table view.
But I am not able to assign tableview's datasource/delegate as it throws some errors.
Cannot assign a value of type NSObject? to a value of type UITableViewDelegate?
I did check this Q&A but this did not work.
var dataSourceDelegate:NSObject?
class RootViewController: UIViewController {
...
override func viewDidLoad() {
dataSourceDelegate = TableDataSourceDelegate()
// Table View
tableView = UITableView()
tableView!.setTranslatesAutoresizingMaskIntoConstraints(false)
tableView!.dataSource = dataSourceDelegate
// Cannot assign a value of type NSObject? to a value of type UITableViewDataSource?
tableView!.delegate = dataSourceDelegate
// Cannot assign a value of type NSObject? to a value of type UITableViewDelegate?
view.addSubview(tableView!)
// Constraints
var views:[String:UIView] = ["table":tableView!]
var hTableConstraint = "H:|[table]|"
var vConstraint = "V:|[table]|"
view.addConstraintsToView([hTableConstraint, vConstraint], view: view, viewVariables: views)
}
...
}
This is the datasource/delegate class
class TableDataSourceDelegate:NSObject, UITableViewDataSource, UITableViewDelegate {
// MARK: Datasource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return UITableViewCell()
}
// MARK: Delegates
}
NSObject? doesn't conforms to UITableViewDelegate, neither to UITableViewDataSource. You should create your protocol like
protocol GeneralDataSource: UITableViewDataSource, UITableViewDelegate {}
And then all data sources should conform that protocol.
class MyDataSource: NSObject, GeneralDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return UITableViewCell()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
}
Then you can use it like this
var myDataSource: GeneralDataSource?
override func viewDidLoad() {
super.viewDidLoad()
self.myDataSource = MyDataSource()
self.tableView.delegate = self.myDataSource
}
This is how your TableDataSourceDelegate should look like:
import UIKit
class TableDataSourceDelegate: NSObject {
}
extension TableDataSourceDelegate: UITableViewDataSource {
#objc func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
#objc func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "defaultCell")
cell.textLabel?.text = "test"
return cell
}
}
extension TableDataSourceDelegate: UITableViewDelegate {
// your delegate implementation here
}
And view controller implementation
import UIKit
// The typealias definition
typealias TVDataSourceDelegate = protocol<UITableViewDataSource, UITableViewDelegate>
class ViewController: UIViewController {
var dataSourceDelegate: TVDataSourceDelegate?
var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
dataSourceDelegate = TableDataSourceDelegate()
// Table View
tableView = UITableView()
tableView!.translatesAutoresizingMaskIntoConstraints = false
tableView!.dataSource = dataSourceDelegate
tableView!.delegate = dataSourceDelegate
view.addSubview(tableView!)
// other code ...
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Although, I would recommend to separate dataSource and delegate objects (e.g. put the delegate protocol conforming code into your view controller's code.

Saving values to UserDefults from Textfield in TableView : Swift

I am trying to save values from a tableview that users will input into the textfield, the problem is that I do not know how to access the new value and replace the string in the array.
So basically the app will display fields based on what the user wants and then the user can edit those values to their liking. Once the textfields have been updated, the values are stored again in userdefaults so that the next time the tableview is opened, the update values will appear.
This is what the tableviewcontroller looks like at the moment:
//
// Asset1TableViewController.swift
// Net Calc 2
//
// Created by Joshua Peterson on 30/06/2015.
// Copyright © 2015 Peterson Productions. All rights reserved.
//
import UIKit
class Asset1TableViewController: UITableViewController {
var dataHolder: [NSString] = [NSString]()
var finalDataHolder: [NSString] = [NSString]()
var acountAmountHolder: [NSString] = [NSString]()
var finalAccountAmountHolder: [NSString] = [NSString]()
let defaults = NSUserDefaults.standardUserDefaults()
let key1 = "keySave1"
let key2 = "keySave2"
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if let storedTitleValue : NSArray? = self.defaults.arrayForKey(self.key1) {
if storedTitleValue == nil {
self.dataHolder = [NSString]()
} else {
let readArray : [NSString] = storedTitleValue as! [NSString]
for element in readArray {
self.dataHolder.append(element as String)
self.finalDataHolder.append(element as String)
}
}
}
if let storedAmountValue : NSArray? = self.defaults.arrayForKey(self.key2) {
if storedAmountValue == nil {
self.acountAmountHolder = [NSString]()
} else {
let readArray : [NSString] = storedAmountValue as! [NSString]
for element in readArray {
self.acountAmountHolder.append(element as String)
self.finalAccountAmountHolder.append(element as String)
}
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataHolder.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell
cell.AccountLabel.text = dataHolder[indexPath.row] as String
cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
return cell
}
#IBAction func addButtonTapped(sender: AnyObject) {
let newAccounTitle = "Account Name"
let newAccountAmount = "R0.00"
dataHolder.append(newAccounTitle)
acountAmountHolder.append(newAccountAmount)
tableView.reloadData()
}
#IBAction func saveButtonTapped(sender: AnyObject) {
// Save
defaults.setObject(dataHolder as Array, forKey: key1)
defaults.setObject(acountAmountHolder as Array, forKey: key2)
defaults.synchronize()
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
dataHolder.removeAtIndex(indexPath.row)
acountAmountHolder.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
}
I have tried to apply some of the code that i have found on the website but the problem is that I cant actually connect to the cell.
Ok so after some research I have added a few functions to the custom cell class so that it looks like this:
import UIKit
protocol TableViewCellDelegate {
// Indicates that the edit process has begun for the given cell
func cellDidBeginEditing(editingCell: Account1Cell)
// Indicates that the edit process has committed for the given cell
func cellDidEndEditing(editingCell: Account1Cell)
}
class Account1Cell: UITableViewCell, UITextFieldDelegate {
#IBOutlet weak var AccountLabel: UITextField!
#IBOutlet weak var AccountAmount: UITextField!
var delegate: TableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
AccountLabel.delegate = self
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
// close the keyboard on Enter
AccountLabel.resignFirstResponder()
return false
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
// disable editing of completed to-do items
return true
}
func textFieldDidEndEditing(textField: UITextField) {
if AccountLabel != nil {
let newAccountLabel = AccountLabel.text
print(newAccountLabel) // Prints out the new edited text!!!!!!!!
}
if delegate != nil {
delegate!.cellDidEndEditing(self)
}
}
func textFieldDidBeginEditing(textField: UITextField) {
if delegate != nil {
delegate!.cellDidBeginEditing(self)
}
}
}
Now what I need to do is either replace that value in the Array at the index (which i think is going to be rather complicated) or create some sort of loop that will read ALL the values and simply store all of the new values to UserDefaults. Maybe there is something else?
Any help is appreciated!!
You should have a protocol in your custom cell like this, and call it when the text field in the cell gets modified:
protocol TableViewCellToTVController{
func cellCurrentlyEditing(editingCell: Account1Cell) -> Int
}
....
func textFieldShouldReturn(textField: UITextField) -> Bool {
// close the keyboard on Enter
let myrow: Int? = self.delegate_special?.cellCurrentlyEditing(self)
println("cellCurrentlyEditing got called from delegate" , myrow)
AccountLabel.resignFirstResponder()
return false
}
implement this function in tableviewcontroller to know which row got selected :
func cellCurrentlyEditing(editingCell: Account1Cell) -> Int{
var rowNum = 0
let indexP: NSIndexPath = tableView.indexPathForCell(editingCell)!
rowNum = indexP.row
return rowNum
}
also make your tableviewcontroller the delegate for each cell:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Account1Cell", forIndexPath: indexPath) as! Account1Cell
cell.AccountLabel.text = dataHolder[indexPath.row] as String
cell.AccountAmount.text = acountAmountHolder[indexPath.row] as String
cell.delegate_special = self;
return cell
}