UITableView application crashes when scrolling - iphone

Firstly, please forgive my English.
I am learning about iPhone SDK, Obj-C and trying to make UITableView app. But my app crashes when scrolling the table. I've searched but can't solve my problem, so I post my question here and look for your help.
TMTMemberListTableViewController.h
#interface TMTMemberListTableViewController : UITableViewController
{
NSMutableArray *familyMembers;
sqlite3 *database;
}
#property (nonatomic, retain) NSMutableArray *familyMembers;
- (void) configureCell:(TMTFamilyMemberCell *)cell withFamilyMember:(TMTFamily *)member;
#end
TMTMemberListTableViewController.m
#interface TMTMemberListTableViewController (Private)
- (void) loadMemberListFromDatabase;
#end
#implementation TMTMemberListTableViewController
#synthesize familyMembers;
- (void) loadMemberListFromDatabase
{
familyMembers = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"easycook.sqlite"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
const char *sql = "SELECT member_id from family";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSString *memberID = [NSString stringWithUTF8String:(char *) sqlite3_column_text(statement, 0)];
TMTFamily *member = [[TMTFamily alloc] initWithMemberID:memberID database:database];
[familyMembers addObject:member];
[member release];
}
}
sqlite3_finalize(statement);
}
else
{
sqlite3_close(database);
NSAssert1(0, #"Failed to open database with message '%s'.", sqlite3_errmsg(database));
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.clearsSelectionOnViewWillAppear = NO;
self.navigationItem.rightBarButtonItem = self.editButtonItem;
[self loadMemberListFromDatabase];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (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 [familyMembers count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//static NSString *MyIdentifier = #"MyIdentifier";
TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[[TMTFamilyMemberCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
TMTFamily *member = [familyMembers objectAtIndex:indexPath.row];
// Set up the cell
[self configureCell:cell withFamilyMember:member];
[member release];
return cell;
}
- (void) configureCell:(TMTFamilyMemberCell *)cell withFamilyMember:(TMTFamily *)member
{
cell.familyMember = member;
cell.memberNameLabel.text = member.description;
}
- (void)dealloc
{
NSLog(#"Dealloc");
[familyMembers release];
[super dealloc];
}
When scrolling table, my app crashes with EXC_BAD_ACCESS at
[self configureCell:cell withFamilyMember:member];
and
cell.memberNameLabel.text = member.description;

This line is not incrementing retain counter:
TMTFamily *member = [familyMembers objectAtIndex:indexPath.row]
So the following line is your problem
[member release];
You cannot release object if you down't own it. Either retain it like that:
TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] retain];
or
TMTFamily *member = [[familyMembers objectAtIndex:indexPath.row] copy];
or remove mentioned release completelly.

First off, welcome to Stack Overflow and welcome to the world of iOS Development.
There are a bunch of problems with your code and if you have an Apple developer account, I highly suggest you head over to the 2012 WWDC Session Videos and look at the talk about Modern Objective C session. https://developer.apple.com/videos/wwdc/2012/
Looking at the code, your bad access could either be an already released object or an empty cell. To determine the cause, you need to enable NSZombies. To do so, click on your project name in the tool bar as shown here:
In this example, it's called PartialTransparentcy (spelling be damned). When you click that button, click the edit scheme button and you'lll see a list of options. You'll want to click enable Zombie objects. If you don't see it, press the Diagnostics tab.
Then run your code and it'll log the object that is giving your grief. Just remember that zombie objects are very expensive. If you submit an app with them enabled, you'll be automatically rejected.
The first thing I notice when I look at your cell initialization code is this:
TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:nil];
You are sending in a nil identifier which negates that whole entire point of reusing cells. Instead, you are creating a new cell for each row instead of reusing older cells.
So uncomment this line:
static NSString *MyIdentifier = #"MyIdentifier";
and change the dequeue method to read like this:
TMTFamilyMemberCell *cell = (TMTFamilyMemberCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
If you are building your cell in interface builder, you'll need to also give the cell an identifier. This may be the cause of the crash.
Next ... your sqllite code should be encapsulated in another object. There's no reason for the view controller to know about it. Also, you should really investigate core data. It defaults to sqllite backing store. It's also a pretty awesome technology.
And finally, take a look at ARC. Let the compiler handle the grunt work of memory management so that you can focus on the user experience of your application.
Hope that helps and good luck!

Related

Load youtube channel to uitableview

i had search in the whole internet for my question: "How to load youtube channel into an uitableview"
I can't find a good example or tutorial.
Please someone can help me?
Thank you very much!
It looks like youtube already provides an API where you can retrieve your information have a look at this link:
http://apiblog.youtube.com/2009/02/youtube-apis-iphone-cool-mobile-apps.html
Otherwise you should search for youtube projects on github. I already found 2 projects. The first one provides already a preview page and plays the video after you selected one:
YoutubeBrowserDemo
HCYoutubeParser
Of course you would neet to look how to get the specific channels you are looking for but I think this should help you for the beginning.
add your youtube channel ID
class.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *urlForPlaylist=#"http://gdata.youtube.com/feeds/api/playlists/URchannelID";
GDataServiceGoogleYouTube *service = [self youTubeService];
[service fetchFeedWithURL:urlForPlaylist
delegate:self
didFinishSelector:#selector(request:finishedWithFeed:error:)];
}
//youtube
- (GDataServiceGoogleYouTube *)youTubeService {
static GDataServiceGoogleYouTube* _service = nil;
if (!_service) {
_service = [[GDataServiceGoogleYouTube alloc] init];
[_service setUserAgent:#"AppWhirl-UserApp-1.0"];
[_service setServiceShouldFollowNextLinks:NO];
}
// fetch unauthenticated
[_service setUserCredentialsWithUsername:nil
password:nil];
return _service;
}
- (void)request:(GDataServiceTicket *)ticket
finishedWithFeed:(GDataFeedBase *)aFeed
error:(NSError *)error {
self.feed = (GDataFeedYouTubeVideo *)aFeed;
NSLog(#"feed..////%#",_feed);
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return[[self.feed entries] count];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"CellR";
UITableViewCell *cell = nil;
cell = [self.VideoTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
GDataEntryBase *entry = [[self.feed entries] objectAtIndex:indexPath.row];
NSString *title = [[entry title] stringValue];
NSArray *thumbnails = [[(GDataEntryYouTubeVideo *)entry mediaGroup] mediaThumbnails];
NSLog(#"thumbnails:%#",thumbnails);
GDataEntryYouTubeVideo *video = (GDataEntryYouTubeVideo *)entry ;
NSString *videoURL = [[[video links] objectAtIndex: 0] href];
}
/////////////
in class.h
#import "GData.h"
#import "GDataYouTube.h"
#import "GDataServiceGoogleYouTube.h"
#property (nonatomic, retain) GDataFeedYouTubeVideo *feed;

tableview will not update on phone

If this is a repost, I apologize, but I have been scouring the net and cant seem to find anything that works. I have a list of workouts that I display in a tableview that are gathered in plists in the bundle. There is a also a separate tab that I have that allows a user to build their own workouts and save them in the documents folder plist file. Once they are saved, they are added to the table view. In the simulator, everyuhting works fine. But on the actual device, it is not updated unless I close the program for an extended period of time, reload the program from xcode, or turn the phone off. I have tried adding [[self tableview] reload] to "viewDidLoad", "viewWillappear", and "viewDidAppear" and none of them work. Once again, the file is saved, the updating does work in the simulator, and it doesn't update in the phone right away. Any suggestions? Thanks.
Edit: i know it is a long piece of code, but should be straight forward (hopefully lol)
#import "BIDWODList.h"
#import "BIDWODDetails.h"
#define kFileName #"SavedDFWorkouts.plist"
#interface BIDWODList ()
#end
#implementation BIDWODList
#synthesize names;
#synthesize savedNames;
#synthesize keys;
#synthesize details;
#synthesize wodType;
#synthesize benchmarkGirls;
#synthesize theNewGirls;
#synthesize heroes;
#synthesize savedDFGWorkouts;
#synthesize chosenWOD;
#synthesize chosenDetails;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *buildBenchmarkGirls = [[NSMutableArray alloc] init];
NSMutableArray *buildTheNewGirls = [[NSMutableArray alloc] init];
NSMutableArray *buildHeroes = [[NSMutableArray alloc] init];
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"CrossfitWOD" withExtension:#"plist"];
//put the contents of the plist into a NSDictionary, and then into names instance variable
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.names = dictionary;
//take all the keys in the dictionary and make an array out of those key names
self.keys = [self.names allKeys];
for (NSString *nameCheck in keys){
self.details = [names valueForKey:nameCheck];
if ([[self.details valueForKey:#"Type"] isEqualToString:#"The Benchmark Girls"]) {
[buildBenchmarkGirls addObject:nameCheck];
}else if ([[self.details valueForKey:#"Type"] isEqualToString:#"The New Girls"]) {
[buildTheNewGirls addObject:nameCheck];
}else {
[buildHeroes addObject:nameCheck];
}
}
NSString *filePath = [self dataFilePath];
NSMutableDictionary *savedWorkout = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
self.savedNames = savedWorkout;
self.savedDFGWorkouts = [[savedWorkout allKeys] sortedArrayUsingSelector:#selector(compare:)];
self.benchmarkGirls = [buildBenchmarkGirls sortedArrayUsingSelector:#selector(compare:)];
self.theNewGirls = [buildTheNewGirls sortedArrayUsingSelector:#selector(compare:)];
self.heroes = [buildHeroes sortedArrayUsingSelector:#selector(compare:)];
//[[self tableView] reloadData]; //reloads the data in case a DFG workout was saved
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.names = nil;
self.keys = nil;
self.benchmarkGirls = nil;
self.theNewGirls = nil;;
self.heroes = nil;
self.details = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSString *)dataFilePath {
NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFileName];
}
-(void)viewDidAppear:(BOOL)animated{
[[self tableView] reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 4;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if (section == 0) {
return [benchmarkGirls count];
}else if (section == 1){
return [theNewGirls count];
}else if (section == 2){
return [heroes count];
}else{
return [savedDFGWorkouts count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier];
}
if (section == 0) {
cell.textLabel.text = [benchmarkGirls objectAtIndex:row];
}else if (section == 1) {
cell.textLabel.text = [theNewGirls objectAtIndex:row];
}else if (section == 2) {
cell.textLabel.text = [heroes objectAtIndex:row];
}else{
cell.textLabel.text = [savedDFGWorkouts objectAtIndex:row];
}
return cell;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (section == 0) {
return #" The Benchmark Girls";
}else if (section == 1){
return #"The New Girls";
}else if (section ==2){
return #"The Heroes";
}else{
return #"Saved DFG Workouts";
}
}
#pragma mark - Table view delegate
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
BIDWODDetails *destination = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
if (section == 0) {
self.chosenWOD = [self.benchmarkGirls objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else if (section == 1) {
self.chosenWOD = [self.theNewGirls objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else if (section ==2) {
self.chosenWOD = [self.heroes objectAtIndex:row];
self.chosenDetails = [names objectForKey:chosenWOD];
}else {
self.chosenWOD = [self.savedDFGWorkouts objectAtIndex:row];
self.chosenDetails = [savedNames objectForKey:chosenWOD];
}//end if
//self.chosenDetails = [names objectForKey:chosenWOD];
//[destination setValue:chosenWOD forKey:#"chosenWOD"];
//[destination setValue:chosenDetails forKey:#"chosenDetails"];
destination.chosenWOD = self.chosenWOD;
destination.chosenDetails = self.chosenDetails;
}
#end
Different behaviour between the simulator and the device is often related to incorrect case being used in filenames - the simulator isn't case sensitive, and the device is. Check that you have the correct case used everywhere you reference the plist file.
Alternatively, on the simulator you are able to write directly to the application bundle, but on the device this is not possible and you can only write to certain directories in your application's sandbox, typically the documents directory. You would normally copy a plist to the documents directory on first run, and use that file thereafter.
If I understand right your code you load plist file only in viewDidLoad, but most likely this function called only when you first time load your view. To make it work you should load plist
in viewDidAppear. Something like this:
- (void)viewDidAppear {
NSBundle *bundle = [NSBundle mainBundle];
NSURL *plistURL = [bundle URLForResource:#"CrossfitWOD" withExtension:#"plist"];
//put the contents of the plist into a NSDictionary, and then into names instance variable
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfURL:plistURL];
self.names = dictionary;
//take all the keys in the dictionary and make an array out of those key names
self.keys = [self.names allKeys];
for (NSString *nameCheck in keys){
self.details = [names valueForKey:nameCheck];
if ([[self.details valueForKey:#"Type"] isEqualToString:#"The Benchmark Girls"]) {
[buildBenchmarkGirls addObject:nameCheck];
}else if ([[self.details valueForKey:#"Type"] isEqualToString:#"The New Girls"]) {
[buildTheNewGirls addObject:nameCheck];
}else {
[buildHeroes addObject:nameCheck];
}
}
NSString *filePath = [self dataFilePath];
NSMutableDictionary *savedWorkout = [[NSMutableDictionary alloc]initWithContentsOfFile:filePath];
self.savedNames = savedWorkout;
self.savedDFGWorkouts = [[savedWorkout allKeys] sortedArrayUsingSelector:#selector(compare:)];
[self.tableView reloadData];
}
If it works in the Simulator and does not on the phone, almost for sure the problem is a timing issue. Saving files on a real phone takes much longer than on the simulator.
You should do the following:
when you save a file, log it, and log the return code from the save. If the way you save does not provide a return code, use NSFileManager to verify the file is in fact where it should be and even the size of it. This takes time to do but you should do it.
when your table is asking for the number of this and that, log it, and lot what is returned. You may find that that this comes before the files are saved.
It takes time and effort, but if you start logging all relevant things, you can find it. I just spend 6 hours today tracking down a race condition I had thought could never happen, and it was only after looking at a huge trail of messages that I was able to see the problem.
Almost for sure you will see that either file is not saved, its not where you thought it was, or that the phone timing means some events happen later than they do in the Simulator.

Memory leaks in UITableView with NSMutableArray - How to stop them?

I'm pretty new to objective-c development and I'm to the point I'm beginning to test my application for leaks and patching up anything else I may have done wrong originally. I followed the examples from a book I bought and expanded on those ideas. The Leaks instrument is telling me in my tableView cellForRowAtIndexPath method I have a leak and I'm not sure on how to fix it.
Here is the related .h contents:
#interface NewsListViewController : UITableViewController<UIActionSheetDelegate> {
NSMutableArray *newsList, *account, *playerList;}
And here is the related .m contents:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)ip {
static NSString *CellIdentifier = #"NewsCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier];
[cell autorelease];
}
NSManagedObject *uNews = [newsList objectAtIndex:[ip row]];
NSManagedObjectContext *playerDBContext = [[AppController sharedAppController] managedObjectContext];
NSFetchRequest *playerDBRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *playerDBEntity = [NSEntityDescription entityForName:#"Players"
inManagedObjectContext:playerDBContext];
[playerDBRequest setEntity:playerDBEntity];
NSPredicate *playerDBPredicate = [NSPredicate predicateWithFormat:#"playerID=%#", [uNews valueForKey:#"playerID"]];
[playerDBRequest setPredicate:playerDBPredicate];
NSError *playerDBError;
NSArray *playerDBList = [playerDBContext executeFetchRequest:playerDBRequest error:&playerDBError];
[playerDBRequest release];
playerList = [playerDBList mutableCopy];
NSString *playerInformation;
if (![playerDBList count] == 0) {
NSManagedObject *playerInfo = [playerList objectAtIndex:0];
playerInformation = [NSString stringWithFormat:#"%#, %# (%#-%#)", [playerInfo valueForKey:#"playerLastName"],
[playerInfo valueForKey:#"playerFirstName"],
[playerInfo valueForKey:#"team"],
[playerInfo valueForKey:#"position"]];
} else {
//NSInteger playerID = (NSInteger *)[uNews valueForKey:#"playerID"];
[self addPlayer:(NSInteger *)[uNews valueForKey:#"playerID"]];
NSLog(#"%#", [uNews valueForKey:#"playerID"]);
playerInformation = [uNews valueForKey:#"playerInfo"];
}
cell.textLabel.text = playerInformation;
cell.detailTextLabel.text = [uNews valueForKey:#"news"];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;}
It's throwing the error on the playerList = [playerDBList mutableCopy]; line - Help with how to fix and an explanation would be greatly appreciated. It's probably from reallocating without releasing but when I've tried using [playerList release]; at the end of the cellForRowAtIndexPath my app crashes.
Properties would make this 'just work'.
.h:
...
#property (nonatomic, retain) NSMutableArray *playerList;
...
.m:
#implementation MyClass
#synthesize playerList;
... then in your cellForIndexPath method ...
self.playerList = [[playerDBList mutableCopy] autorelease];
...
- (void)dealloc {
[playerList release];
[super dealloc];
}
A property declared 'retain' will automatically handle memory management when the property is assigned, releasing the old value if it exists before retaining the new one.
The release you tried crashed because the first time through playerlist hasn't ever been assigned and you release a nil. But the second time through it has something and you leak it. Whenever I reuse a retaining pointer like that, I do
if( playerList )
[playerList release];
playerList = [playerDBList mutableCopy];
just to be safe.

iPhone dev, NSDictionary how to retain full Dict?

I have a problem with retaining data in a nested NSDictionary. Or is it something with NSMutableDictionary that will make this work? Take a look, I will try to explain as good as possible.
My .h file looks like:
#interface MyViewController : UIViewController
<UITableViewDataSource, UITableViewDelegate>
{
NSDictionary *fullData;
IBOutlet UITableView *tableView;
}
#property (nonatomic, retain) NSDictionary *fullData;
#property (nonatomic, retain) UITableView *tableView;
#end
I set up my inits in viewDidLoad
- (void)viewDidLoad {
...
fullData = [NSDictionary dictionaryWithContentsOfURL:url];
[fullData retain];
[super viewDidLoad];
}
And this works fine when I try to insert it into UITableViewCells and whatever I need to do, even if I do an NSLog that prints fullData here, all of the data will be displayed.
like so:
2010-11-24 14:49:53.334 MyApp[25543:40b] {
items = (
{
id = 5;
localId = 1;
name = "A name1";
},
{
id = 8;
localId = 3;
name = "A name2";
},
{
id = 9;
localId = 4;
name = "A name3";
},
{
id = 10;
localId = 5;
name = "A name4";
},
{
id = 11;
localId = 6;
name = "A name5";
}
);
results = 5;
}
Although this works perfectly I want to keep the fullData in my other events, for example didSelectRowAtIndexPath. First of all, I have to retain the , and also if I do, only the first level data will be retained. the dict items will just point to some memory which doesn't exist.
So I try:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Data: %#", fullData);
}
And this sometimes returns this:
2010-11-24 14:44:28.288 MyApp[25493:40b] Data: {
items = (
"<_NSIndexPathUniqueTreeNode: 0x9d2a820>",
"<CALayer: 0x9d27980>",
"<CALayer: 0x9d2bc30>",
"<CALayer: 0x9d29830>",
"<CALayer: 0x9d299e0>"
);
results = 5;
}
It seems like some values are retained, however the data inside items are not possible to access. Is it better for me to store the data to a local file and then access it again at this point, or should be it possible to retain the full dictionary?
I tried adding [[fullData objectForKey:#"items"] retain];
I am pretty new to this, so I need help to make my code follow best practices as well. I have tried many solutions and watched several movies from apple and other places too. I just can't solve it. It might be simple but I dont know where to look.
Thank you.
I am sorry, I did solve the issue myself
I didn't include this function:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Retain count: %i", [fullData retainCount]);
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"cell"];
// create a cell
if( cell == nil )
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
}
// fill it with content
NSArray *current = [[fullData objectForKey:#"items"] objectAtIndex:indexPath.row];
NSString *rowLabel = [NSString stringWithFormat:#"%#, %#",[current valueForKey:#"localId"], [current valueForKey:#"name"]];
cell.textLabel.text = rowLabel;
[current release];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// return it
return cell;
}
And the issue is that I release the current variable each row in the table. This should be a result of that the instance in the variable current is not a copy, instead it is the real reference.
Thanks anyways.
fullData = [NSDictionary dictionaryWithContentsOfURL:url];
is auto-released. you shouldn't retain it. Use this:
self.fullData = [[NSDictionary alloc] initWithContentsOfURL:url];
And I don't think you need to retain it for your purposes now. Only if you need to access it after MyViewController is released.
Are you releasing the UITableView? It may go through and release it's cells which are in your NSDictionary. W/o more code, I can't tell.
You'll need to post some more code in order to track down the solution. The NSDictionary retains its contents, so unless you are over-releasing the objects somewhere else, retaining the NSDictionary will be sufficient.
I am sorry, I did solve the issue myself
I didn't include this function:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Retain count: %i", [fullData retainCount]);
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:#"cell"];
// create a cell
if( cell == nil )
{
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
}
// fill it with content
NSArray *current = [[fullData objectForKey:#"items"] objectAtIndex:indexPath.row];
NSString *rowLabel = [NSString stringWithFormat:#"%#, %#",[current valueForKey:#"localId"], [current valueForKey:#"name"]];
cell.textLabel.text = rowLabel;
[current release];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// return it
return cell;
}
And the issue is that I release the current variable each row in the table. This should be a result of that the instance in the variable current is not a copy, instead it is the real reference.
Thanks anyways.

How to reset array in multiview iphone app

I am trying to have a tableview that leads to another tableview whose list items depend on the first view. I have the database set up properly and my problem is that when I select one item on the first page and go to the second view for the first time it works fine but when I return to the first page and go back to the second view again the list still has the old values loaded with new ones. Is there a way to destroy the array and recreate it every time the second view is loaded? Where would I do this?
Here is where my array is initialized in the delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self copyDatabaseIfNeeded];
organArray = [[NSMutableArray alloc] init];
procedureArray = [[NSMutableArray alloc] init];
[Organ getInitialDataToDisplay:[self getDBPath]];
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
return YES;
}
Here is where the data is added to the array in my custom class:
+ (void) getDatabase:(NSString *)dbPath WithOrganID:(NSNumber *)organID
{
RadiologyAppAppDelegate *appDelegate = (RadiologyAppAppDelegate *)[[UIApplication sharedApplication] delegate];
if(sqlite3_open([dbPath UTF8String],&database) == SQLITE_OK){
const char *sql = "select * from Organ";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK){
while (sqlite3_step(selectstmt) == SQLITE_ROW) {
NSInteger primaryKey = sqlite3_column_int(selectstmt, 0);
Procedure *procedureObj = [[Procedure alloc] initWithPrimaryKey:primaryKey];
procedureObj.procedureName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt,1)];
procedureObj.procedureID = sqlite3_column_int(selectstmt,0);
[appDelegate.procedureArray addObject: procedureObj];
[procedureObj release];
}
}
}
else
sqlite3_close(database);
}
Finally, here is my view controller:
- (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];
}
Procedure *procedureObj = [appDelegate.procedureArray objectAtIndex:indexPath.row];
PVCprocedureObj = appDelegate.procedureArray;
cell.textLabel.text = procedureObj.procedureName;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
Thanks for the help!
I would pass the data-object (data to be shown in the second table) to the 2nd controller. I think this is the easiest approach and you are not showing that part.
Pass the object when clicking the cell, inside: – tableView:didSelectRowAtIndexPath: and not when making the cell: -tableView:cellForRowAtIndexPath:
Hope this helps