Migration swift to swift 3 NSMutableArray - ios

When i made the migration swift code i have this error "Type 'Any' has no subscript members" and my code is
var myArray: NSMutableArray = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = UITableViewCell()
if let name = self.myArray[(indexPath as NSIndexPath).row]["FirstName"] as? String{
cell.textLabel?.text = ("\(name)")
}
}
I tried many things but i do not have a answer for this problem.

First of all: Do not use NSMutableArray in Swift!
The error occurs because the compiler needs to know if the object is subscriptable by key. Using a native Swift type solves the problem.
var myArray = [[String:Any]]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = UITableViewCell() // will not work
if let name = self.myArray[indexPath.row]["FirstName"] as? String { // optional binding actually not needed
cell.textLabel?.text = name // please no string interpolation
}
return cell // mandatory!
}
Note: Consider that UITableViewCell() will not work. The recommended way are reusable cells
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

You should use
Generics
dequeueReusableCell
IndexPath instead of NSIndexPath
so here's the code
import UIKit
class Controller: UITableViewController {
var persons = [[String:String]]()
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCellID") ?? UITableViewCell(style: .default, reuseIdentifier: "MyCellID")
cell.textLabel?.text = persons[indexPath.row]["FirstName"]
return cell
}
}

Related

How to fill tableview with two arrays using single custom cell?

I want to display two array values in tableview using single cell.
Suppose i have two array and both contains same no of elements.
FirstArray and SecondArray. there is two label in tableview cell Lbl1 and Lbl2, now Lbl1 should fill with FirstArray and Lbl2 Should fill with SecondArray. I know that we can not use two array for uitableview datasource . I can not figure out how to do this.
Please help me.
I also tried using multiple custom tableview cells with section. but it did not give the desired result.
I have two Array -
let datalist1 = ["firstCell1" , "firstCell2" , "firstCell3" , "firstCell4"]
let datalist2 = ["secondCell1" ,"secondCell2" , "secondCell3" ,"secondCell4"]
In tableview numberOfRowsInSection :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0
{
return datalist1.count
}
else {
return datalist2.count
}
}
In cellForRowAt :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as? FirstCell
cell?.initData(name: datalist1[indexPath.row])
return cell!
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? SecondCell
cell?.initData(lbl: datalist2[indexPath.row])
return cell!
}
}
Actual Output :
FirstCell1
FirstCell2
FirstCell3
FirstCell4
SecondCell1
SecondCell2
SecondCell3
SecondCell4
Expected Output:
FirstCell1
SecondCell1
FirstCell2
SecondCell2
FirstCell3
SecondCell3
FirstCell4
SecondCell4
Hello You not need to add two section just do as bellow.
This is your arrays.
let datalist1 = ["firstCell1" , "firstCell2" , "firstCell3" , "firstCell4"]
let datalist2 = ["secondCell1" ,"secondCell2" , "secondCell3" ,"secondCell4"]
Number of rows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datalist1.coun
}
Cell for row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as? FirstCell
cell.Lbl1.text = datalist1[indexPath.row]
cell.Lbl2.text = datalist2[indexPath.row]
return cell!
}
Based on the explanation and code, you have provided, the requirement is not clear.
However, there may be two cases based on the above details:
Case-1:
Cell-1 : FirstCell1
Cell-2 : SecondCell1
Cell-3 : FirstCell2
Cell-4 : SecondCell2
Then you can implement something like below:
In tableview numberOfRowsInSection :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (datalist1.count + datalist2.count)
}
In cellForRowAt :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row % 2 == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as? FirstCell
cell?.initData(name: datalist1[indexPath.row])
return cell!
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? SecondCell
cell?.initData(lbl: datalist2[indexPath.row])
return cell!
}
}
Case-2:
Cell-1 : FirstCell1 SecondCell1
Cell-2 : FirstCell2 SecondCell2
Cell-3 : FirstCell3 SecondCell3
Cell-4 : FirstCell4 SecondCell4
Then you can implement something like below:
In tableview numberOfRowsInSection :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return datalist1.count
}
In cellForRowAt :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as? FirstCell
//Single custom cell can implement both the labels
cell?.initData(name: datalist1[indexPath.row],lbl: datalist2[indexPath.row])
return cell!
}
}
You've to Declare as
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section %2 == 0 {
let cell1 = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as? FirstCell
cell1.lbl1.text = datalist1[indexPath.row]
return cell1!
}
else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as? SecondCell
cell2.lbl2.text = datalist2[indexPath.row]
return cell2!
}
}
The best way is using models. You have to declare data model such as
struct MyModel {
var firstValue: String?
var secondValue: String?
}
Then you have to convert your two arrays to a single array of MyModel objects
var myData = Array<MyModel>()
Then by using for loop you can iterate over one array and fill the myData array.
for (index, _) in datalist1 {
let object = MyModel()
object.firstValue = datalist1[index]
object.firstValue = datalist2[index]
myData.append(object)
}
Then just implement tableview protocol methods and fill your custom cell with MyModel objects.
1. Create a single array from datalist1 and datalist2 using zip(_:_:), that we'll be using as dataSource for tableView.
lazy var dataList = Array(zip(self.datalist1, self.datalist2))
dataList is of type [(String, String)].
Example:
If datalist1 and datalist2 are,
let datalist1 = ["firstCell1" , "firstCell2" , "firstCell3" , "firstCell4"]
let datalist2 = ["secondCell1" ,"secondCell2" , "secondCell3" ,"secondCell4"]
then, dataList contains
[("firstCell1", "secondCell1"), ("firstCell2", "secondCell2"), ("firstCell3", "secondCell3"), ("firstCell4", "secondCell4")]
2. You need a single cell to display all that data. There is no need to create 2 different UITableViewCells for this. Example:
class CustomCell: UITableViewCell {
#IBOutlet weak var lbl1: UILabel!
#IBOutlet weak var lbl2: UILabel!
}
3. Now, your UITableViewDataSource methods look like,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.lbl1.text = self.dataList[indexPath.row].0
cell.lbl2.text = self.dataList[indexPath.row].1
return cell
}

