UITableViewController resetting data source - uitableview

I have a UITableViewController that is presented as the view controller of a UIPopOverController. The tvc has three properties - a dictionary and two arrays. The dictionary holds two arrays, which are used to populate the other two properties. I follow this process:
In root view controller I init the table view controller
On a trigger I set the dictionary property of the table view controller and call a method (reloadData).
- (void) reloadData {
self.arrGroupSearches = [self.dictSavedSearches objectForKey:#"Group Searches"];
self.arrCustomerSearches = [self.dictSavedSearches objectForKey:#"Customer Searches"];
[self.tableView reloadData];
}
as I step through the method it the data is brought in as I expected.
self SavedSearchesPopoverViewController * 0x786653c0 0x786653c0
UITableViewController UITableViewController
_dictSavedSearches NSDictionary * 2 key/value pairs 0x79fb6ab0
_arrGroupSearches NSArray * #"1 object" 0x79fb6b00
_arrCustomerSearches NSArray * #"0 objects" 0x79faf410
but once the code hits [self.tableView reloadData] call, it resets the viewcontroller properties
self SavedSearchesPopoverViewController * 0x786653c0 0x786653c0
UITableViewController UITableViewController
_dictSavedSearches NSDictionary * 0 key/value pairs 0x79938560
_arrGroupSearches NSArray * #"0 objects" 0x78744160
_arrCustomerSearches NSArray * #"0 objects" 0x78744160
I'm not really sure what I am doing wrong here.
Edit: Here's the whole implementation:
#implementation SavedSearchesPopoverViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.arrCustomerSearches = [[NSArray alloc] init];
self.arrGroupSearches = [[NSArray alloc] init];
self.dictSavedSearches = [[NSDictionary alloc] init];
self.tableView.rowHeight = 30.0;
}
- (void) reloadData {
self.arrGroupSearches = [self.dictSavedSearches objectForKey:#"Group Searches"];
self.arrCustomerSearches = [self.dictSavedSearches objectForKey:#"Customer Searches"];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView* vHeader = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, tableView.frame.size.width, 40.0)];
if (section == 0) {
UILabel* lblPopoverTitle = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 5.0, 240.0, 30.0)];
lblPopoverTitle.text = #"Group Saved Searches";
lblPopoverTitle.textColor = GMT_BRIGHT_BLUE;
lblPopoverTitle.font = FORM_NAME;
lblPopoverTitle.textAlignment = NSTextAlignmentCenter;
[vHeader addSubview:lblPopoverTitle];
} else if (section == 1) {
UILabel* lblPopoverTitle = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 5.0, 240.0, 30.0)];
lblPopoverTitle.text = #"Customer Saved Searches";
lblPopoverTitle.textColor = GMT_BRIGHT_BLUE;
lblPopoverTitle.font = FORM_NAME;
lblPopoverTitle.textAlignment = NSTextAlignmentCenter;
[vHeader addSubview:lblPopoverTitle];
}
vHeader.backgroundColor = GMT_DARK_BLUE;
return vHeader;
}
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 40.0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0) {
return self.arrGroupSearches.count;
} else if (section == 1) {
return self.arrCustomerSearches.count;
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString* strValue;
if (indexPath.section == 0) {
strValue = [self.arrGroupSearches objectAtIndex:indexPath.row];
} else if (indexPath.section == 1) {
strValue = [self.arrCustomerSearches objectAtIndex:indexPath.row];
}
cell.textLabel.text = strValue;
cell.textLabel.textColor = GMT_DARK_BLUE;
cell.textLabel.font = TABLE_CELL_FONT;
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary* dictUserData = [[NSDictionary alloc] initWithObjectsAndKeys:
nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"cvc" object:self userInfo:dictUserData];
}
The view controller is init in another view controller (contentViewController) in the view did load:
self.mySavedSearchesPopover = [[SavedSearchesPopoverViewController alloc] init];
and presented in the popover like so:
if (showSavedSearches) {
//check to see if there are saved searches first before presenting popover
NSDictionary* dictSavedSearches = [self.myController readPlistFile:#"savedSearches"];
if (![dictSavedSearches objectForKey:#"Error Message"]) {
self.mySavedSearchesPopover.dictSavedSearches = [self.myController getSavedSearches:dictSavedSearches];
[self.mySavedSearchesPopover reloadData];
[self.mySavedSearchesPopover.tableView reloadData];
[self presentPopover:SAVED_SEACHES_POPOVER];
} else {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"savedSearchErrorTitle", nil) message:NSLocalizedString(#"savedSearchErrorMsg", nil) delegate:nil cancelButtonTitle:NSLocalizedString(#"ok", nil) otherButtonTitles:nil, nil];
[alert show];
}
}
- (void) presentPopover : (int) popoverID {
if (self.currentPopoverController != nil) {
[self.currentPopoverController dismissPopoverAnimated:YES];
self.currentPopoverController = nil;
}
CGRect launchFrame;
...
} else if (popoverID == SAVED_SEACHES_POPOVER) {
//this is inited in the update view method
launchFrame = CGRectMake(0.0, 70.0, 0.0, 180.0);
self.currentPopoverController = [[UIPopoverController alloc] initWithContentViewController:self.mySavedSearchesPopover];
self.currentPopoverController.popoverContentSize = CGSizeMake(240.0, 300.0);
...
//display popovercontroller
[self.currentPopoverController presentPopoverFromRect:launchFrame inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionLeft
animated:YES];

In the following code block where you present the popover:
[self.mySavedSearchesPopover reloadData];
[self.mySavedSearchesPopover.tableView reloadData];
[self presentPopover:SAVED_SEACHES_POPOVER];
The viewDidLoad method is firing after you call [self.mySavedSearchesPopover reloadData] which is recreating those properties with empty arrays. You need to call reloadData after you present the popover.

Related

The cell of tavbview quickly slides into a blank

A tabview pull up, load the new data, and then quickly pull up, the above cell disappears and becomes blank,I guess because the refresh time, the data is not with the new
This is the main code:
#interface DYBOrdersViewController ()<UITableViewDelegate,UITableViewDataSource>
#property(nonatomic,strong)NSMutableArray * currentArr;
#property(nonatomic,strong)NSArray * dataArr;
#property(nonatomic,strong)UITableView * mainTab;
#property(nonatomic,strong)UIRefreshControl * refreshC;
#property(nonatomic,assign)BOOL isPull;
#property(nonatomic,assign)CGFloat cellheight;
#end
static NSString * orderID = #"orderID";
#implementation DYBOrdersViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray * mutarr0 = [NSMutableArray arrayWithObjects:#"全部",#"全部",#"全部",#"完成",#"全部", nil];
NSMutableArray * mutarr1 = [NSMutableArray arrayWithObjects:#"待取件",#"待取件",#"待取件",#"待取件", nil];
NSMutableArray * mutarr2 = [NSMutableArray arrayWithObjects:#"未完成",#"未完成",#"未完成", nil];
NSMutableArray * mutarr3 = [NSMutableArray arrayWithObjects:#"已完成",#"已完成", nil];
NSMutableArray * mutarr4 = [NSMutableArray arrayWithObjects:#"已取消", nil];
self.dataArr = #[mutarr0,mutarr1,mutarr2,mutarr3,mutarr4];
self.currentArr = self.dataArr[0];
[self setUI];
self.automaticallyAdjustsScrollViewInsets = NO;
}
// 设置界面
-(void)setUI{
UIRefreshControl * refreshC = [[UIRefreshControl alloc]initWithFrame:self.navBar.bounds];
self.refreshC = refreshC;
[refreshC beginRefreshing];
[refreshC addTarget:self action:#selector(loadData) forControlEvents:UIControlEventValueChanged];
NSArray * segArr = #[#"全部",#"待取件",#"待收货",#"待评价",#"已取消"];
UISegmentedControl * segC = [[UISegmentedControl alloc]initWithItems:segArr];
segC.frame = CGRectMake(0,64, self.view.frame.size.width,40);
segC.tintColor = [UIColor sun_colorWithHex:0x0082f5];
//实现添加的事件
[segC addTarget:self action:#selector(change:) forControlEvents:UIControlEventValueChanged];
// 创建刷新界面
UITableView * tabV = [[UITableView alloc]initWithFrame:CGRectMake(0,CGRectGetMaxY(segC.frame), [UIScreen mainScreen].bounds.size.width, self.view.frame.size.height - CGRectGetMaxY(segC.frame)-self.tabBarController.tabBar.frame.size.height) style:UITableViewStylePlain];
tabV.separatorStyle = UITableViewCellSeparatorStyleNone;
tabV.showsVerticalScrollIndicator = NO;
tabV.delegate = self;
tabV.dataSource = self;
self.mainTab = tabV;
[tabV registerClass:[DYBOrdersViewCell class] forCellReuseIdentifier:orderID];
[tabV addSubview:self.refreshC];
[self.view addSubview:tabV];
[self.view addSubview:segC];
}
// Refresh data method
-(void)loadData{
[self.refreshC endRefreshing];
[self.currentArr addObject:#"新数据"];
self.isPull = NO;
[self.mainTab reloadData];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 100;
}
//点击不同分段就会有不同的事件进行相应
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSLog(#"%lu",(unsigned long)self.currentArr.count);
return self.currentArr.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
DYBOrdersViewCell * cell = [tableView dequeueReusableCellWithIdentifier:orderID forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
// cell.textLabel.text = self.currentArr[indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DYBOrderdetailController * VC = [[DYBOrderdetailController alloc]init];
VC.title = #"订单详情";
VC.view.backgroundColor = [UIColor whiteColor];
[self.navigationController pushViewController:VC animated:YES];
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
// 将要显示的最后一组
NSInteger section = indexPath.section;
// 所有cell数
NSInteger count = [tableView numberOfRowsInSection:section];
//将要显示的row数量
NSInteger row = indexPath.row ;
if (section <0 || row <0) {
return;
}
// 如果是最后一行最后一个cell 数据刷新
if (row == count -1 && !self.isPull) {
NSLog(#"要刷新了");
self.isPull = YES;
[self loadData];
}
}

UILabel showing wrong

i'm using a tableview to load datas from my college db, the table load the tablecell normally... but when i scroll down the table the name of the discipline goes well but the grade is showing up one on top of above
why is that?
#import "NFMainViewController.h"
#import "NFData.h"
#interface NFMainViewController ()
#end
#implementation NFMainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
data = [[NFData getData] objectForKey:#"data"];
cursoData = nil;
cursosView = [[UIViewController alloc] init];
[cursosView setTitle:#"Cursos"];
cursosTable = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[cursosTable setDelegate:self];
[cursosTable setDataSource:self];
[cursosView.view addSubview:cursosTable];
[self pushViewController:cursosView animated:NO];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - TableView delegates
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (tableView == cursosTable) {
return [data count];
} else {
return [cursoData count];
}
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *ident = #"headerIdent";
UITableViewHeaderFooterView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ident];
if (view == nil) {
view = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:ident];
}
if (tableView == cursosTable) {
view.textLabel.text = [[data objectAtIndex:section] objectForKey:#"unidade"];
} else {
NSDictionary *temp = [cursoData objectAtIndex:section];
view.textLabel.text = [NSString stringWithFormat:#"%#º/%#", [temp objectForKey:#"semestre"], [temp objectForKey:#"ano"]];
}
return view;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == cursosTable) {
return [[[data objectAtIndex:section] objectForKey:#"cursos"] count];
} else {
return [[[cursoData objectAtIndex:section] objectForKey:#"disciplinas"] count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ident = #"cellIdent";
UITableViewCell *view = [tableView dequeueReusableCellWithIdentifier:ident];
if (view == nil) {
view = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ident];
}
if (tableView == cursosTable) {
view.textLabel.text = [[[[data objectAtIndex:indexPath.section] objectForKey:#"cursos"] objectAtIndex:indexPath.row] objectForKey:#"curso"];
} else {
UIFont *font = [UIFont fontWithName:#"Arial" size:10.0f];
view.textLabel.font = font;
view.selectionStyle = UITableViewCellSelectionStyleNone;
NSDictionary *temp = [[[cursoData objectAtIndex:indexPath.section] objectForKey:#"disciplinas"] objectAtIndex:indexPath.row];
view.textLabel.text = [temp objectForKey:#"disciplina"];
CGRect notaRect = view.bounds;
notaRect.origin.x = notaRect.size.width - 70.0f;
notaRect.size.width = 50.0f;
UILabel *nota = [[UILabel alloc] initWithFrame:notaRect];
nota.textAlignment = NSTextAlignmentRight;
nota.font = font;
nota.text = [temp objectForKey:#"nota"];
[view addSubview:nota];
CGRect labelRect = view.textLabel.frame;
labelRect.size.height -= 60;
view.textLabel.frame = labelRect;
CGRect progRect = view.bounds;
progRect.origin.x += 6.0f;
progRect.size.width -= 12.0f;
progRect.origin.y += progRect.size.height - 6.0f;
progRect.size.height = 5.0f;
UIProgressView *prog = [[UIProgressView alloc] initWithFrame:progRect];
int faltas = [[temp objectForKey:#"faltas"] intValue];
int maximo = [[temp objectForKey:#"maximo"] intValue];
float value = 1.0f * faltas / maximo;
if (value > 1.0f) {
prog.progressTintColor = [UIColor blackColor];
} else if (value == 1.0f) {
prog.progressTintColor = [UIColor redColor];
} else if (value >= 0.7f) {
prog.progressTintColor = [UIColor yellowColor];
}
[prog setProgress:value];
[view addSubview:prog];
}
return view;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == cursosTable) {
cursoData = [[[[data objectAtIndex:indexPath.section] objectForKey:#"cursos"] objectAtIndex:indexPath.row] objectForKey:#"epocas"];
notasView = [[UIViewController alloc] init];
[notasView setTitle:#"Disciplinas"];
notasTable = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds];
[notasTable setDelegate:self];
[notasTable setDataSource:self];
[notasView.view addSubview:notasTable];
[self pushViewController:notasView animated:YES];
}
}
#end
Your nota UILabel is created each time a UITableViewCell is dequeued. So the first time the tableview loads everything is fine. Then when you start scrolling, your code reuse cells with the nota label already created, but you add another label on top of it. You need to reuse the label previously created.
The best way is to create a UITableViewCell subclass with a nota property for instance.

Push a new UIViewController when I click in a cell in a UIPopoverController

I need to open a ViewController when I click in a UIPopoverController cell.
SeccionesViewController is the ViewController that I put in the UIPopoverController, that is a table. The function that not works is didSelectRowAtIndexPath from TableView.
Thank you for advance.
My code to show UIPopoverController is:
-(IBAction)seccionesButtonTapped:(id)sender
{
if (_itemPicker == nil) {
//Create the ColorPickerViewController.
_itemPicker = [[SeccionesViewController alloc] initWithStyle:UITableViewStylePlain];
//Set this VC as the delegate.
_itemPicker.delegate = self;
}
if (_itemPickerPopover == nil) {
//The color picker popover is not showing. Show it.
_itemPickerPopover = [[UIPopoverController alloc] initWithContentViewController:_itemPicker];
//[_itemPickerPopover presentPopoverFromBarButtonItem:(UIBarButtonItem *) sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
[_itemPickerPopover presentPopoverFromRect:CGRectMake(350, 902, 300, 300) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
} else {
//The color picker popover is showing. Hide it.
[_itemPickerPopover dismissPopoverAnimated:YES];
}
}
The SeccionesViewController code is:
-(id)initWithStyle:(UITableViewStyle)style
{
if ([super initWithStyle:style] != nil) {
//Initialize the array
_itemNames = [NSMutableArray array];
//Set up the array of colors.
[_itemNames addObject:AMLocalizedString(#"listaTareas", #"")];
[_itemNames addObject:AMLocalizedString(#"EventosTab", #"")];
//Make row selections persist.
self.clearsSelectionOnViewWillAppear = NO;
//Calculate how tall the view should be by multiplying the individual row height
//by the total number of rows.
NSInteger rowsCount = [_itemNames count];
NSInteger singleRowHeight = [self.tableView.delegate tableView:self.tableView heightForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
NSInteger totalRowsHeight = rowsCount * singleRowHeight;
//Calculate how wide the view should be by finding how wide each string is expected to be
CGFloat largestLabelWidth = 0;
for (NSString *itemName in _itemNames) {
//Checks size of text using the default font for UITableViewCell's textLabel.
CGSize labelSize = [itemName sizeWithFont:[UIFont boldSystemFontOfSize:20.0f]];
if (labelSize.width > largestLabelWidth) {
largestLabelWidth = labelSize.width;
}
}
//Add a little padding to the width
CGFloat popoverWidth = largestLabelWidth + 100;
//Set the property to tell the popover container how big this view will be.
self.contentSizeForViewInPopover = CGSizeMake(popoverWidth, totalRowsHeight);
}
return self;
}
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_itemNames count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = [_itemNames objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selectedItem = [_itemNames objectAtIndex:indexPath.row];
NSUserDefaults *dispositivo = [NSUserDefaults standardUserDefaults];
NSString *dis = [dispositivo stringForKey:#"dispositivo"];
if ([selectedItem isEqualToString:AMLocalizedString(#"listaTareas", #"")]) {
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:dis bundle:nil];
ListaTareasViewController *tareas= [storyBoard instantiateViewControllerWithIdentifier:#"ListaTareasView"];
tareas.communitykey = communitykey;
tareas.tituloAsig = tituloAsig;
tareas.infoH = infoH;
if ((vengoDe != 1) && (vengoDe != 2) && (vengoDe != 3)) {
tareas.vengoDe = 1;
}else{
tareas.vengoDe = vengoDe;
}
tareas.infoAsig = infoAsig;
[self.navigationController pushViewController:tareas animated:YES];
}else if ([selectedItem isEqualToString:AMLocalizedString(#"EventosTab", #"")]){
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:dis bundle:nil];
ListaEventosViewController *eventos= [storyBoard instantiateViewControllerWithIdentifier:#"listaEventosView"];
eventos.communitykey = communitykey;
eventos.nomAsig = tituloAsig;
eventos.infoH = infoH;
if ((vengoDe != 1) && (vengoDe != 2) && (vengoDe != 3)) {
eventos.vengoDe = 1;
}else{
eventos.vengoDe = vengoDe;
}
eventos.infoAsig = infoAsig;
[self.navigationController pushViewController:eventos animated:YES];
}
}
You have this code:
//Set this VC as the delegate.
_itemPicker.delegate = self;
which makes it look like you're on the right track. But then you reload the storyboard, instantiate a controller and push it into a navigation controller that doesn't exist (so, no crash, but no result either).
When you should be doing is using that delegate relationship to pass the selectedItem back to the source view controller. Once there, that view controller does have access to the navigation controller so it can decide how to use the selectedItem to create a controller and push that controller for display.
It is possible that you could pass tareas / eventos back to the delegate instead of selectedItem. Who should own the knowledge of which view controller is required and how it should be configured is something for you to decide based on your app structure.

Get segmentedcontrol value from tableviewcells

How do i get the value (the selected state) from my segmentedcontrols in the tableviewcells?
When i press the button "Get states" it should return the value for each of the segmented controls. I have tried different methods, but I can't find one that works :(
My code so far:
- (void)viewDidLoad
{
[super viewDidLoad];
tableData = [[NSMutableArray alloc] initWithCapacity:0];
tableData = [NSArray arrayWithObjects:#"First", #"Second", #"Third", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"StateCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"StateCell"];
}
//Config cell..
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
NSArray *itemArray = [NSArray arrayWithObjects: #"1", #"2", #"3", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(110, 7, 100, 28);
[cell.contentView addSubview:segmentedControl];
return cell;
[[self tableView] reloadData];
}
- (IBAction)getStates:(id)sender {
// Ruturn the current selected statement, for the individual cell's segmentedcontrol..
// Ex. First = SelectedState 1, Second = SelectedState 0 & Third = SelectedState 2..
}
So what I'm really is asking for; is what the "Get states" button action has to do..
Thanks for your time!
Your code has a couple of problems. Most of them happen because a UITableView reuses its cells.
You are creating a new UISegmentedControl each time a cell is displayed, which you should not. You should create the UISegmentedControl only if you create the cell, move that code into the cell == nil).
You don't have a dataSource that saves the state of the segments. You should not save states in views, especially not if you are dealing with a tableView, because cells are reused.
Here's an example that will get the functionality you need.
// this is an object of your model, it has a title and saves the selected index
#interface MBFancyObject : NSObject
#property (strong, nonatomic) NSString *title;
#property (assign, nonatomic) NSInteger selectedIndex;
#end
#implementation MBFancyObject
#end
#interface MasterViewController () {
NSMutableArray *_objects; // stores instances of MBFancyObject
}
#end
#implementation MasterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// set up the model
_objects = [NSMutableArray array];
for (NSInteger i = 0; i < 6; i++) {
MBFancyObject *object = [[MBFancyObject alloc] init];
object.title = [NSString stringWithFormat:#"Object #%ld", (long)i];
object.selectedIndex = i % 3;
[_objects addObject:object];
}
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:#"Get States" style:UIBarButtonItemStyleBordered target:self action:#selector(logStates:)];
self.navigationItem.rightBarButtonItem = button;
}
#pragma mark - Table View
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FancyCell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"FancyCell"];
// add the segmentedControl when you create a new cell
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"1", #"2", #"3"]];
segmentedControl.frame = CGRectMake(110, 7, 100, 28);
[cell.contentView addSubview:segmentedControl];
// add an action so we can change our model if the view changes
[segmentedControl addTarget:self action:#selector(didChangeSegmentedControl:) forControlEvents:UIControlEventValueChanged];
// use a tag so we can retrieve the segmentedControl later
segmentedControl.tag = 42;
}
// either if the cell could be dequeued or you created a new cell,
// segmentedControl will contain a valid instance
UISegmentedControl *segmentedControl = (UISegmentedControl *)[cell.contentView viewWithTag:42];
MBFancyObject *object = _objects[indexPath.row];
cell.textLabel.text = object.title;
segmentedControl.selectedSegmentIndex = object.selectedIndex;
return cell;
}
- (IBAction)didChangeSegmentedControl:(UISegmentedControl *)sender {
// transform the origin of the cell to the frame of the tableView
CGPoint senderOriginInTableView = [self.tableView convertPoint:CGPointZero fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
NSAssert(indexPath, #"must have a valid indexPath");
MBFancyObject *object = _objects[indexPath.row];
object.selectedIndex = sender.selectedSegmentIndex;
}
- (IBAction)logStates:(id)sender {
// query the model, not the view
for (NSInteger i = 0; i < [_objects count]; i++) {
MBFancyObject *object = _objects[i];
NSLog(#"Object \"%#\" - %ld", object.title, (long)object.selectedIndex);
// since you have only one section, each indexPath is 0,i
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
}
}
#end
Use an array to store all the segment control values, and when click one segment control then just change the value correspondingly.
You have serious problem with reusing here
Do not ever allocate a new UI element in tableView:cellForRowAtIndexPath: method unless it is in the if condition if (cell == nil)
Change What in Your tableView:cellForRowAtIndexPath: to be
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"StateCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"StateCell"];
// Add the Segmented Control
NSArray *itemArray = [NSArray arrayWithObjects: #"1", #"2", #"3", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(110, 7, 100, 28);
segmentedControl.tag = 1;
[cell addSubview:segmentedControl];
}
//Config cell..
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
// Get that Segmented Control
UISegmentedControl *segmentedControl = (UISegmentedControl *)[cell viewWithTag:1];
segmentedControl.selectedSegmentIndex = 0; // Set your default value here or add your data in an array and read from that array
return cell;
Then in the action of the button do that
for (UITableViewCell *cell in [tableView visibleCells]) {
UISegmentedControl *segmentedControl = (UISegmentedControl *)[cell viewWithTag:1];
NSLog(#"%d",segmentedControl.selectedSegmentIndex);
}
However this code is not perfect unless you have only 3 cells in your table to avoid reuse or visibility problem

ReloadData (UITableView) doesn't work

I got a big problem.
[self.tableView reloadData];
Doesn't work, and I don't understand why.
[[self tableView] reloadData];
Doesn't work too.
Here is my code:
.h
#interface ArticleViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
{
}
#end
.m
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
}
btnLeft = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"btnLeft"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(loadPlist)];
self.navigationItem.leftBarButtonItem = btnLeft;
In the loadPlist method, I'm writing in a .plist file. This part work fine.
Once all is write in the .plist file :
btnRight = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"btnRight"]
style:UIBarButtonItemStylePlain
target:self
action:#selector(reloadTheTB)];
self.navigationItem.rightBarButtonItem = btnRight;
- (void)reloadTheTB {
NSLog(#"Test reloadTheTB");
[[self tableView] reloadData];
}
If I touch btnRight, I can see in the log "Test reloadTheTB".
Here is tableView:cellForRowAtIndexPath:
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
cell = [self getCellContentView:CellIdentifier];
contentDictio = [dict objectAtIndex:indexPath.row];
UILabel *lblTemp1 = (UILabel *)[cell viewWithTag:1];
lblTemp1.text = [contentDictio objectForKey:#"title"];
if(indexPath.row % 2) {
UIView* myBackgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
myBackgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"cell_grise"]];
cell.backgroundView = myBackgroundView;
}
else {
UIView* myBackgroundView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
myBackgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"cell_blanche"]];
cell.backgroundView = myBackgroundView;
}
}
return cell;
}
UPDATE:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [dict count];
}
Help me please...
Actually I'm wondering this how you know that reloadData is not called?
Try to put some log in cellForRowAtIndexPath? to see if is called or not when you click your button? and also in do this :
- (void)reloadTheTB {
NSLog(#"Test reloadTheTB");
NSLog(#"%#",dict);
[[self tableView] reloadData];
}
Is the content of your dictionary what you expect? or is not changed after loadPlist?
Probably the call to reloadData is not executed on the main thread and you can update the UI only on the main thread. Try to execute your method on the main thread doing something like this :
-(void)ReloadTheTB{
[self.tableView performSelectorOnMainThread#selector(reloadData) withObject:nil waitUntilDone:NO]
}

Resources