UITableview with 2 cells - ios

I am trying to build an app with 2 cell on a tableview
the header that will have the Headlines and the second that will have the normal feeds.
My question is how to connect this two cells
The code for the raw feeds are working
Example:
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.posts.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell
// Configure the cell...
let post = self.posts[indexPath.row]
cell.title.text = post.title?.utf8Data?.attributedString?.string
if let imageUrl = post.imageUrl {
cell.imgView?.downloadImage(from: imageUrl)
}
let myFormatter = DateFormatter()
myFormatter.dateStyle = .none
myFormatter.timeStyle = .short
cell.pubDate.text = myFormatter.string(from: post.pubDate!) // What gives?
return cell
}
}

You can do this by filling a solid color, like white, for both the cells and set Table View separator to none.
tableView.separatorStyle = .none
And if you want to create a serious of such combined cells, then add a view to the bottom of the second cell, i.e. Feed Row, and fill that view with other color, like grey. This view will work as a separator for serious.

I suggest you let your tableview empty in storyboard. (delete all cells)
What I usually do, and what I feel is more flexible and cleaner in terms of code and files, is always use custom cells.
Create a subclass of UITableViewCell for each cell type you need (here, 2). One could be HeaderCell, and the other could be FeedCell.
If you use the "Create UITableViewCell class" I think you can find in Xcode (haven't used it in a long time), it should create the class for you, as well as a .xib file. If you don't have the corresponding .xib just create it and link it manually.
The .xib file is where you will put your labels, connect the outlets and maange everything you need. That's where you'll remake the cells you deleted ealier on. I think you can actually cut and paste in the xib and it might work.
Now you have a custom class, with its corresponding xib, which you can use as a cell.
Make sure your tableview is connected as delegate and datasource in storyboard (it should already be done in your setup).
In ViewDidLoad you will need to register all your cell classes to the tableview.
That is done using this method call on your tableview property (outlet)
I'm not sure how to write it in swift, but it's
MyTableView.Register(nib, key) in pseudo code.
Both the parameters come from your custom cell class (it's the .Nib and the class name, which you could hardcode). I usually do MyHeaderCell.Nib and MyHeaderCell.Key that are put in static, but that you can do however you want.
Now that your tableview is aware of the cells it will have to display, you just have to manage it in your cellForRow method.
Simply do it by index :
var cell;
if (indexPath.Row == 0)
{
cell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell", for: indexPath) as! HeaderCell
}
else
{
cell = tableView.dequeueReusableCell(withIdentifier: "FeedCell", for: indexPath) as! FeedCell
}
let post = self.posts[indexPath.row]
cell.title.text = post.title
return cell
And there you go :)
I've never done swift so there are certainly syntax mistakes but the idea is how you should do it.

Related

What does Apple mean by term "registers" in regards to creating new tableView cells?

I'm working through an exercise which uses tableviews. I noticed within a test during the exercise, they use a method I haven't needed in the past when implementing tableviews from storyboards. The method is:
func register(AnyClass?, forCellReuseIdentifier: String)
After reading the short description of this function in the reference pages. I'm curious to know what does apple mean by term "registers"? I half assume that since we are doing this exercise programmatically at the moment, this function is only needed if you're creating UITableviews programmatically. If this statement is incorrect, please let me know as I'd like to learn more.
Here is the code from the example:
func test_CellForRow_DequesCellFromTableView(){
let mockTableView = MockTableView()
mockTableView.dataSource = sut
mockTableView.delegate = sut
mockTableView.register(ItemCell.self, forCellReuseIdentifier: "ItemCell")
sut?.itemManger?.add(ToDoItem.init(title: "Foo"))
mockTableView.reloadData()
_ = mockTableView.cellForRow(at: IndexPath.init(row: 0, section: 0))
XCTAssertTrue(mockTableView.cellGotDequeed)
}
The DequeueReusable methods are there to check if any reusable cells are left before creating new ones. Hope you have an idea about the working of reusable cells
What happens when the queue is empty? Now we do need to create a cell. We can follow 2 methods to create a cell,
Create cell manually
Create it automatically by registering cell with a valid xib file
METHOD 1
if you do it with manually, you must check cell is empty or not after dequeueReusableCell check. Just like below,
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Reuse an old cell if exist else return nil
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
//check cell is nil if nil you want to allocate it with proper cell
if(cell == nil){
//create cell manually
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "CellSubtitle")
}
// do stuff to the cell here
return cell
}
METHOD 2
We could create the cell manually like above which is totally fine. But it would be convenient if the table view would create the cell for us directly.
That way we don't have to load it from a nib or instantiate it.
For registering a cell with a xib or class we use func register(AnyClass?, forCellReuseIdentifier: String) method. Let see an example,
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(MyCell.self, forCellReuseIdentifier: "Cell")
}
// ...
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath) as MyCell
// no "if" - the cell is guaranteed to exist
// ... do stuff to the cell here ...
cell.textLabel.text = // ... whatever
// ...
return cell
}
You are "registering" your custom Cell class - ItemCell - for reuse as a cell for your tableview.
See: https://developer.apple.com/reference/uikit/uitableview/1614888-register
"Register" tells XCode that the cell exists. A cell is registered under a "reuse identifier." This is a unique string that corresponds to your TableViewCell, in this case ItemCell.
A cell can also be registered in the Storyboard by filling out the "Identifier" in the cell's attributes inspector.

