Xamarin iOS TableView not showing up - c#

I am making an app for iOS using Xamarin I had some trouble with UITableViews and found this tutorial: https://learn.microsoft.com/en-us/xamarin/ios/user-interface/controls/tables/populating-a-table-with-data
I created a new project and followed what they did, but it doesn't work for me. I must be doing something wrong, but I can't figure out what.
Could someone take a look and see why the TableView doesn't show up?
BasicViewController:
public class BasicTableViewController : UIViewController
{
private UIView view;
public override void ViewDidLoad()
{
base.ViewDidLoad();
var table = new UITableView(View.Bounds);
table.Source = new BasicTableSource("aaaaaaaaa", "bbbbb", "cccccccc", "ddddddddddddd", "eeeee");
Add(table);
}
public override void LoadView()
{
view = new UIView()
{
BackgroundColor = UIColor.White,
};
View = view;
}
}
BasicTableViewSource:
public class BasicTableSource : UITableViewSource
{
private readonly string[] items;
public BasicTableSource(params string[] items)
{
this.items = items;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell("cell");
if (cell == null)
cell = new UITableViewCell(UITableViewCellStyle.Default, "cell");
cell.TextLabel.Text = items[indexPath.Row];
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return items.Length;
}
}
AppDelegate:
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
public override UIWindow Window { get; set; }
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
Window.RootViewController = new BasicTableViewController();
Window.MakeKeyAndVisible();
return true;
}
}
What the simulator looks like when running this project:
What the simulator looks like

Cause:
When you override the method LoadView.It seems that you forgot to set the Frame of view.So the size of view will with Height as 0 and Width as 0.
Solution:
Set the frame of view as the size of screen.
public override void LoadView()
{
view = new UIView()
{
Frame = UIScreen.MainScreen.Bounds,
BackgroundColor = UIColor.White,
};
View = view;
}

Related

How have a custom UICollectionViewCell fill horizontal width?

