how to handle two different types in an Array in Swift for a UITableView
Here is an approach that uses a protocol to unite your two classes:
protocol TableItem {
}
class Header: TableItem {
// Header stuff
}
class Item: TableItem {
// Item stuff
}
// Then your array can store objects that implement TableItem
let arr: [TableItem] = [Header(), Item()]
for item in arr {
if item is Header {
print("it is a Header")
} else if item is Item {
print("it is an Item")
}
}
The advantage of this over [AnyObject]
or NSMutableArray
is that only the classes which implement TableItem
would be allowed in your array, so you gain the extra type safety.
Swift - display two different arrays of structs in a table view
Create a protocol
with common property with Date
type and add it in both structs. In ViewController
add an array which merges both array and sorts by date.
Use that array in tableView
data source methods.
protocol CommonData {
var date: Date { get }
}
struct A: CommonData, Codable {
var date: Date
var x: String
}
struct B: CommonData, Codable {
var date: Date
var y: String
}
class TimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arr1: [A] = []
var arr2: [B] = []
var totalArr: [CommonData] {
return (arr1 as [CommonData]) + (arr2 as [CommonData]).sorted(by: { $0.date < $1.date })
}
override func viewDidLoad() {
super.viewDidLoad()
arr1.append(A(date: Date(), x: "x"))
if let yesterDay = Calendar.current.date(byAdding: .day, value: -1, to: noon) {
arr2.append(B(date: yesterDay, y: "y"))
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return totalArr.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier")
?? UITableViewCell(style: .default, reuseIdentifier: "reuseIdentifier")
print(totalArr[indexPath.row].date.description)
if let data = totalArr[indexPath.row] as? A {
print(data.x)
} else if let data = totalArr[indexPath.row] as? B {
print(data.y)
}
return cell
}
}
Using two arrays in UITableview swift
Don't do that. Don't use multiple arrays as data source
return list.count + list_2.count
causes the error because actually you have only list.count
number of items where list.count
must be equal to list_2.count
. The addition raises an out-of-range exception at row list.count + 1
Use a custom struct
struct Item {
let foo : String
let bar : String
}
Then map the two arrays
var items = [Item]()
items = zip(list, list_2).map{ Item(foo:$0.0, bar:$0.1) }
In numberOfRowsInSection
return items.count
In cellForRowAt
get the value from the Item
instance
let item = items[indexPath.row]
cell.la_view.text = item.foo
cell.la_view2.text = item.bar
To append an item use
func append(add:Int) {
let lastIndex = items.count
items.append( Item(foo:"\(add)", bar:"\(add)") )
let indexPath = IndexPath(row: lastIndex, section: 0)
table_View.insertRows(at: [indexPath], with: .automatic)
}
And please according to the naming convention use lowerCamelCased rather than snake_cased variable names.
How do I populate two sections in a tableview with two different arrays using swift?
TableView Cells
You could use a multidimensional array. For example:
let data = [["0,0", "0,1", "0,2"], ["1,0", "1,1", "1,2"]]
For the number of sections use:
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return data.count
}
Then, to specify the number of rows in each section use:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data[section].count
}
Finally, you need to setup your cells:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellText = data[indexPath.section][indexPath.row]
// Now do whatever you were going to do with the title.
}
TableView Headers
You could again use an array, but with just one dimension this time:
let headerTitles = ["Some Data 1", "KickAss"]
Now to set the titles for the sections:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section < headerTitles.count {
return headerTitles[section]
}
return nil
}
The code above checks to see there's a title for that section and returns it, otherwise nil
is returned. There won't be a title if the number of titles in headerTitles
is smaller than the number of arrays in data
.
The Result
How to fill tableview with two arrays using single custom cell?
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!
}
Putting different custom cell types in a tableview
This idea from your dequeue
call in cellForRowAt
is ingenious and natural-seeming, but illegal:
as! cellTypes[indexPath.row]
Swift won't let you cast (as!
) to a type that is not specified until runtime. It's a static language, not a dynamic language. The type must be a literal type specified at compile time.
You'll just have to split your cellForRowAt
implementation into two completely separate switch cases, one for rows 0 and 1, and one for rows 2 and 3, and do a different dequeue
for each one, each one declaring and specifying its own local cell
variable with a cast as! FilterTableViewCell
or as! FilterTableViewCell2
literally — and proceeding from there, separately, within each case.
You cannot unify the two cases as your elegant-looking code attempts to do, because only in a context where cell
is typed literally as FilterTableViewCell or FilterTableViewCell2 can you access the properties belonging to the respective type.
As for this expression:
var reminderCells = [FilterTableViewCell(),FilterTableViewCell(),
FilterTableViewCell2(),FilterTableViewCell2()]
...the problem here is that Swift can only infer that this must be an array of UITableViewCell, which has no FilterTableViewCell properties.
You could work around this by defining a third type, e.g. FilterTableViewCellParent, to act as a common superclass for FilterTableViewCell and FilterTableViewCell2, and giving it their common properties which they can both inherit; reminderCells
could then be an array of FilterTableViewCellParent and you'd be able to access the properties through an element of it. (Or of course you could make FilterTableViewCell the superclass of FilterTableViewCell2 or vice versa, and thus do it with just two types.)
But personally I think you should abandon your attempts to be "elegant" and just do everything completely separately in the two cases of the switch, even at the cost of some repetition. Sometimes one must just program the same way Superman gets into his pants; he may be Superman but he still has to get into one leg at a time.
Working with array with different data types in Swift
Use a protocol that has the methods/properties necessary for next and previous actions. Have both of your track types implement the protocol. Have your array have the type of the protocol.
protocol Track {
title: String
albumTitle: String
// other method and properties
}
class JSONTrack: Track {
// implementation
}
class CoreDataTrack: Track {
// implementation
}
let tracks = [Track]()
Related Topics
Monitoring App Switching on Os X
Firebasefirestoreswift Won't Install (Cocoapods)
Nsimage Getting Resized When I Draw Text on It
Suppressing Implicit Returns in Swift
Swift 2 to 3 Migration Dispatch_Get_Global_Queue
How to Create a Multi Line Text Field in Swiftui for MACos
Why Is an Object Not Being Decoded
Hide Password with "•••••••" in a Textfield
Environmentobject VS Singleton in Swiftui
Programmatically Disabling Screenshot in App
Swift Encode Tuple Using Nscoding
Difference Between Nsrange and Nsmakerange
Nsdatecomponents Weekofyear Returns Wrong Date
How to Animate Bordercolor Change in Swift
Subtle Cast Warning When Using SQLite.Swift ... Binding? to Any