This question already has answers here:
UITableView cells strangely disappearing
(2 answers)
Closed 9 years ago.
Very strange problem here.
Essentially what is happening is that our Tableview cells are becoming hidden in some cases when we simply put the app to sleep and then re-unlock. Our normal tableview looks like this:
And then when we re-open the app it will look like this:
All the rows and sections are set correctly, yet the cells are hidden.:
When this happens, our cellForRowAtIndexPath no longer gets called. This surely has to be the problem. Has anyone ever seen behavior like this? Here is how we set up the tableview. (sorry it is long)
//
// SPHomeViewController.m
// Spek
#interface SPHomeViewController () <UITableViewDataSource, UITableViewDelegate, MKMapViewDelegate, SPCreationViewDelegate, UIAlertViewDelegate, CLLocationManagerDelegate>
#property (nonatomic, strong) UITableView* tableView;
#property (nonatomic, strong) NSMutableArray* tableDatasource;
#property (nonatomic, strong) NSMutableArray* datasource;
#property (nonatomic, strong) NSMutableArray* friendsDatasource;
#property (nonatomic, strong) UISegmentedControl* userFilterSegment;
#property (nonatomic) BOOL isLoadingData;
#end
#implementation SPHomeViewController
#synthesize datasource = _datasource;
#synthesize friendsDatasource = _friendsDatasource;
#synthesize tableDatasource = _tableDatasource;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
//[[SPLocationManager locationManager] startUpdatingLocationForSig];
[self setNeedsStatusBarAppearanceUpdate];
self.view.backgroundColor = [UIColor colorWithRed:230.0f/255.0f green:230.0f/255.0f blue:230.0f/255.0f alpha:1.0];
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - kTopBarHeight)];
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.backgroundColor = [UIColor clearColor];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
if (self.creationView.center.y > self.view.frame.size.height) {
self.creationView = nil;
}
NSLog(#"Mem warning");
}
//****************************************
//****************************************
#pragma mark - UITableViewDelegate/DataSource
//****************************************
//****************************************
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"INDEX PATH ROW: %d AND SECTION: %d", indexPath.row, indexPath.section);
if (indexPath.section == 0) {
UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SPMapCellSpace"];
cell.backgroundColor = [UIColor clearColor];
cell.backgroundView = [[UIView alloc] init];
cell.selectedBackgroundView = [[UIView alloc] init];
return cell;
} else if (indexPath.section == self.tableDatasource.count + 1) {
UITableViewCell* cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SPBottomCellSpace"];
cell.backgroundColor = [UIColor clearColor];
cell.backgroundView = [[UIView alloc] init];
cell.selectedBackgroundView = [[UIView alloc] init];
return cell;
}
SPMark* mark = self.tableDatasource[indexPath.section - 1];
NSString* reuseId = [SPHomeViewController cellIdentifierFromData:mark];
SPTableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
if (cell == nil) {
cell = [SPTableViewCell cellFromMark:mark reuseID:reuseId];
[cell updateView:YES];
}
[cell addDataToCell:mark];
if (indexPath.section >= self.tableDatasource.count - 2 && !self.isLoadingData && self.pageNumber != -1) {
self.fetchNextPage = YES; // When the scrollview stops it will load more data if available.
}
return cell;
}
- (unsigned int)getPageNumber {
return (self.userFilterSegment.selectedSegmentIndex == 0) ? self.pageNumber : self.friendsPageNumber;
}
- (void)setCurrentPageNumber:(unsigned int)page {
if (self.userFilterSegment.selectedSegmentIndex == 0) {
self.pageNumber = page;
} else {
self.friendsPageNumber = page;
}
}
- (void)incrementCurrentPageNumber {
if (self.userFilterSegment.selectedSegmentIndex == 0) {
self.pageNumber++;
} else {
self.friendsPageNumber++;
}
}
// Every cell has a section header so this should be equal to the number of speks returned from the server
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"section count is: %d",self.tableDatasource.count + 2 );
return self.tableDatasource.count + 2; // Add two because the mapview needs to go on the top and extra spacing at the bottom.
}
// There is a section for every cell, so there is only one cell per section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return kMapHeight+2;
} else if (indexPath.section == self.tableDatasource.count + 1) {
return kExtraSpaceBelowHomeView;
}
SPMark* mark = self.tableDatasource[indexPath.section - 1];
return [SPTableViewCell cellHeightForMark:mark];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0 || indexPath.section == self.tableDatasource.count + 1) {
cell.backgroundColor = [UIColor clearColor];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0 || indexPath.section == self.tableDatasource.count + 1)
return;
SPMark* mark = self.datasource[indexPath.section - 1 ];
SPMarkViewController* markVC = [SPMarkViewController withMark:mark];
[markVC displayData];
[self.navigationController pushViewController:markVC animated:YES];
}
-(void)reloadTableview {
[self.tableView setDelegate:self];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
[self.tableView setNeedsDisplay];
});
}
- (void)showNoItems {
if (self.tableDatasource.count == 0 && self.accuracyBad == NO) {
self.opaqueIcon.hidden = NO;
self.noItems.hidden = NO;
self.beTheFirst.hidden = NO;
self.downArrow.hidden = NO;
self.noItemsBackround.hidden = NO;
[self.view bringSubviewToFront:self.noItemsBackround];
[self.view bringSubviewToFront:self.downArrow];
[self.view bringSubviewToFront:self.beTheFirst];
[self.view bringSubviewToFront:self.noItems];
[self.view bringSubviewToFront:self.opaqueIcon];
}
}
- (void)showTableView {
if (self.tableDatasource.count != 0) {
self.noItems.hidden = YES;
self.beTheFirst.hidden = YES;
self.downArrow.hidden = YES;
self.noItemsBackround.hidden = YES;
self.opaqueIcon.hidden = YES;
[self.view sendSubviewToBack:self.noItemsBackround];
[self.view sendSubviewToBack:self.downArrow];
[self.view sendSubviewToBack:self.beTheFirst];
[self.view sendSubviewToBack:self.noItems];
[self.view sendSubviewToBack:self.opaqueIcon];
}
}
//****************************************
//****************************************
#pragma mark - Setters/Getters
//****************************************
//****************************************
- (NSMutableArray*)datasource {
if (!_datasource) {
_datasource = [NSMutableArray array];
if (!self.firstLoad) {
[self loadDataForPagination:NO];
}
}
return _datasource;
}
- (NSMutableArray*)friendsDatasource {
if (!_friendsDatasource) {
_friendsDatasource = [NSMutableArray array];
if (!self.firstLoad) {
[self loadDataForPagination:NO];
}
}
return _friendsDatasource;
}
- (NSMutableArray*)tableDatasource {
if (!_tableDatasource) {
_tableDatasource = (self.userFilterSegment.selectedSegmentIndex == 0) ? self.datasource : self.friendsDatasource;
}
return _tableDatasource;
}
- (SPCreationView*)creationView {
if (!_creationView) {
UIView* window = [SPUtils getAppDelegate].window;
CGSize viewSize = window.frame.size;
CGRect startFrame = CGRectMake(0, viewSize.height, [SPUtils screenWidth], [SPUtils screenHeight]);
_creationView = [SPCreationView creationView:startFrame delegate:self];
[window insertSubview:_creationView belowSubview:self.creationButton];
_creationView.frame = startFrame;
}
return _creationView;
}
- (void)setTableDatasource:(NSMutableArray *)tableDatasource {
_tableDatasource = tableDatasource;
[self preFetchImages];
dispatch_async(dispatch_get_main_queue(), ^{
if(_tableDatasource == nil || _tableDatasource.count == 0) {
[self showNoItems];
} else {
[self showTableView];
}
[self reloadTableview];
});
}
- (void)setDatasource:(NSMutableArray *)datasource {
_datasource = datasource;
}
- (void)setFriendsDatasource:(NSMutableArray *)friendsDatasource {
_friendsDatasource = friendsDatasource;
}
#end
If you think it's a AppDelegate problem, we don't do anything with this controller in there, so I don't see how it could be.
I've only seen this occur previously when I was reloading data (incorrectly) from a background thread. I see you're trying to push the reloads onto the main thread already.
It looks like you're flailing a bit trying to be sure updates are occurring on the main thread. You should probably just verify that your actions are occurring on main by checking [NSThread isMainThread] rather than making your code async to the main thread, making lots of async flow changes can lead to unexpected behavior.
That said, since this only happens on wake from sleep maybe you have some background mode on and you aren't updating the UI from the correct thread there?
Related
When I load my tableView, the images change sizes as I filter through the uisegmentedcontrol.
Here is the code for my tableView (I have the fixed constraints for the UIImageView's width and height, but somehow they aren't adhered to):
#import "ScheduleTableViewController.h"
#import "TFHpple.h"
#import "Game.h"
#import "ScheduleCellTableViewCell.h"
#import "GameModel.h"
#define team #"Muskegon"
#interface ScheduleTableViewController ()
{
GameModel *_homeModel;
}
#property (nonatomic, strong) UISegmentedControl *segmentedControl;
#property (nonatomic, strong) NSMutableArray *omahaHomeGames;
#property (nonatomic, strong) NSMutableArray *omahaAwayGames;
#property (nonatomic, strong) NSMutableArray *omahaAllGames;
#property (nonatomic, strong) NSArray *objects;
#property UIActivityIndicatorView *spinner;
#end
#implementation ScheduleTableViewController
-(void)itemsDownloaded:(NSArray *)items
{
// This delegate method will get called when the items are finished downloading
// Filter through all the games for the games that contain Omaha as a home team and add them to the property omahaHomeGames
for (Game *game in items) {
if ([game.homeTeam containsString:team]) {
[_omahaHomeGames addObject:game];
}
}
// Filter through all the games for the games that contain Omaha as an away team and add them to the property omahaAwayGames
for (Game *game in items) {
if ([game.awayTeam containsString:team]) {
[_omahaAwayGames addObject:game];
}
}
// Filter through all the games for the games that contain Omaha as a home or away team and add them to the property omahaAllGames
for (Game *game in items) {
if ([game.homeTeam containsString:team] || [game.awayTeam containsString:team]) {
[_omahaAllGames addObject:game];
}
}
[_spinner stopAnimating];
// Reload the table view
[self.tableView reloadData];
}
- (instancetype) initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Create new HomeModel object and assign it to _homeModel variable
_homeModel = [[GameModel alloc] init];
// Set this view controller object as the delegate for the home model object
_homeModel.delegate = self;
// Call the download items method of the home model object
[_homeModel downloadItems];
// add a segmented control to filter by Home/Away
NSArray *divisions = [[NSArray alloc] initWithObjects:#"All", #"Home", #"Away", nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:divisions];
segmentedControl.frame = CGRectMake(0, 0, 120, 30);
segmentedControl.tintColor = [UIColor orangeColor];
[segmentedControl addTarget:self action:#selector(filterByHomeAway:) forControlEvents:UIControlEventValueChanged];
segmentedControl.selectedSegmentIndex = 0;
self.navigationItem.titleView = segmentedControl;
self.segmentedControl = segmentedControl;
// alloc and init properties
self.omahaAllGames = [[NSMutableArray alloc] init];
self.omahaHomeGames = [[NSMutableArray alloc] init];
self.omahaAwayGames = [[NSMutableArray alloc] init];
}
return self;
}
- (IBAction)filterByHomeAway:(id)sender
{
NSLog(#"Filter: %ld", (long)self.segmentedControl.selectedSegmentIndex);
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height;
spinner.center = CGPointMake(screenWidth/2.0, screenHeight/5.0);
spinner.hidesWhenStopped = YES;
[self.view addSubview:spinner];
[spinner startAnimating];
self.spinner = spinner;
// Load the Cell NIB file
UINib *nib = [UINib nibWithNibName:#"ScheduleCellTableViewCell" bundle:nil];
// Register this NIB, which contains the cell
[self.tableView registerNib:nib forCellReuseIdentifier:#"ScheduleCell"];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (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.
if (self.segmentedControl.selectedSegmentIndex == 0) {
return (self.omahaAllGames.count);
}
if (self.segmentedControl.selectedSegmentIndex == 1) {
return (self.omahaHomeGames.count);
}
if (self.segmentedControl.selectedSegmentIndex == 2) {
return self.omahaAwayGames.count;
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Get a new or recycled cell
ScheduleCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ScheduleCell" forIndexPath:indexPath];
if (self.segmentedControl.selectedSegmentIndex == 0) {
_objects = _omahaAllGames;
}
if (self.segmentedControl.selectedSegmentIndex == 1) {
_objects = _omahaHomeGames;
}
if (self.segmentedControl.selectedSegmentIndex == 2) {
_objects = _omahaAwayGames;
}
// Configure the cell
Game *thisGame = [_objects objectAtIndex:indexPath.row];
if (self.segmentedControl.selectedSegmentIndex == 0) {
cell.versusLabel.text = [NSString stringWithFormat:#"%# vs. %#", thisGame.homeTeam, thisGame.awayTeam];
}
if (self.segmentedControl.selectedSegmentIndex == 1) {
cell.versusLabel.text = [NSString stringWithFormat:#"%# vs. %#", team, thisGame.awayTeam];
}
if (self.segmentedControl.selectedSegmentIndex == 2) {
cell.versusLabel.text = [NSString stringWithFormat:#"%# vs. %#", team, thisGame.homeTeam];
}
// Trim the white space from before and after the date/time
NSString *day = [thisGame.dayString substringFromIndex: 8];
NSString *dayModified = [day substringWithRange: NSMakeRange(0, 11)];
NSString *time = [thisGame.timeString substringFromIndex:9];
NSString *timeModified = [time substringWithRange: NSMakeRange(0, 8)];
NSString *dateAndTime = [NSString stringWithFormat:#"%# %#", dayModified, timeModified];
cell.dateLabell.text = dateAndTime;
cell.locationLabel.text = thisGame.arena;
// Assign the image of the away team if home, and the home team if away, and the team that isn't Omaha if all
if (self.segmentedControl.selectedSegmentIndex == 0) {
[thisGame assignAllTeamImage];
cell.imageView.image = thisGame.image;
}
if (self.segmentedControl.selectedSegmentIndex == 1) {
[thisGame assignHomeTeamImage];
cell.imageView.image = thisGame.image;
}
if (self.segmentedControl.selectedSegmentIndex == 2) {
[thisGame assignAwayTeamImage];
cell.imageView.image = thisGame.image;
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
#end
How do I make them stay a consistent size? I just can't seem to make it work. Thank you.
Instead of displaying the image in the default imageView of cell, try creating a new imageView and adding it to the cell.
UIImageView *imageViewIcon = [[UIImageView alloc] initWithFrame:CGRectMake(5, 0, 50, 50)];
[cell addSubview:imageViewIcon];
if (self.segmentedControl.selectedSegmentIndex == 0) {
[thisGame assignAllTeamImage];
//cell.imageView.image = thisGame.image;
imageViewIcon.image = thisGame.image;
}
if (self.segmentedControl.selectedSegmentIndex == 1) {
[thisGame assignHomeTeamImage];
//cell.imageView.image = thisGame.image;
imageViewIcon.image = thisGame.image;
}
if (self.segmentedControl.selectedSegmentIndex == 2) {
[thisGame assignAwayTeamImage];
//cell.imageView.image = thisGame.image;
imageViewIcon.image = thisGame.image;
}
In the above code change the frame of the imageViewIcon as per your requirement.
And since you are using dequeueReusableCellWithIdentifier don't forget to give the imageViewIcon a tag and remove it at the beginning.
Hope this helps you. :)
In my app I have a popup with a [table view][1] .
When compiled with Xcode 5.1 everything works fine, but the same code compiled with Xcode 6.1 failed to call the [cellForRowAtIndexPath][3] [delegate][4] method.
The other delegate meths are called.
One intersting point is self.tableView.rowHeight; returns -1
I have tried explicitly setting the delegate and data source to self but that makes not difference
The class is called by the following code;
`-(IBAction)selectLanguage:(id)sender
{
ATLMLanguagePopoverTableViewController *pvc = [[ATLMLanguagePopoverTableViewController alloc] initWithNibName:nil bundle:nil];
pvc.target = self;
pvc.action = #selector(popoverDidSelectItem:);
pvc.items = [[[ATLMLibraryManager getManager]libraryDefaults]getAvailableLanguageNames];
_myPopoverController.contentViewController = pvc;
[_myPopoverController setPopoverContentSize:[pvc popoverContentSize]];
[_myPopoverController presentPopoverFromBarButtonItem:(UIBarButtonItem *)sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
`
Hear is the definition of the class
/
/ LanguagePopoverTableViewController.m
// SalesAid
//
// Created by phuang on 1/16/13.
// Copyright (c) 2013 Align Technology. All rights reserved.
//
#import "ATLMLanguagePopoverTableViewController.h"
#import "ATLMLocalizationManager.h"
#import "ATLMUtils.h"
#interface ATLMLanguagePopoverTableViewController ()
#end
#implementation ATLMLanguagePopoverTableViewController
#synthesize items, selectedItem, target, action;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
selectedItem = -1;
target = nil;
action = NULL;
}
return self;
}
-(void) resetLocalization {
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)setItems:(NSArray *)newItems {
items = [newItems copy];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
selectedItem=0;
NSString *curLang = (NSString *) [[ATLMLocalizationManager getManager]getCurrentLanguage] ;
for(int i = 0; i < items.count ; i++ ){
if([curLang isEqualToString:(NSString *)[items objectAtIndex:i]]){
selectedItem = i;
break;
}
}
NSIndexPath *i = [NSIndexPath indexPathForRow:selectedItem inSection:0];
[self.tableView selectRowAtIndexPath:i animated:NO scrollPosition:UITableViewScrollPositionNone];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (CGSize)popoverContentSize {
NSInteger rowHeight = self.tableView.rowHeight;
UITableView *tv = self.tableView;
rowHeight = 50;
return CGSizeMake(100, [items count] * rowHeight);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [items 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];
}
cell.textLabel.font = [UIFont systemFontOfSize:14];
UIView *myBackView = [[UIView alloc] initWithFrame:cell.frame];
myBackView.backgroundColor = [ATLMUtils getAlignBlue];
cell.selectedBackgroundView = myBackView;
[cell setSelectedBackgroundView: myBackView ];
NSString *textLabelKey = [items objectAtIndex:[indexPath indexAtPosition:1]];
cell.textLabel.text = ATLMLocalizedString(textLabelKey, nil);
cell.textLabel.textAlignment = NSTextAlignmentCenter;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedItem = indexPath.row;
if (target != nil && action != NULL) {
[target performSelector:action withObject:self];
}
}
#end
`
OK to answer my own question;
Basically the code adds the model to the view controller after the init method is called. However is seem the thread model has changed a bit and the view is created before the model is added so the row count in the model is zero
The solution is to pass the model as part of the init method.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil items:(NSArray *)itemArray
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
items = [itemArray copy];
selectedItem = -1;
target = nil;
action = nil;
}
return self;
}
I have a UITableView for an Instagram feed. I have implemented UIRefreshControl for pull to refresh functionality.
After drag and release the refresh control, and while the spinner is going, I'm able to drag the tableview down without the app crashing. However, if I scroll the tableview upwards, the app crashes (maybe because of cell 2, 3 etc?)
Here's a video showing the problem: http://www.screenmailer.com/v/DukT4lt2aUGm8c5MLRlGMg/2586/3a23tXo7uXs.mp4
Why is this happening?
Code for the .m file:
#import "InstagramViewController.h"
#import "InstagramCell.h"
#import <InstagramKit/InstagramKit.h>
#import "UIImageView+AFNetworking.h"
#interface InstagramViewController ()
{
NSMutableArray *mediaArray;
}
#property (nonatomic, strong) InstagramPaginationInfo *currentPaginationInfo;
#end
#implementation InstagramViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
//mediaArray = [[NSMutableArray alloc] init];
}
return self;
}
- (void)viewDidLoad
{
mediaArray = [[NSMutableArray alloc] init];
[super viewDidLoad];
[self loadMedia];
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(reloadMedia) forControlEvents:UIControlEventValueChanged];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
-(void)reloadMedia
{
self.currentPaginationInfo = nil;
[mediaArray removeAllObjects];
[self loadMedia];
}
-(IBAction)loadMedia
{
// start network indicator
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
[[InstagramEngine sharedEngine] getMediaWithTagName:#"AUFsommer" count:10 maxId:self.currentPaginationInfo.nextMaxId withSuccess:^(NSArray *media, InstagramPaginationInfo *paginationInfo) {
if (paginationInfo)
{
self.currentPaginationInfo = paginationInfo;
}
[mediaArray addObjectsFromArray:media];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
[self reloadData];
} failure:^(NSError *error) {
NSLog(#"Search Media Failed");
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}];
}
-(void)reloadData
{
[self.refreshControl endRefreshing];
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[UIView alloc] init];
headerView.backgroundColor = [UIColor colorWithWhite:1.0f alpha:0.9f];
InstagramMedia *media = mediaArray[section];
// create imageview for profile photo
AsyncImageView *profilePhoto = [[AsyncImageView alloc] initWithFrame:CGRectMake(8, 8, 32, 32)];
profilePhoto.layer.borderColor = [[UIColor colorWithRed:204.0/255.0f green:204.0/255.0f blue:204.0/255.0f alpha:1.0f] CGColor];
profilePhoto.layer.borderWidth = 1;
profilePhoto.layer.masksToBounds = YES;
profilePhoto.layer.cornerRadius = 16.0;
[profilePhoto loadImageFromURL:[media.user.profilePictureURL absoluteString]];
// uifont settings
UIFont *labelFont = [UIFont boldSystemFontOfSize:13.0];
// create label for username
UILabel *usernameLabel = [[UILabel alloc] initWithFrame:CGRectMake(48, 0, 210, 48)];
usernameLabel.text = media.user.username;
usernameLabel.font = labelFont;
usernameLabel.textColor = [UIColor colorWithRed:235.0/255.0 green:24.0/255.0 blue:22.0/255.0 alpha:1.0f];
// create label for timestamp
UILabel *timestampLabel = [[UILabel alloc] initWithFrame:CGRectMake(250, 0, 54, 48)];
timestampLabel.textAlignment = NSTextAlignmentRight;
timestampLabel.font = labelFont;
// timestampLabel.text = [self stringForDisplayFromDate:media.createdDate];
// add to view
[headerView addSubview:profilePhoto];
[headerView addSubview:usernameLabel];
[headerView addSubview:timestampLabel];
return headerView;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return mediaArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
InstagramCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[InstagramCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// clear photo
[cell.igPhoto setImage:nil];
if (mediaArray.count >= indexPath.section+1)
{
InstagramMedia *media = mediaArray[indexPath.section];
cell.title.text = media.caption.text;
[cell.igPhoto loadImageFromURL:[media.standardResolutionImageURL absoluteString]];
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
InstagramMedia *media = mediaArray[indexPath.section];
CGSize maximumLabelSize = CGSizeMake(304.0f, 20000.0f);
CGSize expectedLabelSize = [media.caption.text sizeWithFont:[UIFont systemFontOfSize:13.0f] constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping];
return (320.0f + expectedLabelSize.height + 20.0f);
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
CGFloat currentOffset = scrollView.contentOffset.y;
CGFloat maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height;
if (maximumOffset - currentOffset < 10.0)
{
[self loadMedia];
}
}
#end
The first thing you should do is to add an exception breakpoint in your project, so you will know why and where it crashes.
The reason why your app is crashing is that you try to read in an empty array. In the method reloadMedia, you do this :
self.currentPaginationInfo = nil;
[mediaArray removeAllObjects];
So at this point, your array is empty, but your UITableView is not aware of that. By scrolling before your data is reloaded, the methods cellForRowAtIndexPath will get called and try to access an index in your empty array.
To fix this, you can call [self.tableView reloadData]; after [mediaArray removeAllObjects];. This way, the UITableView will makes its call to know how many rows and sections it should have and will be aware there is no more rows and sections.
Or, if you want the old information to still be in your UITableView during the loading, just don't nil the currentPaginationInfo or empty mediaArray in reloadMedia,
Here's a run down of what I want to accomplish:
Main UIViewController is a UITableViewController
Tapping on a cell takes user to a new UIViewController where they can input text and save it
User can preview all the text saved on another UIViewController
When user re-arranges the table in the Main UIViewController, user can see the changes in the Preview
How can I change/move the text on the Preview UIViewController when the UITableViewController is re-arranged?
Any general approach, tips, tutorials, examples is much appreciated!
Thanks!
EDIT, Here's my code:
Singleton .h
#import <Foundation/Foundation.h>
#interface MyInformation : NSObject
{
NSMutableArray * informationArray;
NSMutableString * nameString;
NSMutableString * jobString;
}
#property (nonatomic, retain) NSMutableArray * informationArray;
#property (nonatomic, retain) NSMutableString * nameString;
#property (nonatomic, retain) NSMutableString * jobString;
+ (id)sharedInformation;
#end
Singleton .m
#import "MyInformation.h"
#implementation MyInformation
static MyInformation * _sharedMyInformation = nil;
#synthesize informationArray = _informationArray;
#synthesize nameString = _nameString;
#synthesize jobString = _jobString;
#pragma mark Singleton Methods
+ (id)sharedInformation
{
#synchronized(self)
{
if (_sharedMyInformation == nil)
{
_sharedMyInformation = [[self alloc] init];
}
}
return _sharedMyInformation;
}
- (id)init
{
if (self = [super init])
{
_nameString = [[NSMutableString alloc] init];
_jobString = [[NSMutableString alloc] init];
_informationArray = [[NSMutableArray alloc] initWithObjects:_nameString, _jobString, nil];
}
return self;
}
#end
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[UIScreen mainScreen] bounds].size.height == 568)
{
self.aTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 1136) style:UITableViewStyleGrouped];
self.aTableView.delegate = self;
self.aTableView.dataSource = self;
[self.view addSubview:self.aTableView];
self.editBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStylePlain target:self action:#selector(editButtonTapped)];
self.navigationItem.rightBarButtonItem = self.editBarButtonItem;
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.aTableView reloadData];
}
- (void)editButtonTapped
{
if (self.editing)
{
[super setEditing:NO animated:NO];
[self.aTableView setEditing:NO animated:NO];
[self.aTableView reloadData];
[self.editBarButtonItem setTitle:#"Edit"];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStylePlain];
}
else
{
[super setEditing:YES animated:YES];
[self.aTableView setEditing:YES animated:YES];
[self.aTableView reloadData];
[self.editBarButtonItem setTitle:#"Done"];
[self.editBarButtonItem setStyle:UIBarButtonItemStyleDone];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
MyInformation * myInformation = [MyInformation sharedInformation];
int count = [myInformation.informationArray count];
if (section == 0)
{
return count;
}
else if (section == 1)
{
return 1;
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * CellIdentifier = #"CellIdentifier";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
MyInformation * myInformation = [MyInformation sharedInformation];
if (indexPath.section == 0 && indexPath.row == 0)
{
cell.textLabel.text = [NSString stringWithFormat:#"%#", myInformation.nameString];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 0 && indexPath.row == 1)
{
cell.textLabel.text = [NSString stringWithFormat:#"%#", myInformation.jobString];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 1 && indexPath.row == 0)
{
cell.textLabel.text = #"Preview";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.section == 0 && indexPath.row == 0)
{
NameViewController * name = [[NameViewController alloc] initWithNibName:#"NameViewController" bundle:nil];
[self.navigationController pushViewController:name animated:YES];
}
if (indexPath.section == 0 && indexPath.row == 1)
{
JobViewController * job = [[JobViewController alloc] initWithNibName:#"JobViewController" bundle:nil];
[self.navigationController pushViewController:job animated:YES];
}
if (indexPath.section == 1 && indexPath.row == 0)
{
PreviewViewController * preview = [[PreviewViewController alloc] initWithNibName:#"PreviewViewController" bundle:nil];
[self.navigationController pushViewController:preview animated:YES];
}
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
MyInformation * myInformation = [MyInformation sharedInformation];
NSString * item = [myInformation.informationArray objectAtIndex:sourceIndexPath.row];
[myInformation.informationArray removeObjectAtIndex:sourceIndexPath.row];
[myInformation.informationArray insertObject:item atIndex:destinationIndexPath.row];
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 )
{
return YES;
}
else
{
return NO;
}
}
#end
EDIT 2:
I do not believe my array is getting updated.
Here's an example of my save code:
- (IBAction)saveButtonTapped
{
MyInformation * myInformation = [MyInformation sharedInformation];
if (_nameTextField.text == nil)
{
myInformation.nameString = #"";
}
else
{
[myInformation.nameString setString:#""];
[myInformation.nameString appendFormat:#"%#", _nameTextField.text];
}
[self.navigationController popToRootViewControllerAnimated:YES];
}
In this log, the nameString does update to whatever text I type in and save.
But my informationArray always returns as ( "", "" )
EDIT 3 & 4:
Hard coding the strings in the singleton with set characters.
Now I can rearrange my table which is good.
Below is the updated code. The labels on the preview page will rearrange when I rearrange the table.
Here's that code:
- (void)viewDidLoad
{
[super viewDidLoad];
MyInformation * myInformation = [MyInformation sharedInformation];
_nameLabel = [[UILabel alloc] init];
_nameLabel.frame = CGRectMake(20, 20, 300, 44);
_nameLabel.text = [NSString stringWithFormat:#"%#", [myInformation.informationArray objectAtIndex:0]];
_jobLabel = [[UILabel alloc] init];
_jobLabel.frame = CGRectMake(50, 50, 300, 44);
_jobLabel.text = [NSString stringWithFormat:#"%#", [myInformation.informationArray objectAtIndex:1]];
[self.view addSubview:_nameLabel];
[self.view addSubview:_jobLabel];
}
EDIT 5:
The only thing left to accomplish is how do I update the text in the strings in the singleton and in the UITableViewCells?
EDIT 6:
I solved the issue. I had to change the strings in the Singleton to NSMutableStrings. I modified my save button code to set the string to an empty value and the append it with the textfield text. After this it now works as expected!
Thank you for the help and suggestions!
I am assuming you have a backing NSMutableArray, but the answer should generalize to any data storage scheme.
Use tableView:moveRowAtIndexPath:toIndexPath: to detect when the user reorders the first table and update the backing array by removing the object at fromIndexPath.row and inserting it at toIndexPath.row. This makes sure that your backing models accurately reflect the changes the user just made in the UI.
When the user moves to the preview view, that view either needs to pull from the same shared data source (the one we modified in #1) or be given a copy of the just rearranged array. The latter case is simpler and can be done by adding an NSArray property on the preview controller: #property(nonatomic, copy) NSArray *itemsToPreview. Then ensure that the preview controller uses that array instead of the original one.
Apple's documentation on reordering table views is a good resource.
In iOS for the iPhone I want to make a control with similar appearance and behavior to the android spinner control when configured to behave like a drop down list box. Specifically when pressed a modal list of text options with radio buttons comes up and when one of them is pressed the list disappears and the control updates to that choice. Example:
So far I have seen a full-screen option using [self presentViewController...] with a custom ViewController but I want a partial screen (like pictured above) solution. Does anyone know how to do this or could point in the right direction.
The native solution to this will be a UIActionSheet which on iPhone will appear from the bottom and be partial screen or on iPad be very similar to the android version.
You can find the documentation here: UIActionSheet
if you didnt want to use the UIActionSheet and you wanted to make it reusable rather than adding a whole bund of UIViews to your current XIB, you could create a custom UIView with whatever interface you would need to populate it and use the interface builder to help make it look ok.
that view could have a message handler that posts the response that you would need to listen for.
then just init and load the view into your subviews and populate it
then post a message from the custom view to the handler you registered
so for your custom view you would have something like this.
#implementation SomeCustomView
+(SomeCustomView*)viewFromNibNamed:(NSString *)nibName{
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:NULL];
NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
SomeCustomView *customView = nil;
NSObject* nibItem = nil;
while ((nibItem = [nibEnumerator nextObject]) != nil) {
if ([nibItem isKindOfClass:[AADropDown class]]) {
customView = (SomeCustomView*)nibItem;
break;
}
}
return customView;
}
-(void)someInitializationWith:(NSArray*)repeatableData andNotificationId:(NSString*)noteId{
//set your stuff up for the view here and save the notification id
}
...
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[[NSNotificationCenter defaultCenter] postNotificationName:Your_Notification_Id object:somevalue];
}
#end
and include other things, like in this case the tableview stuff or any other logic.
then in your viewcontroller you could call it like
__block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:#"customViewAction" object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification *note) {
//deal with notification here
[[NSNotificationCenter defaultCenter] removeObserver: observer];
}];
SomeCustomView *cv =(SomeCustomView*) [SomeCustomView viewFromNibNamed:#"SomeCustomView"];
[cv someInitializationWith:arrayOptions andNotificationId:#"customViewAction"];
[self.view addSubview:cv];
and in your interface builder you will just need to make sure that the class of the view is set to your class type.
then you can easily reuse this code again whenever a user needs to select something else in the same manner.
Here is a variation on the solution suggested by AtomRiot.
On your view (xib or storyboard) make a button and assign this graphic to it. Don't worry if it appears stretched out in the editor. The code will make it a realizable graphic.
2X version
Then include the following files in your project (copied below):
DDLBHelper.h
DDLBHelper.m
Then in your ViewController's .h file make links to the button:
#property (weak, nonatomic) IBOutlet UIButton *ddlbB;
- (IBAction)ddlbBClick:(id)sender;
In you ViewController's .m file make the following calls:
#synthesize ddlbB, choiceLabel;
DDLBHelper *mDDLBH;
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *strings = [[NSArray alloc] initWithObjects:#"Item 1", #"Item 2", #"Item 3", nil];
mDDLBH = [[DDLBHelper alloc] initWithWithViewController:self button:ddlbB stringArray:strings currentValue:1];
}
- (IBAction)ddlbBClick:(id)sender {
[mDDLBH popupList];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
[mDDLBH adjustToRotation];
}
Works just like android.
Here are the files:
DDLBHelper.h
// DDLBHelper.h
// Created by MindSpiker on 9/27/12.
#import <Foundation/Foundation.h>
#protocol DDLBHelperDelegate <NSObject>
#required
- (void) itemSelected: (int)value;
#end
#interface DDLBHelper : UIViewController <UITableViewDelegate, UITableViewDataSource>{
id <DDLBHelperDelegate> delegate;
}
#property (retain) id delegate;
// external interface
- (id) init;
- (id) initWithWithViewController:(UIViewController *)viewController button:(UIButton *)button stringArray:(NSArray *)values currentValue:(int) currentValue;
- (void) popupList;
- (BOOL) isShown;
- (void) adjustToRotation;
- (int) getValue;
- (NSString *)getValueText;
#end
DDLBHelper.m
// DDLBHelper.m
// Created by MindSpiker on 9/27/12.
#import "DDLBHelper.h"
#import <QuartzCore/QuartzCore.h>
#interface DDLBHelper () {
#private
UIViewController *mVC;
UIButton *mButton;
NSArray *mValues;
int mValue;
UITableView *mTV;
UIView *mBackgroundV;
}
#end
#implementation DDLBHelper
#synthesize delegate;
- (id) init {
self = [super init];
mVC = nil;
mButton = nil;
mValues = nil;
mValue = -1;
return self;
}
- (id) initWithWithViewController:(UIViewController *)viewController button:(UIButton *)button stringArray:(NSArray *)values currentValue:(int) currentValue {
self = [super init];
// save pointers
mVC = viewController;
mButton = button;
mValues = values;
mValue = currentValue;
[self setupButton];
return self;
}
- (void) popupList{
if (mBackgroundV == nil){
mBackgroundV = [self setupBackgroundView];
[mVC.view addSubview:mBackgroundV];
}
if (mTV == nil){
mTV = [self setupTableView];
[mVC.view addSubview:mTV];
}
[mTV reloadData];
[mBackgroundV setHidden:NO];
[mTV setHidden:NO];
}
- (BOOL) isShown{
return !mTV.isHidden;
}
- (void) adjustToRotation{
BOOL isShown = [self isShown];
// remove the controls
if (mBackgroundV != nil){
[mBackgroundV removeFromSuperview];
mBackgroundV = nil;
}
if (mTV != nil){
[mTV removeFromSuperview];
mTV = nil;
}
if (isShown){
[self popupList];
}
}
- (int) getValue{
return mValue;
}
- (NSString *) getValueText{
if (mValues != nil && mValue > -1) {
if (mValues.count > mValue){
return [mValues objectAtIndex:mValue];
}
}
return nil;
}
- (void) updateButtonTitle{
NSString *title = [NSString stringWithFormat:#" %#", [self getValueText]];
[mButton setTitle:title forState:UIControlStateNormal];
}
- (void) setupButton {
UIImage *buttonBG = [UIImage imageNamed:#"sis_proceeds_ddlb.png"];
UIEdgeInsets insets = UIEdgeInsetsMake(8, 8, 8, 45);
UIImage *sizableImg = [buttonBG resizableImageWithCapInsets:insets];
[mButton setBackgroundImage:sizableImg forState:UIControlStateNormal];
[mButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[self updateButtonTitle];
}
- (UIView *) setupBackgroundView{
UIView *v = [[UIView alloc] initWithFrame:mVC.view.bounds];
[[v layer] setOpaque:NO];
[[v layer] setOpacity:0.7f];
[[v layer] setBackgroundColor:[UIColor blackColor].CGColor];
return v;
}
- (UITableView *) setupTableView {
CGRect rect = [self makeTableViewRect];
UITableView *tv = [[UITableView alloc] initWithFrame:rect style:UITableViewStylePlain];
[tv setDelegate:self];
[tv setDataSource:self];
[tv setBackgroundColor:[UIColor whiteColor]];
[[tv layer] setBorderWidth:2];
[[tv layer] setBorderColor:[UIColor lightGrayColor].CGColor];
[[tv layer] setCornerRadius:10];
[mVC.view addSubview:tv];
return tv;
}
- (CGRect) makeTableViewRect {
float l=0.0, t=0.0, w=0.0, h=0.0, maxH=0.0, cellH=0.0, cellsH=0.0;
// get
l = mButton.frame.origin.x;
w = mButton.frame.size.width;
t = mVC.view.bounds.origin.y + 50;
maxH = mVC.view.bounds.size.height - 100;
// get cell height
UITableViewCell *c = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
cellH = c.bounds.size.height;
// see if list will overlow maxH(eight)
cellsH = cellH * mValues.count;
if (cellsH > maxH) {
h = maxH;
} else {
h = cellsH;
}
return CGRectMake(l, t, w, h);
}
#pragma mark - TableView Delegate functions
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1; // this is a one section table
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return mValues.count; // should be called for only one section
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// try to resuse a cell if possible
static NSString *RESUSE_IDENTIFIER = #"myResuseIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RESUSE_IDENTIFIER];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:RESUSE_IDENTIFIER];
}
cell.textLabel.text = [mValues objectAtIndex:indexPath.row];
if (mValue == indexPath.row){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
// save value and hide view
mValue = indexPath.row;
[self updateButtonTitle];
[mBackgroundV setHidden:YES];
[mTV setHidden:YES];
[delegate itemSelected:mValue];
}
#end