I'm trying to make an app for people of my student dancing association to find a dance partner. It's been a fun project during corona. Everything is done in ASP Core 5 and Xamarin Forms, and it's almost ready for testing. However, I'm having some trouble with the chat UI. When I use a CollectionView in Forms, it loads very slowly, due to rendering performance (at least on Android, iOS is generally much faster). To solve that I tried creating it as a view and use native renderers for iOS and Android. With Android, I simply used a NuGet package (XamarinLibrary.Xamarin.AndroidX.ChatKit), but for iOS I could find no such package. There's a native SwiftUI package (MessageKit), though I don't know how to wrap that (and the documentation is a lot). So I started to instead write it in Xamarin iOS. My test loads really quickly, although I'm now struggling with the layout of the Collection and the ViewCell. Could someone show me how to create message cells that fill the horizontal space?
Thanks in advance! :)
This is what it looks like right now:
Screenshot
[UPDATE] I partially solved the issue by adding this (though it does not work in the constructor):
Screenshot 2
public override bool ShouldInvalidateLayoutForBoundsChange(CGRect newBounds) {
MinimumLineSpacing = 10;
MinimumInteritemSpacing = 10;
SectionInset = new UIEdgeInsets(top: 0, left: 10, bottom: 0, right: 10);
ItemSize = new CGSize(width: (newBounds.Width - 20), height: 100);
return true;
}
My code currently (the data source isn't correct yet):
public class MessageListLayout : UICollectionViewFlowLayout {
public MessageListLayout() {
ItemSize = new CGSize(UIScreen.MainScreen.Bounds.Size.Width, 50);
EstimatedItemSize = AutomaticSize;
}
public override bool ShouldInvalidateLayoutForBoundsChange(CGRect newBounds) {
return true;
}
public override UICollectionViewLayoutAttributes LayoutAttributesForItem(NSIndexPath path) {
return base.LayoutAttributesForItem(path);
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect(CGRect rect) {
return base.LayoutAttributesForElementsInRect(rect);
}
}
public class MessageListDataSource : UICollectionViewDataSource {
private string CellId { get; set; }
#region Computed Properties
public UICollectionView CollectionView { get; set; }
public List<int> Numbers { get; set; } = new List<int>();
#endregion
#region Constructors
public MessageListDataSource(UICollectionView collectionView, string cellId) {
// Initialize
CollectionView = collectionView;
CellId = cellId;
// Init numbers collection
for (int n = 0; n < 100; ++n) {
Numbers.Add(n);
}
}
#endregion
#region Override Methods
public override nint NumberOfSections(UICollectionView collectionView) {
// We only have one section
return 1;
}
public override nint GetItemsCount(UICollectionView collectionView, nint section) {
// Return the number of items
return Numbers.Count;
}
public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) {
// Get a reusable cell and set {~~it's~>its~~} title from the item
var cell = collectionView.DequeueReusableCell(CellId, indexPath) as MessageListViewCell;
cell.Text = Numbers[(int)indexPath.Item].ToString();
return cell;
}
public override bool CanMoveItem(UICollectionView collectionView, NSIndexPath indexPath) {
// We can always move items
return true;
}
public override void MoveItem(UICollectionView collectionView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath) {
// Reorder our list of items
var item = Numbers[(int)sourceIndexPath.Item];
Numbers.RemoveAt((int)sourceIndexPath.Item);
Numbers.Insert((int)destinationIndexPath.Item, item);
}
#endregion
}
So this should be the base message bubble.
public class MessageListViewCell : UICollectionViewCell {
UIImageView imageView;
public string Text { get; set; }
[Export("initWithFrame:")]
public MessageListViewCell(CGRect frame) : base(frame) {
BackgroundView = new UIView { BackgroundColor = UIColor.Orange };
SelectedBackgroundView = new UIView { BackgroundColor = UIColor.Green };
ContentView.Layer.BorderColor = UIColor.LightGray.CGColor;
ContentView.Layer.BorderWidth = 2.0f;
ContentView.BackgroundColor = UIColor.White;
//ContentView.Transform = CGAffineTransform.MakeScale(1, 1);
ContentView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
imageView = new UIImageView(UIImage.FromBundle("placeholder.png"));
imageView.Center = ContentView.Center;
imageView.Transform = CGAffineTransform.MakeScale(0.7f, 0.7f);
ContentView.AddSubview(imageView);
}
public UIImage Image {
set {
imageView.Image = value;
}
}
[Export("custom")]
public void Custom() {
// Put all your custom menu behavior code here
Console.WriteLine("custom in the cell");
}
public override bool CanPerform(Selector action, NSObject withSender) {
if (action == new Selector("custom"))
return true;
else
return false;
}
}
[assembly: ExportRenderer(typeof(MessagesListControl), typeof(MessagesListControlRenderer))]
namespace Vinder.iOS.UI.Renderers {
public class MessagesListControlRenderer : ViewRenderer<MessagesListControl, UICollectionView> {
static readonly NSString messageListViewCell = new("MessageListViewCell");
private UICollectionView collectionView { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<MessagesListControl> e) {
base.OnElementChanged(e);
if (e.OldElement != null) {
// Unsubscribe to events
}
if (e.NewElement != null) {
if (Control == null) {
collectionView = new UICollectionView(new CGRect(0, 0, UIScreen.MainScreen.Bounds.Size.Width, 300), new MessageListLayout());
collectionView.RegisterClassForCell(typeof(MessageListViewCell), messageListViewCell);
collectionView.BackgroundColor = UIColor.Blue; // blue is easy for seeing the correct bounds
collectionView.DataSource = new MessageListDataSource(collectionView, messageListViewCell);
SetNativeControl(collectionView);
}
// Subscribe to events
}
}
}
}

How to create a List view in xamarin ios

I want to create a listview with multiple fields and image. I am used table view for developing list view, but I wont get the correct design.
Please help me...
Here is my code
class TableViewSource : UITableViewSource
{
List<Sample> tabledata;
public TableViewSource(List<Sample> items)
{
tabledata = items;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell("cell") as CustomVegeCell;
if (cell == null)
cell.UpdateCell(tabledata[indexPath.Row].CaseID
, tabledata[indexPath.Row].Description
, UIImage.FromFile("right_arrow.png"));
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return tabledata.Count;
}
public override void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
{
if (indexPath.Row == tabledata.Count - 1)
{
//Reload your data here
}
}
}
Here is my ViewController.cs
List<Sample> _itemdata;
public ViewController(IntPtr handle) : base(handle)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
DAtaBinding();
mainTable.Source = new TableViewSource(_itemdata);
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
}
public void DAtaBinding()
{
_itemdata = new List<Sample>() { { new Sample { CaseID="CQ964C",Description="Aswathy"} },
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
{ new Sample { CaseID="CQ964C",Description="Anu"}},
};
}
}
Here is my custom tableviewcell
CustomVegeCell.cs
public class CustomVegeCell : UITableViewCell
{
UILabel headingLabel, subheadingLabel;
UIImageView imageView;
public CustomVegeCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(218, 255, 127);
imageView = new UIImageView();
headingLabel = new UILabel()
{
Font = UIFont.FromName("Cochin-BoldItalic", 22f),
TextColor = UIColor.FromRGB(127, 51, 0),
BackgroundColor = UIColor.Clear
};
subheadingLabel = new UILabel()
{
Font = UIFont.FromName("AmericanTypewriter", 12f),
TextColor = UIColor.FromRGB(38, 127, 0),
TextAlignment = UITextAlignment.Center,
BackgroundColor = UIColor.Clear
};
ContentView.AddSubviews(new UIView[] { headingLabel, subheadingLabel, imageView });
}
public void UpdateCell(string caption, string subtitle, UIImage image)
{
imageView.Image = image;
headingLabel.Text = caption;
subheadingLabel.Text = subtitle;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
imageView.Frame = new CGRect(ContentView.Bounds.Width - 63, 5, 33, 33);
headingLabel.Frame = new CGRect(5, 4, ContentView.Bounds.Width - 63, 25);
subheadingLabel.Frame = new CGRect(100, 18, 100, 20);
}
}
After adding the custom tableviewcell i got an exception in the GetCell method
I want this design for my screen
You have to new a class inherit from UITableViewCell, and create custom cell layouts in it.
In this scenario you need three labels and a arrow image, and adjust their frame as demonstrated.
Toturial here.
Sample here.