cellForRow(at: ) returns nil

So I have this function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(selectedIndexPath: indexPath)
return cell;
}
func changeCellProperty(selectedIndexPath: IndexPath){
print("indexpath = \(selectedIndexPath)") . // printing [0,0] and all values
let cell = self.tableView.cellForRow(at: selectedIndexPath) as! customCell
// got nil while unwrapping error in above statement.
cell.label.text = ""
// and change other properties of cell.
}
I am not able to understand the error.
When I am getting the indexpath, then why I am not able to point a particular cell and change properties accordingly.
You cannot access a cell that has not yet been added to the tableView. That is what you are trying to do here in changeCellProperty method. So, if your dequeue works, then all you would need to do is pass the dequeued cell to that method.
func changeCellProperty(cell: customCell){
cell.label.text = ""
// and change other properties of cell.
}
Your cellForRowAt method would look like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) as! customCell
changeCellProperty(cell: cell)
return cell
}
Note: class names should be UpperCamelCase. So your customCell should be named CustomCell.

swift dictionary in tableview

I has add struct
struct lists {
var title : String!
var description : String!
}
create dictionary:
var list = Dictionary<String, String>()
var listArray = [lists]()
update data to dictionary:
list.updateValue("InquiryNumberCode", forKey: InquiryNumberCode)
list.updateValue("InquiryNumberDescription", forKey: InquiryNumberDescription)
list.updateValue("InquiryNumberValue", forKey: InquiryNumberValue)
run for loop to append listArray:
for (description, title) in list {
print("\(title): \(description)")
listArray.append(lists(title: title , description: description ))
}
Tried insert data to Tableview cell has same error.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "detail", for: indexPath) as! DetailTableViewCell
let celldata = listArray[indexPath.section]
cell.titleOutlet.text = celldata.title[indexPath.row]
return cell
}
error:
Cannot assign value of type 'Character' to type 'String?'
I can't transfer data to Tableview cell, have any one can told me why?
listArray is an Array of lists structs. So to access title, you should change your code to:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "detail", for: indexPath) as! DetailTableViewCell
let celldata = listArray[indexPath.row]
cell.titleOutlet.text = celldata.title
return cell
}

Unwrapping UITableView cell text

I'm trying to get the text on a table view cell and then get the index of it in an array.
This is the code I'm using:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
let indexOfCellString = event.index(of: cell.textLabel!.text)
}
But I get the following errors:
value of optional type string? not unwrapped
invalid character in source file
What is going on here? What else do I need to unwrap?
There is no need to cast dequeueReusableCell to UITableViewCell since that is its return type.
cell.textLabel is optional. And then the text property of UILabel is optional.
Properly deal with optionals:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let text = cell.textLabel?.text {
let indexOfCellString = event.index(text)
// do stuff with indexOfCellString
}
return cell
}

unexpectedly found nil while unwrapping an Optional value in SWIFT 3.0

I am using tableview with custom cell in swift 3.0. I take a textview and give outlet of class of tabelview cell and accessing in tableview delegate method but its showing me error like unexpectedly found nil while unwrapping an Optional value
here is my code. Record is array
Chek this Screenshot. FYI I have taken A new custom class and Give Outlet to it but same problem ocuured
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return record.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell")
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
if let str = record.object(at: indexPath.row) as? String {
print(cell.txtview)
cell.txtview.text = str
}
return cell
}
Its perfectly working in Static cell but in custom cell it showing me error.
cell.textview is not taken from custom cell
Please help me with it
Please try with following line not sure about that:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell")
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
if let title = record.object(at: indexPath.row) as? String {
cell.textview.text = title
} else {
cell.textview.text = ""
}
return cell
}

Resources