reloadData wont call cellForRowAtIndexPath - iphone

I got myself in a problem that I cant find a solution to, so if someone can help me I would appreciate it. I've read a lot of posts on what could be the problem but I did not found any solution.
I have a .h
#interface FirstViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>{
UITableView *myTableView;
}
#property (strong, nonatomic) UITableView *myTableView;
#end
and a .m
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize myTableView;
static NSString *CellIdentifier = #"CellIdentifier";
- (void)viewDidLoad
{
[super viewDidLoad];
myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStylePlain];
myTableView.dataSource = self;
myTableView.delegate = self;
[self.view addSubview:myTableView];
myTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
myTableView.rowHeight = 325;
myTableView.backgroundColor = [UIColor yellowColor];
[myTableView setDelegate:self];
[myTableView setDataSource:self];
[myTableView registerClass:[MTTableViewCell class] forCellReuseIdentifier:CellIdentifier];
[self separateByType];
}
-(void)separateByType
{
NSURL *url = [NSURL URLWithString:tempUrl];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSString *response = [request responseString];
SBJsonParser *jsonReader = [SBJsonParser new];
firstJsonData = [NSMutableDictionary dictionary];
firstJsonData = [jsonReader objectWithString:response error:nil];
NSLog(#"Calling reloadData on %#", self.myTableView);
[self.myTableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[firstJsonData objectForKey:#"data"] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MTTableViewCell *cell = (MTTableViewCell *)[myTableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[MTTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[cell.titleTextlabel setText:[JSONDATA objectAtIndex:[indexPath row]]];
[cell.descriptionTextlabel setText:[JSONDATA objectAtIndex:[indexPath row]]];
return cell;
}

First Of All , Your code should run well.
Be Sure that numberOfRowsInSection function should return valid number.
Be Sure that "myTableView" is not nil.
Be sure that "myTableView" is seen as background yellow?

Don't declare ivar UITableView *myTableView
Don't #synthesize myTableView
Always access myTableView via the property accessor self.myTableView

-(void)viewWillAppear:(BOOL)animated{
[self performSelector:#selector(reloadTable) withObject:nil afterDelay:0.2];
[self.tableView reloadData]; not working
}
- (void)reloadTable {
[self.tableView reloadData];
}
above code works for me reload table in selector method.

Related

How to keep the checkmark in a UITableView after the view disappears

I have a uitableview that's displaying multiple selections with a custom checkmark. When selected the rows value is save using NSUserDefaults. The problem is that despite the values being saved the checkmarks disappear from the table cell rows. I can't figure out why.
thanks for any help, I'm really stuck on this.
Here's the .h code:
#interface CategoriesViewController : UITableViewController {
NSString *selectedCategoryTableString;
NSString *jsonStringCategory;
int prev;
}
// arForTable array will hold the JSON results from the api
#property (nonatomic, retain) NSArray *arForTable;
#property (nonatomic, retain) NSMutableArray *arForIPs;
#property (nonatomic, retain) NSMutableArray *categorySelected;
#property (nonatomic, retain) NSString *jsonStringCategory;
#property(nonatomic, retain) UIView *accessoryView;
#end
and the .m code:
#implementation CategoriesViewController
#synthesize jsonStringCategory;
#synthesize arForTable = _arForTable;
#synthesize arForIPs = _arForIPs;
- (void)viewDidLoad
{
[super viewDidLoad];
self.arForIPs=[NSMutableArray array];
self.categorySelected = [[NSMutableArray alloc] init];
[self reloadMain];
self.tableView.allowsMultipleSelection = YES;
}
-(void) reloadMain {
jsonString = #"http:///******";
// Download the JSON
NSString *jsonString = [NSString
stringWithContentsOfURL:[NSURL URLWithString:jsonString]
encoding:NSStringEncodingConversionAllowLossy|NSUTF8StringEncoding
error:nil];
NSMutableArray *itemsTMP = [[NSMutableArray alloc] init];
// Create parser
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *results = [parser objectWithString:jsonString error:nil];
itemsTMP = [results objectForKey:#"results"];
self.arForTable = [itemsTMP copy];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.arForTable 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 setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
[cell.detailTextLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
cell.accessoryView.hidden = NO;
}
UIImageView *cellAccessoryImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon-tick.png"]] ;
UIImageView *cellAccessoryNoneImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#""]] ;
if([self.arForIPs containsObject:indexPath]){
cell.accessoryView = cellAccessoryImageView;
} else {
cell.accessoryView = cellAccessoryNoneImageView;
}
// Get item from tableData
NSDictionary *item = (NSDictionary *)[_arForTable objectAtIndex:indexPath.row];
// encoding fix
NSString *utf8StringTitle = [item objectForKey:#"name"];
NSString *correctStringTitle = [NSString stringWithCString:[utf8StringTitle cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding];
cell.textLabel.text = [correctStringTitle capitalizedString];
NSNumber *num = [item objectForKey:#"id"];
cell.detailTextLabel.text = [num stringValue];
cell.detailTextLabel.hidden = YES;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if([self.arForIPs containsObject:indexPath]){
[self.arForIPs removeObject:indexPath];
[self.categorySelected removeObject:[[self.arForTable objectAtIndex:indexPath.row] objectForKey:#"id"]];
} else {
[self.arForIPs addObject:indexPath];
[self.categorySelected addObject:[[self.arForTable objectAtIndex:indexPath.row] objectForKey:#"id"]];
NSLog(#"%# categorySelected",self.categorySelected);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"%# defaults categorySelected",[defaults arrayForKey:#"selectedCategoryTableString"]);
NSString *string = [self.categorySelected componentsJoinedByString:#","];
[defaults setObject:string forKey:#"selectedCategoryTableString"];
NSLog(#"%# STRING",string);
}
[tableView reloadData];
}
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:NO];
[self.navigationController setNavigationBarHidden:YES animated:NO];
self.navigationController.toolbarHidden = YES;
}
First of all your code has lots of memory leaks, please do use the static analyzer and/or instruments to fix them, few for them are pretty obvious like you initialized the SBJSON parser and did not release it, itemsTMP is another.
I have rewritten your code to be much more efficient and memory friendly:
#interface CategoriesViewController : UITableViewController
{
NSArray *_items;
NSMutableArray *_selectedItems;
UIImageView *cellAccessoryImageView;
}
#end
#implementation CategoriesViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_selectedItems = [NSMutableArray new];
cellAccessoryImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon-tick.png"]] ;
[self reloadMain];
self.tableView.allowsMultipleSelection = YES;
}
- (void)reloadMain
{
NSString *jsonString = #"http:///******";
// Download the JSON
jsonString = [NSString
stringWithContentsOfURL:[NSURL URLWithString:jsonString]
encoding:NSStringEncodingConversionAllowLossy|NSUTF8StringEncoding
error:nil];
// Create parser
SBJSON *parser = [SBJSON new];
NSDictionary *results = [parser objectWithString:jsonString error:nil];
if (_items) [_items release];
_items = [[results objectForKey:#"results"] copy];
[parser release];
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)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] autorelease];
[cell.textLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
[cell.detailTextLabel setFont:[UIFont fontWithName: #"Asap-Bold" size: 14.0f]];
cell.accessoryView.hidden = NO;
}
NSDictionary *item = [_items objectAtIndex:indexPath.row];
if ([_selectedItems containsObject:item])
{
// preloaded image will help you have smoother scrolling
cell.accessoryView = cellAccessoryImageView;
}
else
{
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Get item from tableData
cell.textLabel.text = [[NSString stringWithCString:[[item objectForKey:#"name"] cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding] capitalizedString];
cell.detailTextLabel.text = [[item objectForKey:#"id"] stringValue];
cell.detailTextLabel.hidden = YES;
item = nil;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *item = [_items objectAtIndex:indexPath.row];
if ([_selectedItems containsObject:item])
{
[_selectedItems removeObject:item];
}
else
{
[_selectedItems addObject:item];
}
item = nil;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (void)dealloc
{
[_selectedItems release];
[cellAccessoryImageView release];
[super dealloc];
}
#end
Since in your table there is only one section. Try this approach and this will help you certainly.
In - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath write following code;
if([self.arForIPs containsObject:[NSNumber numberWithInt:indexPath.row]]){
cell.accessoryView = cellAccessoryImageView;
} else {
cell.accessoryView = cellAccessoryNoneImageView;
}
And in - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath write code as below,
if([self.arForIPs containsObject:[NSNumber numberWithInt:indexPath.row]]){
[self.arForIPs removeObject:[NSNumber numberWithInt:indexPath.row]];
} else {
[self.arForIPs addObject:[NSNumber numberWithInt:indexPath.row]]
}

UITableView - methods are not being called

I have a subview in which I build a UITableview, I've set the delegate and datasource to the subview but for some reason the table methods are not being called...can someone look over my code and see what I am doing wrong? Thanks
.h file
#interface TwitterController : UIView <UITableViewDelegate, UITableViewDataSource> {
UIButton* btnCloseView;
UITableView* tblTweets;
UIImageView* imgTwitterIcon;
ColorController* colorManager;
NSMutableArray* tweetsArray;
NSMutableArray* tableData;
NSString* twitterID;
}
#property (nonatomic, retain) NSString* twitterID;
- (NSMutableArray* ) getTweets;
- (void) sendNotification : (id) sender;
#end
.m file
#import "TwitterController.h"
#implementation TwitterController
#synthesize twitterID;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
colorManager = [ColorController new];
}
return self;
}
/*- (void)drawRect:(CGRect)rect {
}*/
- (void)layoutSubviews {
imgTwitterIcon = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"imgTwitterBird"]];
CGRect twitterIconFrame = [imgTwitterIcon frame];
twitterIconFrame.origin.x = 50.0;
twitterIconFrame.origin.y = 20.0;
tblTweets = [[UITableView alloc] initWithFrame:CGRectMake(50.0, 25.0, 220.0, 500.0)];
tblTweets.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tblTweets.separatorColor = [colorManager setColor:176.0:196.0:222.0];
tblTweets.layer.borderWidth = 1.0;
tblTweets.rowHeight = 20.0;
tblTweets.scrollEnabled = YES;
tblTweets.delegate = self;
tblTweets.dataSource = self;
tableData = [self getTweets];
UIImage* imgCloseButton = [UIImage imageNamed:#"btnCloseWindow.png"];
CGSize imageSize = imgCloseButton.size;
btnCloseView = [[UIButton alloc] initWithFrame: CGRectMake(220.0, 550.0, imageSize.width, imageSize.height)];
[btnCloseView setImage:[UIImage imageNamed:#"btnCloseWindow.png"] forState:UIControlStateNormal];
[btnCloseView addTarget:self action:#selector(sendNotification:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:tblTweets];
[self addSubview:imgTwitterIcon];
[self addSubview:btnCloseView];
}
- (NSMutableArray*) getTweets {
//array to hold tweets
tweetsArray = [[NSMutableArray alloc] init];
twitterID = #"Pruit_Igoe";
///set up a NSURL to the twitter API
NSURL* twitterAPI = [NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/statuses/user_timeline.json?include_entities=true&include_rts=true&screen_name=%#&count=10", twitterID]];
//get last 10 tweets (max is 20)
TWRequest *twitterRequest = [[TWRequest alloc] initWithURL:twitterAPI
parameters:nil requestMethod:TWRequestMethodGET];
// Notice this is a block, it is the handler to process the response
[twitterRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
// The response from Twitter is in JSON format
// Move the response into a dictionary and print
NSError *error;
NSDictionary *tweetsDict = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&error];
for(NSDictionary* thisTweetDict in tweetsDict) {
[tweetsArray addObject:[thisTweetDict objectForKey:#"text"]];
}
}
else
NSLog(#"Twitter error, HTTP response: %i", [urlResponse statusCode]);
}];
return tweetsArray;
}
#pragma mark Table Management
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tableData count];
NSLog(#"%i", [tableData count]); //does not log!
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.textColor = [UIColor colorWithRed:66.0/255.0 green:66.0/255.0 blue:66.0/255.0 alpha:1];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size: 13.0];
cell.textLabel.text = [tweetsArray objectAtIndex:indexPath.row];
CGRect cellFrame = [cell frame];
cellFrame.size.height = 25.0;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* thisTweet = [tableData objectAtIndex:indexPath.row];
}
#pragma mark Close Window
- (void) sendNotification : (id) sender {
NSMutableDictionary* userData = [[NSMutableDictionary alloc] init];
[userData setObject:#"closeTwitter" forKey:#"theEvent"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"theMessenger" object:self userInfo: userData];
}
#end
I think you are not allocate and initialize tableData. Write it tableData = [[NSMutableArray alloc] init]; in - (id)initWithFrame:(CGRect)frame method or - (void)layoutSubviews method. Just try it.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"%i", [tableData count]);
return [tableData count];
//NSLog(#"%i", [tableData count]); //does not log!
}
If the output is zero, tableData array is empty. Check it tableData array
You should do all the initialization (tblTweets for example) in initWithFrame:.
layoutSubviews is ment for laying out subviews.
In fact your code will (should) work if you move all the code fromLayoutSubviews to initWithFrame:. You can then move parts of the code (the laying out part) back.
EDIT: when you move initializing code you will probably also have to add [tblTweets reloadData]; right after tableData = [self getTweets];

UITableView and Async loading with NSURLconnection

I'm having an issue which to me looks like my JSON URL request is completing after I load my UITableView. I attempted to reload the UITableview but that either isn't working properly or didn't do the trick as some of the other questions suggested. This viewcontroller is being coming off an AppDelegate. Would appreciate a steer if anyone sees something I'm not doing right.
#import "AppDelegate.h"
#import "ViewController.h"
#import "DetailViewController.h"
#import "JSON.h"
#implementation ViewController
#synthesize states,responseData,datasource,appDelegate,_tableView;
#synthesize allTeams;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[self setupArray];
[super viewDidLoad];
// inside all teams
NSLog(#"in VIEW allTeams count, %u",[allTeams count]);
// Do any additional setup after loading the view, typically from a nib.
}
-(void)setupArray{
responseData = [NSMutableData data];
NSLog(#"Want to get teams for via the url");
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://skyrink.secretagents.us/service/"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//#warning Incomplete method implementation.
// Return the number of rows in the section.
NSLog(#"datasource number of rows in section count, %u",[datasource count]);
NSLog(#"allTeams number of rows in section count, %u",[allTeams count]);
return [allTeams count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
//---------- CELL BACKGROUND IMAGE -----------------------------
UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.frame];
UIImage *image = [UIImage imageNamed:#"LightGrey.png"];
imageView.image = image;
cell.backgroundView = imageView;
[[cell textLabel] setBackgroundColor:[UIColor clearColor]];
[[cell detailTextLabel] setBackgroundColor:[UIColor clearColor]];
//cell.textLabel.text = [datasource objectAtIndex:indexPath.row];
//Arrow
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"inside detail view");
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"detail"];
detail.state = [allTeams objectAtIndex:indexPath.row];
detail.capital = [states objectForKey:detail.state];
[self.navigationController pushViewController:detail animated:YES];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSMutableArray *allTeams = [(NSDictionary *)[responseString JSONValue] objectForKey:#"TeamList"];
NSLog(#"allTeams count, %u",[allTeams count]);
NSLog(#"Start reload");
//[self._tableView reloadData];
NSLog(#"Stop reload");
}
#end
You're missing some delegate methods. ResponseData is equal to nil. You haven't handled the response data at all. Check out Apple's docs. https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
You're missing the didReceiveData and didReceiveResponse delegate methods. See here:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html

UITableView does not show new entries when data object conforms to NSCoding

When I make an object class conform to NSCoding, the tableView does not show new entries. Suspected it had to do with the object initialization but cannot solve it. Might be very basic but cannot find the error. Here is the code I simplified to post:
Custom Object:
// DataObject.h
#import <Foundation/Foundation.h>
#interface DataObject : NSObject {
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
// DataObject.m
#import "DataObject.h"
#implementation DataObject
#synthesize name;
- (void)encodeWithCoder:(NSCoder*)encoder {
[encoder encodeObject:name forKey:#"name"];
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super init];
if (!self) return nil;
name = [[decoder decodeObjectForKey:#"name"] retain];
return self;
}
These is the TableView root controller - Have omitted a few methods:
// RootViewController.h
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController {
NSMutableArray *list;
}
#property (nonatomic, retain) NSMutableArray *list;
- (void)add:(id)sender;
- (NSString *)dataFilePath;
#end
// RootViewController.m
#import "RootViewController.h"
#import "DataObject.h"
#implementation RootViewController
#synthesize list;
- (void)add:(id)sender
{
DataObject *newEntry = [[DataObject alloc] init];
newEntry.name = #"Willy";
[self.list addObject:newEntry];
[self.tableView reloadData];
// Scroll table view to last row
if ([list count] > 1) {
NSUInteger index = list.count - 1;
NSIndexPath *lastRow = [NSIndexPath indexPathForRow:index inSection: 0];
[self.tableView scrollToRowAtIndexPath: lastRow atScrollPosition: UITableViewScrollPositionTop animated: YES];
}
[newEntry release];
}
- (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:#"datafile"];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.title = #"Names";
self.list = [[NSMutableArray alloc] init];
NSMutableArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
self.list = tempArray;
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:app];
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithTitle:#"Add"
style:UIBarButtonItemStylePlain
target:self
action:#selector(add:)];
self.navigationItem.leftBarButtonItem = addButton;
[addButton release];
[self.tableView reloadData];
}
- (void)applicationWillResignActive:(NSNotification *)notification;
{
[NSKeyedArchiver archiveRootObject:self.list toFile:[self dataFilePath]];
}
- (void)viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
[super viewWillAppear:animated];
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [list 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] autorelease];
}
// Configure the cell.
NSUInteger row = [indexPath row];
DataObject *oneName = [self.list objectAtIndex:row];
cell.textLabel.text = oneName.name;
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source.
NSUInteger row = [indexPath row];
[self.list removeObjectAtIndex:row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#end
Oh, man I am so embarrassed...It had nothing to do with NSCoding directly but when I made the data class NSCoding compliant I added in viewDidLoad:
NSMutableArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
self.list = tempArray;
The first line is fine, but the second assigned a new pointer address to self.list and the tempArray was later autoreleased...
As this line was not executed in the "not NSCoding compliant" version it appeared to work then and not when encodeWithCoder and initWithCoder were implemented.
Because of this self.list was nil instead of being initialized and ready when in the add: method I added a new instance. It was created fine, but never added to the array and therefore never showed in the tableView.
This was easily fixed using instead in viewDidLoad:
NSMutableArray *tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self dataFilePath]];
[self.list addObjectsFromArray:tempArray];
Worst part is that I was pulling my hair because of this and was convinced it was because of NSCoding and the initialization of objects...

UINavigationController app crashes when clicking the "back" button

hoping someone can help me.
In the didSelectRowAtIndexPath method, I am loading and pushing detail view controller, when you tap the "back" button in the detail view to go back to the root view, the app will crash. No error logs or anything.
I'm 95% sure it's got something to do with the "rides" object being released too early, but can't figure it out.
Thanks for your help!
#import "RidesViewController.h"
#import "RideDetailViewController.h"
#import "JSON.h"
#implementation RidesViewController
#synthesize rides;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"table-view-background.png"]];
rides = [[NSDictionary alloc] init];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"rides" ofType:#"JSON"];
NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
NSString *responseString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSDictionary *results = [responseString JSONValue];
rides = [results objectForKey:#"rides"];
[rides retain];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [rides 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] autorelease];
cell.textLabel.text = [[rides valueForKey:#"title"] objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
RideDetailViewController *rideDetailViewController = [[RideDetailViewController alloc] initWithNibName:#"RideDetailViewController" bundle:nil];
NSString *aTitle = [[NSString alloc] initWithString:[[rides valueForKey:#"title"] objectAtIndex:indexPath.row]];
NSString *aImagePath = [[NSString alloc] initWithString:[[rides valueForKey:#"imagePath"] objectAtIndex:indexPath.row]];
NSString *aDescription = [[NSString alloc] initWithString:[[rides valueForKey:#"description"] objectAtIndex:indexPath.row]];
NSString *aVideoPath = [[NSString alloc] initWithString:[[rides valueForKey:#"videoPath"] objectAtIndex:indexPath.row]];
[rideDetailViewController initWithTitle:aTitle imagePath:aImagePath description:aDescription videoPath:aVideoPath];
[self.navigationController pushViewController:rideDetailViewController animated:YES];
[rideDetailViewController release];
[aTitle release];
[aImagePath release];
[aDescription release];
[aVideoPath release];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)dealloc {
[super dealloc];
}
#end
Define your NSString's in your header, then place them in cellForRowAtIndexPath:
just Cut whole thing from viewdidload and paste this on viewwillapper method.