Bind second UITableView on RowClick of first UITableView in the same UIViewController - ios Xamarin

I have two UITableView in the same UIViewController.
tblView1 & tblView2.
Both TableViews are bringing data dynamically.
Now my problem is: I want to load data in tblView2 on the basis of SelectedRow from tblView1.
For Example, when I select a company name from tblView1, then tblView2 needs to populate the Cars made by that company.
I have rowIndex of my first table (tblView1), but i can't bind my tblView2 from the RowSelected Method of tblView1.
I need help in binding my tblView2. How can i do this?
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using CoreGraphics;
using Foundation;
using UIKit;
namespace Tables
{
public partial class ViewController : UIViewController
{
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public ViewController()
{
//tblView2.Source = new CompanyModelsSource();
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
if (tblView1 != null)
{
tblView1.Source = new CarModelsSource();
}
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
}
class CompanyModelsSource : UITableViewSource
{
private List<Companies> _Companies;
NSString _cellID = new NSString("TableCell");
public CompanyModelsSource()
{
_Companies = CompanyTableSource.AllCompany();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
// tell the TableView how many rows to create
return _Companies.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
//I can't access my tblView2 in this method. So where i can bind my other UITableView?
UILabel lblTotalFacilities = new UILabel();
lblTotalFacilities.Layer.BackgroundColor = UIColor.Blue.CGColor;
lblTotalFacilities.Frame = new CGRect(305, 200, 1024, 400);
ViewController vc = new ViewController();
vc.View.AddSubview(lblTotalFacilities);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
Company currentCompany = _Companies[indexPath.Row];
var cell = tableView.DequeueReusableCell(_cellID) as CompanyTableCell;
if (cell == null) { cell = new CompanyTableCell(_cellID); }
cell.UpdateCellControlsWithAuditData(currentCompany.Name);
return cell;
}
}
public class CompanyTableSource
{
public CompanyTableSource()
{
}
public static List<Companies> AllCompany()
{
CompanyCollection CC = null;
string path1 = path + "Companies.xml";
XmlSerializer serializer = new XmlSerializer(typeof(CompanyCollection));
StreamReader reader = new StreamReader(path1);
CC = (CompanyCollection)serializer.Deserialize(reader);
reader.Close();
List<Companies> comp = CC.CompanyCollection.Cast<Companies>().ToList();
return comp;
}
}
public class CompanyTableCell : UITableViewCell
{
UILabel nameLabel;
public CompanyTableCell(NSString cellId) : base(UITableViewCellStyle.Default, cellId)
{
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(54, 194, 36);
var newFont = UIFont.SystemFontOfSize(12);
nameLabel = new UILabel();
nameLabel.Font = newFont;
ContentView.AddSubviews(new UIView[] { nameLabel });
}
public void UpdateCellControlsWithAuditData(string Name)
{
nameLabel.Text = Name;
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
nameLabel.Frame = new CGRect(10, 0, 350, 33);
}
}
}
Hope this helps. Created everything in a single file for simplicity.
public partial class ViewController : UIViewController
{
public ViewController() : base("ViewController", null)
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
var companySource = new CompanyTableSource();
tblView1.Source = companySource;
companySource.ItemSelected += OnCompanyItemSelected;
}
//this will handle the ItemSelected event
//here you will retrieve the data for the second UITableView
void OnCompanyItemSelected(object sender, Company e)
{
//you can do it this way
tblView2.Source = new CarTableSource(e.Id);
List<Car> cars = GetCarsByCompanyId(e.Id);
//or this whay
tblView2.Source = new CarTableSource(cars);
}
List<Car> GetCarsByCompanyId(int id)
{
//Your logic to get the data goes here
throw new NotImplementedException();
}
}
public class CompanyTableSource : UITableViewSource
{
// You can use the whole object or just an integer (companyId)
public event EventHandler<Company> ItemSelected;
public IList<Company> Items { get; private set; } = new List<Company>();
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var item = Items[indexPath.Row];
ItemSelected?.Invoke(this, item);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
//Do your implementation
throw new NotImplementedException();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return Items.Count;
}
}
public class CarTableSource : UITableViewSource
{
public IList<Car> Items { get; private set; } = new List<Car>();
public CarTableSource(int companyId)
{
//Get your data based on the companyId
}
//Or pass in the data already retreived. (I preffer this method)
public CarTableSource(IList<Car> cars)
{
Items = cars;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
//Do your implementation
throw new NotImplementedException();
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return Items.Count;
}
}

