Delete cell in tableView with Plist - objective-c

I want to delete a cell in one of my 2 tableViews (1 is the main one, 2 the Favorites one).
To delete a cell, i should set a specific value to "NO", in order to be NO in the plist (the Favorite table shows only cells with "isFav" value set to YES).
Check this question for further details: UITableView not showing the right cells
Back to my question, i tried to do
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *plist = [self readPlist];
NSMutableDictionary *theItem = [[[plist objectAtIndex:indexPath.section] valueForKey:#"Rows"] objectAtIndex:indexPath.row];
NSLog(#"%#",theItem);
if (editingStyle == UITableViewCellEditingStyleDelete) {
[theItem setValue:[NSNumber numberWithBool:NO] forKey:#"isFav"];
[self.tableView deleteRowsAtIndexPaths:[[[NSArray arrayWithObject:[plist objectAtIndex:indexPath.section]]valueForKey:#"Rows"]objectAtIndex:indexPath.row] withRowAnimation:UITableViewRowAnimationNone];
[self writePlist:plist];
[self.tableView reloadData];
}
}
- (void)writePlist:(NSArray*)arr
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:#"tipsList.plist"];
NSFileManager *fMgr = [NSFileManager defaultManager];
if ([fMgr fileExistsAtPath:plistPath])
[fMgr removeItemAtPath:plistPath error:nil];
[arr writeToFile:plistPath atomically:YES];
}
- (NSArray*)readPlist
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:#"tipsList.plist"];
NSFileManager *fMgr = [NSFileManager defaultManager];
if (![fMgr fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:#"tipsList" ofType:#"plist"];
}
NSMutableArray *returnArr = [NSMutableArray arrayWithContentsOfFile:plistPath];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"isFav == YES"];
for (NSDictionary *sect in returnArr) {
NSArray *arr = [sect objectForKey:#"Rows"];
[sect setValue:[arr filteredArrayUsingPredicate:predicate] forKey:#"Rows"];
[self.tableView reloadData];
}
return returnArr;
}
but with no success.
What was i trying to do: trying to get to the current item in the table, then set its "isFav" value to NO and then delete the cell from the table, but i'm failing, getting
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary row]: unrecognized selector sent to instance 0x7fd4ab0'
I tried to do [NSArray arrayWithObject:indexPath] but i get
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
Any help appreciated :|

this error occurs because the dataSource count isn't the same like the actual data. When you delete an item the tableView cells will go down eg. from 10 to 9. But you didn't delete the data from your dataSource so you end up with different count and Xcode poke you a little.
As talked (extensively) in chat we got the problem solved with this code:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[tableView beginUpdates];
NSIndexPath *realIndex = [self realIndexPathForIndex:indexPath];
NSArray *plist = [self readFullPlist];
NSMutableDictionary *theItem = [[[plist objectAtIndex:realIndex.section] valueForKey:#"Rows"] objectAtIndex:realIndex.row];
[theItem setValue:[NSNumber numberWithBool:NO] forKey:#"isFav"];
[self writePlist:plist];
[self refreshTable];
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
}
- (NSArray*)readFullPlist
{
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[documentPaths lastObject] stringByAppendingPathComponent:#"tipsList.plist"];
NSFileManager *fMgr = [NSFileManager defaultManager];
if (![fMgr fileExistsAtPath:plistPath]) {
NSString *bundlePlistPath = [[NSBundle mainBundle] pathForResource:#"tipsList" ofType:#"plist"];
[self writePlist:[NSArray arrayWithContentsOfFile:bundlePlistPath]];
}
return [NSArray arrayWithContentsOfFile:plistPath];
}
- (NSIndexPath*)realIndexPathForIndex:(NSIndexPath*)idxPath
{
NSArray *fullList = [self readFullPlist];
NSArray *subArr = [[fullList objectAtIndex:idxPath.section] objectForKey:#"Rows"];
int row = idxPath.row;
int newRow = 0;
for (NSDictionary *dic in subArr)
{
if ([[dic valueForKey:#"isFav"] boolValue]) {
if (row == 0) {
return [NSIndexPath indexPathForRow:newRow inSection:idxPath.section];
}
row--;
}
newRow++;
}
return idxPath;
}

In you tableView: commitEditingStyle: method, look up the statement where you want to delete the rows in the tableView. Here you should hand over an array with NSIndexPaths. This line is very hard to read in your snippet since it contains many nested calls...

Related

update UITableView based on array

I have JSON file who's information I put in my table. I have one button for sorting my array
I can sort my array and print it with NSLog. How can I update my table based on my sorted array?
This is my code:
-(void)sortArry:(UIButton *)sender
{
NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = #[ageDescriptor];
NSArray *sortedArray = [tableData sortedArrayUsingDescriptors:sortDescriptors];
//here i have my data in nslog
NSLog(#"%# sort test",sortedArray);
}
How can I show my sortedArray in the table?
I also used
[self.tableView reloadData];
after sorting but it didn't show the sorted table
Update:
Here is my cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath
*)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *objects = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner:nil options:nil];
for (id currentObject in objects)
{
if([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (CustomCell *) currentObject;
break;
}
}
}
id keyValuePair;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
keyValuePair = [self.filteredTableData objectAtIndex:indexPath.row];
}
else
{
keyValuePair = [self.tableData objectAtIndex:indexPath.row];
}
cell.name.text = keyValuePair[#"name"];
return cell;
}
sortedArray is deleted when it goes out of scope at the end of your sortArry: method. You need to set the property or instance variable that your UITableViewDelegate methods inspect.
Call [tableView reloadData]; after the array is sorted.
sortedArray needs to be a property of your viewController not an instance variable of sortArry , so when you reload all UITableViewdelegate method can access its values and update.
// The array You use to populate the table
#property NSArray ArrayDataSource;
Change the method signature to return the sorted array
-(NSArray *)sortArry
{
NSSortDescriptor *ageDescriptor =
[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = #[ageDescriptor];
NSArray *sortedArray =
[tableData sortedArrayUsingDescriptors:sortDescriptors];
//here i have my data in nslog
NSLog(#"%# sort test",sortedArray);
return sortedArray;
}
Stored the return value in the datasource:
ArrayDataSource = [self.ArrayDataSource];
Finally reload the table
[self.tableView reloadData];

Objective-C: how to add a new cell for each filename in UiTableView?

Bellow i have some code that lists the path to the documents directory where my video files are saved. The code then lists that in a cell but it's the full path and only one cell is used. So what i want to do is first cut down the path and only list the file name of the file in the documents director and then have an individual cell for each file. Is that possible?
Here is the code i am using to list the path to the documents directory:
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if(!filePathsArray) // if data loading has been completed, return the number of rows ELSE return 1
{
if ([filePathsArray count] > 0)
return [filePathsArray count];
else
return 1;
}
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
filePathsArray = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
cell.textLabel.text = [documentsDirectory stringByAppendingPathComponent:[filePathsArray objectAtIndex:indexPath.row]];
return cell;
}
Thanks in advance.
As it is now, you're loading the file paths in viewDidLoad and each time the method tableView:cellForRowAtIndexPath: is called which is inefficient and unnecessary.
In any case, you just want something like:
cell.textLabel.text = [filePathsArray[indexPath.row] lastPathComponent];
if I understand your requirements correctly.
Use this:
NSFileManager *fm [NSFileManager defaultManager];
NSArray *documentsDirectoryContents = [[fm contentsOfDirectoryAtPath:documentDirectory error:nil] mutableCopy];
It works for me, and only returns the filenames of the files within the documents directory (not the full path).
Then use that array as your data source for the table.
So set each cell's text to the corresponding file name.
Furthermore, as NSBum says, you should obtain the filenames ONLY when you want the documents directory's contents to be refreshed - in other words, only when you want to update your table.

Xcode find table view section row on detail text label

I have an index set up with my table and I am able to return the correct arrays for the textLabel.text according to the section header. My problem is I have an a separate array that i need to return in the detailTextLabel.text.
It just repeats in each section starting from the first index from the first section. For example:
A
Apple
apple
Alligator
alligator
B
Ball
apple
Bat
alligator
I've generated index characters and table headers. This is what I have to return the cell.
NSString *alphabet = [arrayIndex objectAtIndex:[indexPath section]];
//---get all of First array's beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *firstArray = [First filteredArrayUsingPredicate:predicate];
NSArray *secondArray = [Second filteredArrayUsingPredicate:predicate];
if ([FirstArray count]>0) {
//---extract the relevant state from the states object---
NSString *cellValue = [firstArray objectAtIndex:indexPath.row];
//<--This line throws and error assuming it is trying to find the first letter to return the detail text -->
NSString *cellValueA = [secondArray objectAtIndex:indexPath.row];
//Returns value from first section and row in all section//
//NSString *cellValueA = [Second objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
cell.detailTextLabel.text = cellValueA;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
How do I find the matching row to the First Array to return the correct index in the Second Array. Any help would be much appreciated. Thank You :-)
FULL CODE
-(void)loadSQL {
// Path to the database
NSString* dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"DATABASE_NAME.sqlite"];
NSLog(#"databasePath: %#",dbPath);
sqlite3 *database;
NSString *firstString;
NSString *secondString;
// Open the database
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
NSString *querySQL = [NSString stringWithFormat:
#"SELECT * FROM songs WHERE items LIKE %# ", viewItems];
const char *sql = [querySQL UTF8String];
sqlite3_stmt *compiledStmt;
// Fetch all names
if (sqlite3_prepare_v2(database, sql, -1, &compiledStmt, NULL) == SQLITE_OK) {
// Append each name
while (sqlite3_step(compiledStmt) == SQLITE_ROW) {
const char* cFirst = (char*)sqlite3_column_text(compiledStmt, 2);
const char* cSecond = (char*)sqlite3_column_text(compiledStmt, 3);
if (cFirst == NULL)
// There should not be a NULL name
NSLog(#"Null name!!");
else {
firstString = [NSString stringWithUTF8String:cName];
secondString = [NSString stringWithUTF8String:cArtist];
[First addObject:firstString];
[Second addObject:secondString];
//[First release];
//[Second release];
}
}
sqlite3_finalize(compiledStmt); // Cleanup the statement
}
else {
NSLog(#"Error retrieving data from database.");
}
sqlite3_close(database);
}
else {
NSLog(#"Error: Can't open database!");
}
//Creating section with 1st letter of the First field//
for (int i=0; i<[First count]-1; i++){
//---get the first char of each state---
char alphabet = [[First objectAtIndex:i] characterAtIndex:0];
NSString *uniChar = [NSString stringWithFormat:#"%C", alphabet];
//---add each letter to the index array---
if (![arrayIndex containsObject:uniChar])
{
[arrayIndex addObject:uniChar];
}
}
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (searching)
return 1;
else
return [arrayIndex count];
}
//---set the title for each section---
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if (searching)
return nil;
else
return [arrayIndex objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (searching)
return([searchedFirst count]);
else{
//return([First count]);
NSString *alphabet = [songIndex objectAtIndex:section];
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *firstArray = [First filteredArrayUsingPredicate:predicate];
return [firstArray count];
}
}
//---set the index for the table---
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
if (searching) {
return nil;
}
return arrayIndex;
}
//return the cell info
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
if(searching) {
cell.textLabel.text = [searchedFirst objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [searchedSecond objectAtIndex:indexPath.row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
else{
//---get the letter in the current section---
NSString *alphabet = [arrayIndex objectAtIndex:[indexPath section]];
//---get all states beginning with the letter---
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *firstArray = [First filteredArrayUsingPredicate:predicate];
NSArray *secondArray = [Second filteredArrayUsingPredicate:predicate];
if ([songArray count]>0) {
NSString *firstValue = [firstArray objectAtIndex:indexPath.row];
NSString *secondValue = [secondArray objectAtIndex:indexPath.row];
cell.textLabel.text = firtValue;
cell.detailTextLabel.text = secondValue;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
return cell;
}
I am not sure I understand what you need, but if you are looking for the index in the array of a given object, then you can use:
indexOfObject:
Returns the lowest index whose corresponding array value is equal to a given object.
- (NSUInteger)indexOfObject:(id)anObject
(ref)
Answering the question from comments about restructuring....
First, create a custom class:
// CellLabels.h
#import <Foundation/Foundation.h>
#interface CellLabels : NSObject
#property (nonatomic, copy) NSString *firstText;
#property (nonatomic, copy) NSString *secondText;
#end
//CellLabels.m
#import "CellLabels.h"
#implementation CellLabels
#synthesize firstText = _firstText;
#synthesize secondText = _secondText;
#end
Instead of First and Second, create and initialize one NSMutableArray called cellData. Replace...
[First addObject:firstString];
[Second addObject:secondString];
...with...
CellLabels *labels = [[CellLabels alloc] init];
labels.first = firstString;
labels.second = secondString;
[cellData addObject:labels];
Then, your array filtering works by comparing "SELF.firstText" and your array references work by using:
CellLabels *labels = [filteredArray objectAtIndex:indexPath.row];
cell.textLabel.text = labels.firstText;
cell.detailTextLabel.text = labels.secondText;
(OK, I didn't check to make sure all that compiled but it should give you the idea.)

NSMutableArray works in ViewDidLoad, but not in DidSelectRowAtIndexPath

Menu.h
#interface Menu : UITableViewController {
NSMutableArray *arrayCellCollectionOrder;
NSMutableDictionary *dictCellCollection;
NSMutableDictionary *dictCellIndividual;
}
#property (nonatomic, retain) NSMutableArray *arrayCellCollectionOrder;
#end
Menu.m
ViewDidLoad works as normal.
#synthesize arrayCellCollectionOrder;
- (void)viewDidLoad {
// Codes to read in data from PLIST
// This part works
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSString *plistPath;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
plistPath = [rootPath stringByAppendingPathComponent:#"InfoTableDict.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:#"InfoTableDict" ofType:#"plist"];
}
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
if (!temp) {
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
arrayCellCollectionOrder = [[[NSMutableArray alloc] init] retain];
arrayCellCollectionOrder = [temp objectForKey:#"CellCollectionOrder"];
// I can access `arrayCellCollectionOrder` here, it's working.
}
cellForRowAtIndexPath works as normal. I can access arrayCellCollectionOrder.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"PhotoCell";
PhotoCell *cell = (PhotoCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"PhotoCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[PhotoCell class]]) {
cell = (PhotoCell *) currentObject;
break;
}
}
}
// Copy the specific dictionary from CellCollection to Cell Individual
dictCellIndividual = [dictCellCollection objectForKey:[NSString stringWithFormat:#"%#", [arrayCellCollectionOrder objectAtIndex:indexPath.row]]];
cell.photoCellTitle.text = [dictCellIndividual objectForKey:#"Title"]; // Load cell title
cell.photoCellImage.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#", [dictCellIndividual objectForKey:#"ThumbnailFilename"]]]; // Load cell image name
return cell;
}
didSelectRowAtIndexPath NOT WORKING. I cannot access arrayCellCollectionOrder.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Browser
NSMutableArray *arrayPhotos = [[NSMutableArray alloc] init];
NSLog(#"indexPath.row = %d", indexPath.row); // Returns the row number i touched, works.
NSLog(#"arrayCellCollectionOrder = %#", [NSString stringWithFormat:#"%#", [arrayCellCollectionOrder objectAtIndex:indexPath.row]]); // DOES NOT WORK.
// Copy the specific dictionary from CellCollection to Cell Individual
dictCellIndividual = [dictCellCollection objectForKey:[NSString stringWithFormat:#"%#", [arrayCellCollectionOrder objectAtIndex:indexPath.row]]]; // This similar line gives error too.
... ...
... ...
... ...
... ...
}
Error is:
* Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFArray objectAtIndex:]: index (1) beyond bounds (0)'
i.e.: I clicked on row 1, but arrayCellCollectionOrder is NULL.
There should have data in arrayCellCollectionOrder as it's declared in ViewDidLoad.
Is there something that I missed out?
Thanks a lot in advance.
arrayCellCollectionOrder = [[[NSMutableArray alloc] init] retain];
arrayCellCollectionOrder = [temp objectForKey:#"CellCollectionOrder"];
Do you see what you are doing to arrayCellCollectionOrder? You first assign it to a new NSMutableArray (and retain it needlessly), and then you immediately orphan the array and assign arrayCellCollectionOrder to another object that you are getting from the temp dictionary. In other words, that first line isn't doing anything for you, other than create a leaked mutable array.
If the second line is correct and you are getting a valid object and that is what you want, then the problem is that I don't see where that object is getting retained. As long as it is in the dictionary, it is probably retained, but if temp is discarded, then its members are released. If you did a
self.arrayCellCollectionOrder = [temp objectForKey:#"CellCollectionOrder"];
then the setter would retain it.

Read plist data into a NSArray but get null

I got same warning here “local declaration hides instance variable” warning
but I got more problems...
Here is my code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.someaddress.php"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
NSLog(#"\n\nCONNECTION: %#", theConnection);
NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
NSString *listFile = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
NSMutableArray *plist = [[NSMutableArray alloc] init];
plist = [listFile propertyList];
NSLog( #"\n 1111 plist is \n%#", plist );
//I can get a plist format data here,But nothing in 2222
NSLog(#"Now you see me tableView Row Count");
NSLog(#"TOTAL PLIST ROW COUNT IS = %i", [plist count]);
// Return the number of rows in the section.
return [plist count];
}
and I got Warning here"Local declaration of 'plist' hides instance variable"
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LightCell";
LightCell0 *cell =(LightCell0 *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[LightCell0 alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell…
NSLog(#"Now you see me Load Data %i", indexPath.row);
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
//I try to get list data here But RETURN NULL
NSLog( #"\n 2222 plist is \n %#", plist);
switch (indexPath.row) {
case 0:
if ([plist valueForKey:#"nodeStatus"] == 0){
cell.lightImageView.image = [UIImage imageNamed:#"lightOff.png"];
NSLog(#"value for key Node Status : %#" ,[self.plists Valuefokey:#"nodeStatus"]);
//also return NULL !!
}
else if([self valueForKey:#"nodeStatus"] == 1){
cell.lightImageView.image = [UIImage imageNamed:#"lightOn.png"];
}
break;
case 1:
cell.lightLocation.text =[plist valueForKey:#"nodeName"] ;
if ([plist valueForKey:#"nodeStatus"] == 0){
cell.lightImageView.image = [UIImage imageNamed:#"lightOff.png"];
}
else if([plist valueForKey:#"nodeStatus"] == 1){
cell.lightImageView.image = [UIImage imageNamed:#"lightOn.png"];
};
break;
default:
break;
}
return cell;
}
This is the tow items I create in a plist
{
category = Light;
nodeID = 1;
nodeName = "Living Room";
nodeStatus = 0;
nodeTrigger = 0;
nodeType = "light_sw";
},
{
category = Light;
nodeID = 2;
nodeName = Kitchen;
nodeStatus = 0;
nodeTrigger = 0;
nodeType = "light_sw";
}
So that's my question ,Why can't I pass "plist" from
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
...
}
to
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
}
and I use NSMutableArray *plist = [[NSMutableArray alloc] init];
But still appear "Local declaration of 'plist' hides instance variable"
???
hope someone can figure out this problem
Best Regards !
and I got Warning here"Local declaration of 'plist' hides instance variable"
Well, then, you should fix that.
The warning is telling you that you've declared two variables named plist: One local to this instance method, and the other an instance variable. The local variable, having a narrower scope, hides the instance variable, so that when you refer to plist in the method, you are referring to the local variable. This means that you cannot access anything stored in the instance variable by another method, nor store anything in it for another method to retrieve.
The solution is either to kill off or to rename the local variable. If the latter is what you want, use Xcode's “Edit All in Scope” feature.
Also:
NSMutableArray *plist = [[NSMutableArray alloc] init];
plist = [listFile propertyList];
Creating the array on the first of those lines is redundant, because you immediately replace your pointer to that array with the pointer to another array, returned by propertyList. Thus, you never use and you leak the first array. You should at least cut out the creation of the first array, and you should probably cut out the entire first line (thereby cutting out both the first array and the local variable).
Here is the code I fix the warning ,the program can build without any warning
it also can display the result after reading the plist in tableview
1.Load the plist:
- (void)viewDidLoad {
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www. someaddress.php"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
NSData *returnData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:nil error:nil];
NSString *listFile = [[NSString alloc] initWithData:returnData encoding:NSASCIIStringEncoding];
plist = [listFile propertyList];
}
2.return the number to rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [plist count];
}
3.read the plist data to show result in cells
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"LightCell0";
LightCell0 *cell =(LightCell0 *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[LightCell0 alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell…
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
int i;
for (i=0; i<[plist count]; i++) {
//Get nodeName
if(indexPath.row == i)
{
cell.lightLocation.text = [[[plist objectAtIndex:i] valueForKey: #"nodeName"]description];
//Get Light Status to show the image
if ([[[plist objectAtIndex:i] valueForKey: #"nodeStatus"] intValue] == 0){
cell.lightImageView.image = [UIImage imageNamed:#"lightOff.png"];
}
else if([[[plist objectAtIndex:i] valueForKey: #"nodeStatus"] intValue] == 1){
cell.lightImageView.image = [UIImage imageNamed:#"lightOn.png"];
cell.lightSwitch.on=YES;
}
}
}
return cell;
}
It can get the right data ,and display the correct result in the tableview cells
BUTTTTTTT
If you scroll up the tableview,it's ok,when you on the top it will scroll down Automatically
When you "scroll down" the tableview,program crash ???
WHY ??? did I write anything wrong ???
plist = [listFile propertyList];=====>self.plist = [listFile propertyList];
THAT IS CORRECT