Two TableViews One Data Source?

I have setup a segue that will show a view controller with a small TableView. I want a different segue to show a bigger TableView but I want the bigger table to have the same exact info as the smaller table. Got the smaller tableView working perfect on its own, but once I give the bigger table a Data source, reset and try it out.....crashes.
// IndexPath or First Cell in TableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if self.TaskTableViews.hidden == false {
cell = tableView.dequeueReusableCellWithIdentifier( "FirstTask" , forIndexPath: indexPath) as UITableViewCell!
let list = frc.objectAtIndexPath(indexPath) as! List
cell.textLabel?.text = list.taskName
cell.textLabel?.textColor = UIColor.whiteColor()
TaskTableViews.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
TaskTableViews.layer.cornerRadius = 8
TaskTableViews.separatorColor?.colorWithAlphaComponent(2.0) }
if self.TaskTable2.hidden == false {
cell = tableView.dequeueReusableCellWithIdentifier( "Second Task" , forIndexPath: indexPath) as UITableViewCell!
let list = frc.objectAtIndexPath(indexPath) as! List
cell.textLabel?.text = list.taskName
cell.textLabel?.textColor = UIColor.whiteColor()
TaskTable2.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
TaskTable2.layer.cornerRadius = 8
TaskTable2.separatorColor?.colorWithAlphaComponent(2.0) }
return cell as UITableViewCell
}
The problem is that the code for your two tables is slamming into each other. To fix this, rejigger your logic. Do not make your logic depend on what is hidden. You can handle only one table at a time; just one table is calling here. That table comes in as the tableView parameter. Make your logic depend on that. Depending what table view that tableView parameter is, configure the cell and return it for that table view.
I think that you should consider changing your approach by just resizing the table view dynamically when you go from one scene to the other instead of having two table views if the information is exactly the same.
If you're still pushing for this approach then don't make the condition be that the table view is hidden and instead implement your own logic or boolean to determine this. But again, I'd rather resize a single table view as needed.
You have many problems in your code
1.
var cell = UITableViewCell()
What's the point of this line?
2.
cell = tableView.dequeueReusableCellWithIdentifier( "FirstTask" , forIndexPath: indexPath) as UITableViewCell!
What's the point of casting? This function returns UITableViewCell (not even optional)
3.
cell.textLabel?.text = list.taskName
Should not compile, cause UITableViewCell doesn't have textLabel
4.
TaskTableViews.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
What's the point of doing this every cell request? Move this to viewDidLoad or other appropriate place
Your if { } parts are identical except of reuse identifier
Use tableView argument when needed
Use if { } else
8.
return cell as UITableViewCell
Why cast? Just return
I'm sure I haven't found all of them))

How to use multiple custom cells (>1) in UITableView

I've searched for an answer to this question all over Stack Overflow and have found some useful answers but my situation is different as the number of rows in the section are to be determined from the number of items listed in an array. I'm trying to create a table that uses two custom cells. The first cell displays profile information while the second displays the news feed.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myProfileDM.profileArray.count
//return myProfileFeedDM.profileFeedArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->
UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("bio", forIndexPath:indexPath) as! ProfileTableViewCell
cell.followerNumber!.text = myProfileDM.profileArray[indexPath.row].followerNumberInterface
cell.followers!.text = myProfileDM.profileArray[indexPath.row].followersInterface
cell.following!.text = myProfileDM.profileArray[indexPath.row].followingInterface
cell.followingNumber!.text = myProfileDM.profileArray[indexPath.row].followingNumberInterface
return cell
}
else{
let cell = tableView.dequeueReusableCellWithIdentifier("feed", forIndexPath:indexPath) as! FeedTableViewCell
//let cell: FeedTableViewCell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "feed")
cell.profileFeedLabel!.text = myProfileFeedDM.profileFeedArray[indexPath.row].profileFeed
cell.profileDateLabel!.text = myProfileFeedDM.profileFeedArray[indexPath.row].profileDate
return cell
}
}
}
when I run the program, the first cell (with identifier-bio) is the only one that loads/shows up.
I suppose the number of rows in the section is wrong. From your variable names I suspect it should be
myProfileFeedDM.profileFeedArray.count + 1
Note that in the feed array you would have to use indexPath.row - 1 to get to the right index of your array because the first row is for the profile.
I don't see any reason from the code why it doesn't work.
Try to debug cellForRowAtIndexPath method to see what is the value of the indexPath on each call
(or just put println ("IndexPath: \(indexPath)") to your cellForIndexPath method)
PS: But as long as you need your profile cell only once - I would suggest to move ProfileCell into table's or Section's header
it would be a bit more logical I think.