iOS TableView button is being called multiple times

I have a TableView with a custom UITableViewCell. In each cell I have multiple buttons, when any of the buttons is click after scrolling down and up it calls itself the many times I scroll down and up.
I have read and research for a solution and I haven't found a solution.
I know the problem is the cell are being reuse so that's why the buttons are being call multiple times but I can't find a way to prevent it.
I added console write line statements through the code and the else part in MoveToWindow is never call. Could that be the reason why?
Research material for solution:
my code is calling twice the btndelete method in uitableview
UIButton click event getting called multiple times inside custom UITableViewCell
My Code:
namespace Class.iOS
{
public partial class CustomCell : UITableViewCell
{
public static readonly NSString Key = new NSString ("CustomCell");
public static readonly UINib Nib;
public int Row { get; set; }
public event EventHandler LikeButtonPressed;
private void OnLikeButtonPressed()
{
if (LikeButtonPressed != null)
{
LikeButtonPressed(this, EventArgs.Empty);
}
}
public override void MovedToWindow()
{
if (Window != null)
{
btnAdd.TouchUpInside += HandleLikeButtonPressed;
}
else
{
btnAdd.TouchUpInside -= HandleLikeButtonPressed;
}
}
private void HandleLikeButtonPressed(object sender, EventArgs e)
{
OnLikeButtonPressed();
}
static CustomCell ()
{
Nib = UINib.FromName ("CustomCell", NSBundle.MainBundle);
}
public CustomCell ()
{
}
public CustomCell (IntPtr handle) : base (handle)
{
}
public void UpdateCell (string Name, int number)
{
// some code
}
public class TableSource : UITableViewSource
{
public override nint RowsInSection (UITableView tableview, nint section)
{
return 8;
}
private void HandleLikeButtonPressed(object sender, EventArgs e)
{
var cell = (CustomCell)sender;
var row = cell.Row;
switch (row)
{
case 0:
cell.label.Text = ""
break;
case 1:
cell.label.Text = ""
break;
}
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (CustomCell.Key) as CustomCell;
cell.Row = indexPath.Row;
if (cell == null)
{
cell = new CustomCell ();
var views = NSBundle.MainBundle.LoadNib("CustomCell", cell, null);
cell.LikeButtonPressed += HandleLikeButtonPressed;
cell = Runtime.GetNSObject( views.ValueAt(0) ) as CustomCell;
}
cell.UpdateCell
(
// some code
);
return cell;
}
}
}
}
The cells are reused in iOS, so you need to make sure you properly unhook handlers and reset state when a cell is reused. You can do something like this:
public partial class CustomCell : UITableViewCell {
EventHandler _likeButtonHandler;
public static readonly NSString Key = new NSString (typeof(CustomCell).Name);
public static readonly UINib Nib = UINib.FromName (typeof(CustomCell).Name, NSBundle.MainBundle);
public CustomCell ()
{
}
public CustomCell (IntPtr handle) : base (handle)
{
}
public override void PrepareForReuse ()
{
LikeButton.TouchUpInside -= _likeButtonHandler;
_likeButtonHandler = null;
base.PrepareForReuse ();
}
public void SetupCell (int row, string Name, EventHandler likeBtnHandler)
{
_likeButtonHandler = likeBtnHandler;
LikeButton.TouchUpInside += _likeButtonHandler;
LikeButton.Tag = row;
NameLabel.Text = Name;
RowLabel.Text = row.ToString ();
}
Notice that I unhook the event handler in the PrepareForReuse override. This is the correct place to do clean up and reset a cell for reuse. You should NOT be using MovedToWindow().
Then your GetCell method will look like this:
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell (CustomCell.Key) as CustomCell ?? new CustomCell ();
cell.SetupCell (indexPath.Row, _fruits [indexPath.Row], _likeButtonHandler);
return cell;
}
The _likeButtonHandler is a simple EventHandler.

