I have textview in VC. Saving this textview using nsuserdefaults and get it later. In VC1 im getting saved textview and displaying in UITableView. But when i launch the app it automcatically displays "null" text in index 0.
VC:
-(void)save:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:textView.text forKey:#"savetext"];
[userData1 synchronize];
}
VC1:
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
textArray=[[NSMutableArray alloc]init];
txt=[[UITextView alloc]initWithFrame:CGRectMake(0, 0, 320, 400)];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *savedValue = [prefs stringForKey:#"savetext"];
txt.text = [NSString stringWithFormat:#"%#", savedValue];
MyAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
// [MyAppDelegate.textArray addObject:txt.text];
if(![MyAppDelegate.textArray containsObject:txt.text]){
[MyAppDelegate.textArray addObject:txt.text];
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:MyAppDelegate.textArray forKey:#"save"];
[userData1 synchronize];
}
[self.view addSubview:txt];
tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 568) style:UITableViewStylePlain];
NSLog(#"Scrolling");
tableView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleRightMargin;
// tableView.contentInset = UIEdgeInsetsMake(0, 0,300, 0); //values passed are - top, left, bottom, right
tableView.delegate = self;
tableView.dataSource = self;
[tableView reloadData];
tableView.contentInset = UIEdgeInsetsMake(0, 0,300, 0);
//self.view = tableView;
[self.view addSubview:tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"count is %#",myMutableArrayAgain);
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier ];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
NSLog(#"cell is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
I had this problem too. NSUserDefaults can't process with mutable objects.
Try to store your string into CoreData. Is it simple and powerful. I make it and it works perfect.
If you have not skills with CoreData here is tutorial:
http://www.youtube.com/watch?v=StMBHzA7h18
Step1 create new file - Data model
Step2 create Entity (name) there add one atribute (name2)
So simple!
Related
I have textview in VC. Saving this textview using nsuserdefaults and get it later. In VC1 im getting saved textview and displaying in UITableView. But when i launch the app it automcatically displays "null" text in index 0.
VC:
-(void)save:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:textView.text forKey:#"savetext"];
[userData1 synchronize];
}
VC1:
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
// textArray=[[NSMutableArray alloc]init];
txt=[[UITextView alloc]initWithFrame:CGRectMake(0, 0, 320, 400)];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *savedValue = [prefs stringForKey:#"savetext"];
NSLog(#"saved is %#",savedValue);
txt.text = [NSString stringWithFormat:#"%#", savedValue];
NSLog(#"text.txt is %#", txt.text);
MyAppDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if(![MyAppDelegate.textArray containsObject:txt.text]){
[MyAppDelegate.textArray addObject:txt.text];
}
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:MyAppDelegate.textArray forKey:#"save"];
[userData1 synchronize];
}
UITableView displays the text values using array:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"array is %#",myMutableArrayAgain);
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"save"]];
NSLog(#"mycell is %#",myMutableArrayAgain);
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
NSLog(#"cell inside is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
This is all because the code is wrong at some places:
1) Nsmutable array with array is wrong:- as the userdefaults is returning you a single string.
So do it like this:-
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
NSMutableArray* myMutableArrayAgain = [NSMutableArray arrayWithObject:[userData1 valueForKey:#"savetext"]];
2) In VC you are saving the value for key in "savetext" but in VC1 you are retrieving the value as "save", so change it, it has been done in the above code.
// The above 2 points would solve your problem but I would say don't code like this as it would consume more memory and would remove tidyness of your code. The code which you have done can be done in a very efficient way.
I tell you .
// Take first View controller VC and add IBAction to a button and a textView or textField what ever.
Write this code in VC :-
.h file
#interface demoViewController : UIViewController{
IBOutlet UITextField *txt1;
}
-(IBAction)getData:(id)sender;
.m file
// first include header file of the next controller where you want to redirect suppose XYZ
#import XYZ.h
-(IBAction)getData:(id)sender{
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
[userData1 setObject:txt1.text forKey:#"savetext"];
demoViewController1 *demo=[[demoViewController1 alloc]initWithNibName:#"demoViewController1" bundle:nil];
[self.navigationController pushViewController:demo animated:NO];
}
// Take the second controller IN taht on ViewDisLoad or ViewDidAppear whatever you feel like
// Take a global MuttableArray
NSMutableArray *myMutableArrayAgain;
// I write this code on ViewDidload allocate the array here as MutableObject need to be allocated
NSUserDefaults *userData1 = [NSUserDefaults standardUserDefaults];
myMutableArrayAgain=[[NSMutableArray alloc]init];
[myMutableArrayAgain addObject: [userData1 valueForKey:#"savetext"]];
// Now table View Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [myMutableArrayAgain count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSLog(#"cell is %#",cell);
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
NSLog(#"cell inside is %#",cell);
}
// Configure the cell...
cell.textLabel.text = [myMutableArrayAgain objectAtIndex:indexPath.row];
[cell.textLabel setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
// Apply this way you can do the stuff in less code and in a great way.
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]]
}
This is my first time asking a question & posting code so I hope I have included everything that is necessary.
In several of my other apps I have been able to successfully reloadData in a UITableView but for some reason I cannot get it to work here.
I am using a navigationController and drilling down a few levels in the UITableView until a new class loads which right now just has two buttons that switch between 2 similar plist files so I can tell that the tableView is actually reloading (Data.plist & Data2.plist)
This is eventually going to be a timesheet sort of app where individual jobs are listed and the user (driver) will punch a timeclock with In/Out buttons. For now, what I want is to drill down and click the button that loads the other plist and go back up to reveal that the new plist data has loaded. My problem is that I cannot get the tableView to reload at all. I've tried putting different variations of [self.tableView reloadData] & [myTableView reloadData] (which I have also connected via IB) all over the place but none of them work. I'm currently calling a method in the rootViewController (where the tableView is) from detailViewController (where the buttons are) and that basic process works for me in other apps when there is no navigationController being used. The navigationController seems to be throwing me off here in this app. I hope an easy solution can be found. My code so far looks like this:
AppDelegate.m
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
}
RootViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
//THIS ESTABLISHES WHICH PLIST TO LOAD BASED ON THE BUTTON CLICKED
plistToUse = [[NSUserDefaults standardUserDefaults] objectForKey:#"plistToUse"];
if (plistToUse == #"Data.plist") {
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"Data.plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
self.data = tempDict;
[tempDict release];
} else if (plistToUse == #"Data2.plist") {
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"Data2.plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
self.data = tempDict;
[tempDict release];
} else {
NSString *Path = [[NSBundle mainBundle] bundlePath];
NSString *DataPath = [Path stringByAppendingPathComponent:#"Data.plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:DataPath];
self.data = tempDict;
[tempDict release];
}
if(CurrentLevel == 0) {
NSArray *tempArray = [[NSArray alloc] init];
self.tableDataSource = tempArray;
[tempArray release];
self.tableDataSource = [self.data objectForKey:#"Rows"];
self.navigationItem.title = #"Choose Driver";
} else if (CurrentLevel == 1) {
self.navigationItem.title = #"Choose Day";
} else if (CurrentLevel == 2) {
self.navigationItem.title = #"Choose Job";
} else if (CurrentLevel == 3) {
self.navigationItem.title = #"Job Details";
} else {
self.navigationItem.title = CurrentTitle;
}
}
-(void)update {
dvController.labelHelper.text = #"UPDATED"; //USED TO SEE IF A LABEL IN THE BUTTON CLASS WILL UPDATE
NSArray *tempArray = [[NSArray alloc] init];
self.tableDataSource = tempArray;
[tempArray release];
self.tableDataSource = [self.data objectForKey:#"Rows"];
self.navigationController.navigationItem.title = #"Choose Driver";
self.navigationController.title = #"THE TITLE";
[myTableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
unsortedIndex=1;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.tableDataSource count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
cell.textLabel.text = [dictionary objectForKey:#"Title"];
NSArray *Children = [dictionary objectForKey:#"Children"];
if ([Children count] == 0) {
Titles = [dictionary objectForKey:#"Title"];
in1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"InTime1"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", in1];
}
in1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"InTime1"];
out1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"OutTime1"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#:%#", in1, out1];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
NSArray *Children = [dictionary objectForKey:#"Children"];
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:[NSBundle mainBundle]];
if([Children count] == 0) {
[self.navigationController pushViewController:dvController animated:YES];
dvController.labelSiteName.text = [dictionary objectForKey:#"Company"];
dvController.labelSiteAddress.text = [dictionary objectForKey:#"Address"];
dvController.labelSiteNotes.text = [dictionary objectForKey:#"Notes"];
[dvController.mapView setMapType:MKMapTypeStandard];
[dvController.mapView setZoomEnabled:YES];
[dvController.mapView setScrollEnabled:YES];
dvController.mapView.showsUserLocation = YES;
[dvController release];
}
else {
RootViewController *rvController = [[RootViewController alloc] initWithNibName:#"RootViewController" bundle:[NSBundle mainBundle]];
rvController.CurrentLevel += 1;
rvController.CurrentTitle = [dictionary objectForKey:#"Title"];
[self.navigationController pushViewController:rvController animated:YES];
rvController.tableDataSource = Children;
[rvController release];
}
}
DetailViewController.m
These are the two buttons that should reload the tableView with either Data.plist or Data2.plist
-(IBAction)getInTime1:(id)sender {
plistToUse = #"Data.plist";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:plistToUse forKey:#"plistToUse"];
[defaults synchronize];
[rvController update];
}
-(IBAction)getOutTime1:(id)sender {
plistToUse = #"Data2.plist";
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:plistToUse forKey:#"plistToUse"];
[defaults synchronize];
[rvController update];
}
I appreciate any help you can give.
Add your data fetching from plist code into your viewDidAppear or viewWillAppear methods, so that each time view appears, the data is loaded from plist.
And also note that your arrays are allocated only once.
This will work for you.
I use a custom cell in my app. When a user taps a table row, a custom cell appears:
#import "SonaraamatuKontroller.h"
#import "TolkegaLahter.h"
//Lahtris kasutatava teksti fondi suurus
#define FONT_SIZE 14.0f
//Tabelilahtri laius
#define CELL_CONTENT_WIDTH 320.0f
//Tabeli sisu äärise kaugus lahtri servadest
#define CELL_CONTENT_MARGIN 5.0f
#implementation SonaraamatuKontroller
#synthesize sonaraamatuSisukord=sonaraamatuSisukord;
#synthesize sonaraamatuTabel;
#synthesize valitudLahtriIndexPath;
#synthesize tolkegaLahter;
#synthesize audioPleier;
#synthesize sonaraamatuFailinimi;
#synthesize sonaraamatuNavribaNimi;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *error;
NSPropertyListFormat format;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:sonaraamatuFailinimi ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:localizedPath];
NSArray *sisukordData = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (sisukordData) {
self.sonaraamatuSisukord = [NSMutableArray arrayWithCapacity:[sonaraamatuSisukord count]];
for (NSDictionary *sisukordDictionary in sisukordData) {
[self.sonaraamatuSisukord addObject:sisukordDictionary];
}
}
self.navigationItem.title=sonaraamatuNavribaNimi;
}
- (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)viewDidUnload {
//Teise vaatesse liikumisel pannakse audiopleier seisma
[audioPleier stop];
// Release anything that can be recreated in viewDidLoad or on demand.
// e.g. self.myOutlet = nil;
}
#pragma mark -
#pragma mark UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//Loeme tabeli sektsioonide arvu - kuna praegusel juhul on sisukorras ainult üks liige (sõnaraamat "Item 0"), siis on ka sektsioone üks
return [sonaraamatuSisukord count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//Loeme vastavas sektsioonis asuvate ridade arvu
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:section] objectForKey:#"Items"];
return [sisukordItems count];
}
- (CGFloat) tableView : (UITableView *) tableView
heightForRowAtIndexPath: (NSIndexPath *) indexPath {
if(valitudLahtriIndexPath != nil
&& [valitudLahtriIndexPath isEqual:indexPath] )
return 95;
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
NSString *text = [sisukordItem objectForKey:#"Valjend"];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
CGFloat height = MAX(size.height, 25.0f);
return height + (CELL_CONTENT_MARGIN * 2);
}
#pragma mark -
#pragma mark UITableViewDelegate
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if((valitudLahtriIndexPath != nil)
&& [valitudLahtriIndexPath isEqual:indexPath]
)
{ //NSLog (#"ValitudPath: %#", valitudLahtriIndexPath);
static NSString *TolkegaLahtriTunnus = #"TolkegaLahter";
TolkegaLahter *cell = (TolkegaLahter *)[tableView dequeueReusableCellWithIdentifier:TolkegaLahtriTunnus];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TolkegaLahter" owner:self options:nil];
cell = tolkegaLahter;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
//Lisame gradiendi:
CAGradientLayer *gradient = [CAGradientLayer layer];
[gradient setCornerRadius:9.0f];
//[gradient setMasksToBounds:YES];
//[gradient setBorderWidth:0.8f];
//[gradient setBorderColor:[[UIColor darkGrayColor] CGColor]];
gradient.frame = cell.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:0.122 green:0.2 blue:1 alpha:0.95] CGColor], (id)[[UIColor colorWithRed:0.041 green:0.1 blue:0.33 alpha:0.95] CGColor],(id)[[UIColor colorWithRed:0.122 green:0.2 blue:1 alpha:0.95] CGColor], nil];
gradient.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],[NSNumber numberWithFloat:0.48],[NSNumber numberWithFloat:1.0], nil];
[cell.layer insertSublayer:gradient atIndex:0];
}
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
cell.valjend.text=[sisukordItem objectForKey:#"Valjend"];
cell.tolge.text=[sisukordItem objectForKey:#"Tolge"];
[sonaraamatuTabel scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
self.tolkegaLahter = nil;
return cell;
}
static NSString *CellIdentifier = #"Cell";
//Loome lahtrisse labeli
UILabel *label = nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
//Esialgu on label tühi (asub punktis 0,0 ning on suurusega 0,0)
label = [[UILabel alloc] initWithFrame:CGRectZero];
//Määrame reavahetuse stiili
[label setLineBreakMode:UILineBreakModeWordWrap];
//Minimaalne fondi suurus on ülal defineeritud konstant
[label setMinimumFontSize:FONT_SIZE];
//Esialgu on ridade arv 0
[label setNumberOfLines:0];
//Määrame fondi. Selle suuruseks on ülal defineeritud konstant
[label setFont:[UIFont systemFontOfSize:FONT_SIZE]];
[label setTag:1];
//Lisame labelile piirid, et programmeerimise käigus oleks paremini näha, kuhu see lahtris paigutub
//[[label layer] setBorderWidth:2.0f];
[[cell contentView] addSubview:label];
[label release];
}
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.selectedBackgroundView=[[[UIView alloc] init] autorelease];
cell.selectedBackgroundView.backgroundColor=[UIColor colorWithRed:0.537 green:0.18 blue:0.122 alpha:1.0];
//Loome andmemassiivi sisukord objektidest (tuntakse ära võtme "Items" abil) andmemassiivi sisukordItems
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
//Loome andmemassiivi sisukordItems objektidest sõnaraamatud sisukordItem
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
//Igas lahtris kuvatakse sellele vastavas sõnaraamatus sisalduva objekti "Valjend" väärtus
NSString *text = [sisukordItem objectForKey:#"Valjend"];
//Sarnaselt lahtri kõrguse arvutamisele heightForRowAtIndexPath meetodis arvutame ka labeli
//kõrguse (sellele ei liideta ääriste kaugusi)
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
//Hangime labeli juhul kui see on nil (ja tegu ei ole vaate esialgse initsieerimisega ehk lahter ei ole nil)
if (!label)
label = (UILabel*)[cell viewWithTag:1];
//Seame labeli teksti
[label setText:text];
//Seame labeli piirjooned
[label setFrame:CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 25.0f))];
label.textColor=[UIColor blackColor];
label.font=[UIFont systemFontOfSize:14];
label.backgroundColor=[UIColor clearColor];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.valitudLahtriIndexPath = indexPath;
if(valitudLahtriIndexPath != nil //Kui see väärtus on tõene,
&& [valitudLahtriIndexPath isEqual:indexPath]) {
[self.sonaraamatuTabel reloadData];
NSMutableArray *sisukordItems = [[sonaraamatuSisukord objectAtIndex:indexPath.section] objectForKey:#"Items"];
NSDictionary *sisukordItem = [sisukordItems objectAtIndex:indexPath.row];
NSString*heliFailinimi=[sisukordItem objectForKey:#"HeliFailinimi"];
NSError *setCategoryError = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
NSString *taustaHeliPath = [[NSBundle mainBundle] pathForResource:heliFailinimi ofType:#"m4a"];
[audioPleier stop];
NSURL *taustaHeliURL = [NSURL fileURLWithPath:taustaHeliPath];
NSError *error;
audioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error];
[audioPleier setDelegate:self]; // We need this so we can restart after interruptions
[audioPleier play];
}
}
- (void)viewWillAppear:(BOOL)animated
{
NSIndexPath*selection = [self.sonaraamatuTabel indexPathForSelectedRow];
if (selection)
[self.sonaraamatuTabel deselectRowAtIndexPath:selection animated:YES];
[self.sonaraamatuTabel reloadData];
}
- (void)dealloc {
[valitudLahtriIndexPath release];
[sonaraamatuSisukord release], sonaraamatuSisukord=nil;
[audioPleier release];
[sonaraamatuFailinimi release];
[sonaraamatuNavribaNimi release];
[super dealloc];
}
#end
After 250 taps the app crashes and I get the message:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle (loaded)' with name 'TolkegaLahter''
What could be the reason of this behaviour? A memory leak somewhere?
EDIT
It was about the AVAudioPlayer, which was created again and again, but not released.
So, I replaced
audioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error];
with
AVAudioPlayer*ajutineAudioPleier = [[AVAudioPlayer alloc] initWithContentsOfURL:taustaHeliURL error:&error];
self.audioPleier=ajutineAudioPleier;
[ajutineAudioPleier release];
Is the code in your question the cellForRowAtIndexPath method? It isn't clear from your question whereabouts this code is or when it is executed.
If it is (or, for some of these, even if it isn't) there are a couple of problems with it:
You aren't returning the cell if the dequeue method brings you something back
You aren't configuring the cell if the dequeue method brings you something back
Which leads me to expect that you haven't set the reuse identifier in your custom cell subclass in interface builder
Which means you are creating a new cell each time which could give you a crash if you have a sufficient number of cells
The scrolling call seems odd (this would only be odd if this was your cellForRowAtIndexPath method)
If you are repeatedly loading from nibs you may want to check out UINib as well.
EDIT
After looking at your full code, I think the problem is your audio player, you are creating and configuring a new one every time the cell is selected and this is leaking.
You should just set up the audio player on your viewDidLoad, and just tell it to play the specific sound when you select the cell.
Try to replace
[[NSBundle mainBundle] loadNibNamed:#"TolkegaLahter" owner:self options:nil];
cell = tolkegaLahter;
to
cell = [[[TolkegaLahter alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier: TolkegaLahtriTunnus] autorelease];
self.tolkegaLahter = [[[NSBundle mainBundle] loadNibNamed:#"TolkegaLahter" owner:self options:nil] lastObject];
cell = self.tolkegaLahter;
Hey everbody. Im getting trouble with a simple thing. But i'm missing some detail. I'm trying to set up the styles of the TableView. I've edited the table on visual, but seems do not take effect what i do.
What im doing wrong?
#implementation ComentariosViewController
#synthesize listaComentarios, tabelaComentarios;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [listaComentarios count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
//cell.font = [UIFont boldSystemFontOfSize:13];
}
NSString *cellValue = [listaComentarios objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
- (void)viewDidLoad
{
tabelaComentarios = [[UITableView alloc] initWithFrame:CGRectZero];
tabelaComentarios.delegate = self;
tabelaComentarios.dataSource = self;
//bkg.image = [UIImage imageNamed:#"BkgComentarios.png"];
tabelaComentarios.autoresizesSubviews = YES;
//
// Change the properties of the imageView and tableView (these could be set
// in interface builder instead).
//
tabelaComentarios.separatorStyle = UITableViewCellSeparatorStyleNone;
tabelaComentarios.rowHeight = 100;
tabelaComentarios.backgroundColor = [UIColor clearColor];
//imageView.image = [UIImage imageNamed:#"gradientBackground.png"];
//
// Create a header view. Wrap it in a container to allow us to position
// it better.
//
UIView *containerView =
[[[UIView alloc]
initWithFrame:CGRectMake(0, 0, 300, 60)]
autorelease];
UILabel *headerLabel =
[[[UILabel alloc]
initWithFrame:CGRectMake(10, 20, 300, 40)]
autorelease];
headerLabel.text = NSLocalizedString(#"Comentários", #"");
headerLabel.textColor = [UIColor grayColor];
headerLabel.font = [UIFont boldSystemFontOfSize:22];
headerLabel.backgroundColor = [UIColor clearColor];
[containerView addSubview:headerLabel];
self.tabelaComentarios.tableHeaderView = containerView;
self.view = tabelaComentarios;
}
-(void)loadView{
// XML
listaComentarios = [[NSMutableArray alloc] init];
TBXML * tbxml = [[TBXML tbxmlWithURL:[NSURL URLWithString:#"http://localhost/dev/mcomm/produto.xml"]] retain];
TBXMLElement * rootXMLElement = tbxml.rootXMLElement;
TBXMLElement * comentarios = [TBXML childElementNamed:#"comentarios" parentElement:rootXMLElement];
TBXMLElement * comentario = [TBXML childElementNamed:#"comentario" parentElement:comentarios];
while (comentario) {
NSString * descText = [TBXML textForElement:comentario];
NSLog(#"%#", descText);
[listaComentarios addObject:descText];
comentario = [TBXML nextSiblingNamed:#"comentario" searchFromElement:comentario];
}
[tbxml release];
}
- (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)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[listaComentarios release];
[tabelaComentarios release];
[super dealloc];
}
#end
If you're using Interface builder to add the table, try commenting out this line:
tabelaComentarios = [[UITableView alloc] initWithFrame:CGRectZero];