How to add three tableview cells in a tableview as Subview?

I want to add 2 cells one as header the segue form the previous tableview and the the second cell for details like this prototype .
First Cell class "courseCell"
Second Cell Class "DetailsTVC"
I found many way but it doesn't work I hope someone help
I couldn't follow with this instruction
Initialize your custom tableviewcell - CustomCell1 and CustomCell2
Since tableviewcell is a subclass of UIView you can add it as a subview.
[TableCell addSubview:CustomCell1];
[TableCell addSubview:CustomCell2];
cell?.addSubview(<#view: UIView>)
[cell ?.addSubview(<#view: UIView>)]
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject!) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell" , forIndexPath : indexPath) as? courseCell
if cell == nil
{
cell = courseCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
}
cell?.name.text = object["title"] as! String!
cell?.location.text = object["Location"] as! String!
return cell!
}
To accomplish it:
TableViewController
- Tableview
- TableViewHeader (create a UIView subclass for this view)
- TableViewContent (datasource)
- TableViewCell1 (virgin american fligth ...)
- TableViewCell1 (departs los angeles)
- TableViewCell1 (arrives new york)
Note that you dont need XIB file to your tableviewController
I am not sure why your question title mentions 3 and your question only mentions 2 but from what I can understand based on the image, it appears you want the header to be the title of the course and the rest of the cells to be the details of the course.
To create a header for your TableView you can create a custom "HeaderCell" as you would create a custom cell and then use it in the method which specifies the Header:
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{
//set the title, image or whatever you want for your custom header cell
}
Now you can use another custom TableView cell as you normally do to show the details.
Tutorial:
http://www.ioscreator.com/tutorials/customizing-header-footer-table-view-ios8-swift

Adding various content type within Table View Cell

I am new to IOS programming and will need some direction here.
I am trying to create a tableview with each rows having a image and some text.
I am able to take a TableViewController and programmatically was able to add basic text and rows. But can you please tell me how should i add more complex content. Trying to achieve something like this using program.
My current code looks like this in my TableViewController and its able to print a text message on each row.
override func numberOfSectionsInTableView(tableView: UITableView!) -> Int {
return 1
}
override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell? {
var mycell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("frontcell", forIndexPath: indexPath) as UITableViewCell
mycell.textLabel.text = "Just a generic message"
return mycell
}
There is a
mycell.contentView
which takes in UIView. But how does it works? How should this object be created?
Appreciate your help.
------Update -----
Thanks to Suryakant for helping out. Answer below for his step by step how to do. Any one who needs the source code can use this. http://pastebin.com/ZfNqK4tW
Though you can achieve it by default UITableViewCell also, as #meda mention in his answer,
but it seems, you want different UIImageView size and 2 UILabels with different font size or may be some more controls there. For Achieving that you need to customize UITableViewCell and you can do that by subclassing UITableViewCell class.
Create a class by subclassing UITableViewCell.
e.g. your subclass say MyCell look like —
2.Go to storyboard and select prototypeCell and select Identity inspector, in Class type your custom class name (e.g MyCell )in place of UITableViewCell.
drag-n-drop all the controls you need and link with their IBOutlets (From MyCell to prototypeCell).
This goes as below..
3.Now goto Attributes Selector and give some Identifier to your MyCell, you can give any string you want.
4.Goto the class where you implemented UITableView delegates and update your cellForIndexPath as bellow
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath:
NSIndexPath!) -> UITableViewCell! {
let kCellIdentifier:String = "cell"
var cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as MyCell!
if cell == nil {
// register Custom UITableView Class to UITableView
tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: kCellIdentifier)
cell = MyCell(style: UITableViewCellStyle.Default, reuseIdentifier: kCellIdentifier)
}
if var label = cell.cellMyCity{
label.text = cityList[indexPath.row]
}
if var label = cell.cellMyCountry{
label.text = countryList[indexPath.row]
}
if var imageView = cell.imageView{
imageView.image = UIImage(named :"img.png")
}
return cell
}
For reference you can see example code here.
You would create a subclass of UITableViewCell and then assign values to the property of your cell
mycell.textLabel.text = "Just a generic message"
mycell.detailTextLabel.text = "Just a detail message"
mycell.imageView.text = myImage
And for that you would use only one prototype Cell no need to duplicate them.

Resources