How do you handle Touch Events in a UITableView

I'm trying to apply an event to a cell in order to specify the TouchesBegan method.
cell.TouchesBegan += OnTouchesBegan;
But TouchesBegan is a method group and not an event.
How do I add custom behavior to a Cells TouchesBegan() method in monotouch?
[Register("MenuView")]
public class MenuView : ViewControllerBase
{
private new MenuViewModel ViewModel { get { return (MenuViewModel)base.ViewModel; } }
public override void ViewDidLoad()
{
base.ViewDidLoad();
// this ensures the sliding panel doesn't fill the entire view.
var frame = View.Frame;
frame.Width = 300;
View.Frame = frame;
var chapters = ViewModel.Chapters;
//var listHeight = (chapters.Count*40);
var navigationList = new UITableView(new RectangleF(0, 50, 300, 300))
{
Source = new NavigationTableSource(chapters)
};
Add(navigationList);
}
}
public class NavigationTableSource : UITableViewSource
{
private readonly IList<ChapterViewModel> _chapters;
private const string CellIdentifier = "NavigationCell";
public NavigationTableSource(IList<ChapterViewModel> chapters)
{
_chapters = chapters;
}
public override int RowsInSection(UITableView tableview, int section)
{
return _chapters.Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
// if there are no cells to reuse, create a new one
cell.TextLabel.Text = _chapters[indexPath.Row].Title;
cell.TouchesBegan += OnTouchesBegan;
return cell;
}
}
TouchesBegan is a method that you can override by subclassing UITableViewCell:
public class CustomCell : UITableViewCell
{
public CustomCell(UITableViewCellStyle style, NSString reuseIdentifier) : base(style, reuseIdentifier)
{
}
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
// do something
base.TouchesBegan(touches, evt);
}
}
Then use your subclass when creating a cell:
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new CustomCell(UITableViewCellStyle.Default, CellIdentifier);
So the way I was able to manage this was to SubClass my UITableViewSource. In there I overrode RowSelected(UITableView tableView, NSIndexPath indexPath)
public class NavigationTableSource : UITableViewSource
{
private readonly IList<ChapterViewModel> _chapters;
private const string CellIdentifier = "NavigationCell";
public NavigationTableSource(IList<ChapterViewModel> chapters)
{
_chapters = chapters;
}
public override int RowsInSection(UITableView tableview, int section)
{
return _chapters.Count;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
// todo: This is where we're going to load up the appropriate chapter.
new UIAlertView("Row Selected", _chapters[indexPath.Row].Title, null, "OK", null).Show();
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var cell = tableView.DequeueReusableCell(CellIdentifier) ??
new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
// if there are no cells to reuse, create a new one
cell.TextLabel.Text = _chapters[indexPath.Row].Title;
return cell;
}
}

Categories

Resources