Loading plist into iOS TableView - ios

I have a plist (images.plist) with the following contents
As you can see, each item has a numerical key, from 0-19. Each item also has two strings (fileName and fileInfo).
I'm trying to load all of the fileName's into a TableView. Here's my attempt:
RosterMasterViewController.h
#interface RosterMasterViewController : UITableViewController
#property (nonatomic, strong) NSDictionary *roster;
#end
RosterMasterViewController.m
#implementation RosterMasterViewController
#synthesize roster = _roster;
...
// This is in my 'viewDidLoad'
NSString *file = [[NSBundle mainBundle] pathForResource:#"images" ofType:#"plist"];
self.roster = [NSDictionary dictionaryWithContentsOfFile:file];
And here's how I'm trying to load the fileName into the Prototype Cells.
RosterMasterViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"imageNameCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell
cell.textLabel.text = [[[self.roster allKeys] objectAtIndex:indexPath.row] objectForKey:#"fileName"];
return cell;
}
NOTE
For the record, my CellIdentifier is correct, if I set the cell.textLabel.text to be #"HELLO!", then I will see "HELLO!" for each item in the NSDictionary. I'm having difficulty with the //Configure the cell section
Unfortunately this isn't working as I expected. I'm having difficulty since my keys are all numerical I think.
UPDATE
Trying to use what I've learned from the answers below, I have this:
// Configure the cell
NSLog(#"Key: %#", [NSNumber numberWithInt:indexPath.row]);
NSDictionary *dict = [self.roster objectForKey:[NSNumber numberWithInt:indexPath.row]];
NSLog(#"Dictionary: %#", dict);
NSString *fileName = [dict objectForKey:#"fileName"];
NSLog(#"FileName: %#", fileName);
cell.textLabel.text = fileName;
return cell;
But that's giving me results like:
2012-02-03 11:24:24.295 Roster[31754:f803] Key: 7
2012-02-03 11:24:24.295 Roster[31754:f803] Dictionary: (null)
2012-02-03 11:24:24.296 Roster[31754:f803] FileName: (null)
If I change this line:
NSDictionary *dict = [self.roster objectForKey:[NSNumber numberWithInt:indexPath.row]];
to:
NSDictionary *dict = [self.roster objectForKey:#"5"];
Then all of the cells will have the correct fileName for the 6th element. Any idea why [NSNumber numberWithInt:indexPath.row isn't working?

You can do this:
NSDictionary *dict = [self.roster objectForKey:indexPath.row];
NSString *fileName = [dict objectForKey:#"fileName"];

As pointed out by Oscar, self.roster it's a NSDictionary wich have inside of him dictionaries for each numeric key.
You must first retrieve the NSDictionary for the numeric key: NSDictionary *fileDictionary = [self.roster objectForKey:indexPath.row];
After that you must extract your filename from this last dictionary so you must request the string for the #"fileName" key.
NSString *fileName = [fileDictionary objectForKey:#"fileName"];
cell.textLabel.text = fileName;
return cell;

No sure if you solved the problem already, but below is how I solved this issue.
NSDictionary *dict =
[self.allItem objectForKey:[NSString stringWithFormat:#"%d",indexPath.row]];
I think the reason was [NSNumber numberWithInt:indexPath.row] is returning number/int value.
But objectForKey: is expecting to receive a string value.
Hope this help.

Related

Obj-C - Remove cell from tableview if NSMutableArray contains same field more than once

I want to remove UITableViewCells from my TableView if the userName "Brittany" appears more than once in my NSMutableArray. E.g. only the first cell displaying userName "Brittany" should appear. If my array self.messages contains userName "Brittany" more than once, I only want to show the first cell. How can I do this? See code below so far:
ViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
NSMutableArray* NameDictionary=[[NSMutableArray alloc] init];
NSString* PreviousName;
int oneTime=0;
for(int i=0;i<[self.messages count];i++){
NSDictionary *fromUser = [self.messages objectAtIndex: i];
NSString *userName = [fromUser objectForKey:#"name"];
if(oneTime==0)
{
NSLog(#"TEST!");
PreviousName=userName;
[NameDictionary addObject:[self.messages objectAtIndex: i]];
oneTime=1;
}
if(oneTime!=0)
{
if([PreviousName isEqualToString: userName])
{
NSLog(#"TEST 1!");
}
else{
[NameDictionary addObject:[self.messages objectAtIndex: i]];
NSLog(#"TEST 2!");
}
PreviousName=userName;
}
}
}
NSDictionary *receivedSubjectLine = [self.messages objectAtIndex:indexPath.row];
NSString *messageSubject = [receivedSubjectLine objectForKey:#"node_title"];
[cell.subjectLine setText:messageSubject];
NSDictionary *fromUser = [self.messages objectAtIndex:indexPath.row];
NSString *userName = [fromUser objectForKey:#"name"];
[cell.senderName setText:userName];
NSDictionary *receivedBody = [self.messages objectAtIndex:indexPath.row];
NSString *messageBody = [receivedBody objectForKey:#"body"];
[cell.fullMessage setText:messageBody];
NSDictionary *messageReceived = [self.messages objectAtIndex:indexPath.row];
NSString *timeReceived = [messageReceived objectForKey:#"published at"];
NSLog(#"Message Received at %#", timeReceived);
[cell.receivedStamp setText:timeReceived];
return cell;
}
You should not try to display non-duplicate items from an array into a table view. That's a recipe for disaster.
Instead, create a removeDuplicates function that takes an input array and returns a new array.
Have the function create an empty mutable set. Loop through the source array from beginning to end. For each object from the source array, if it is not in the set, append it to both the test set and the destination array. If it is in the test set, skip it.
Note that the above will only work if the objects in the array implement the isEqual method and return a meaningful value. By default I believe generic NSObjects return isEqual == true if you are comparing the exact same object. Other classes like NSString and NSNumber implement an isEqual method that actually compares the value. If you're comparing complex objects using something like a string userName, you might need to create a custom object type (e.g. UserObject) that has a custom implementation of isEqual.
That should be enough to get you started. If you get stuck, post your code an an explanation of the problems you're having.

Obj-C: Only return 1 cell (top cell) if cells proceeding contain the same UILabel values?

The top 3 cells in my tableview have a label that says the word 'Squirrels'. Is there a way to make it so that if a UILabel says 'Squirrels' in more than one cell in my table, to only show the first cell of the three?
E.g. if UILabel userName in tableviewCell is equal to #"Squirrels", only show one table
view cell in the table that contains Squirrels in the UILabel
Hope this makes sense. Thanks in advance!
EDIT: I've successfully retrieved the first array containing more than one common 'name' value (see edit to code below). That said, when I try and display these values (firstFoundObject) in my tableview I get the following crash error:
-[__NSDictionaryI objectAtIndex:]: unrecognized selector sent to instance 0x1c01a5a20 2017-10-03 23:01:51.728128-0700
pawswap[623:85420] *** Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSDictionaryI
objectAtIndex:]: unrecognized selector sent to instance 0x1c01a5a20'
ViewController.m
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *nodeTitle = self.messages[0][#"name"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", nodeTitle];
NSArray *filteredArray = [self.messages filteredArrayUsingPredicate:predicate];
id firstFoundObject = nil;
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil;
NSMutableArray *firstObjects = firstFoundObject;
return [firstObjects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *nodeTitle = self.messages[0][#"name"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", nodeTitle];
NSArray *filteredArray = [self.messages filteredArrayUsingPredicate:predicate];
id firstFoundObject = nil;
firstFoundObject = filteredArray.count > 0 ? filteredArray.firstObject : nil;
NSMutableArray *firstObjects = firstFoundObject;
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *receivedSubjectLine = [firstObjects objectAtIndex:indexPath.row];
NSString *messageSubject = [receivedSubjectLine objectForKey:#"node_title"];
[cell.subjectLine setText:messageSubject];
NSDictionary *fromUser = [firstObjects objectAtIndex:indexPath.row];
NSString *userName = [fromUser objectForKey:#"name"];
[cell.senderName setText:userName];
NSDictionary *receivedBody = [firstObjects objectAtIndex:indexPath.row];
NSString *messageBody = [receivedBody objectForKey:#"body"];
[cell.fullMessage setText:messageBody];
NSDictionary *messageReceived = [firstObjects objectAtIndex:indexPath.row];
NSString *timeReceived = [messageReceived objectForKey:#"published at"];
NSLog(#"Message Received at %#", timeReceived);
[cell.receivedStamp setText:timeReceived];
return cell;
}
PREVIOUS
ViewController.m
#pragma mark - Table view data source
- (int)numberOfSectionsInTableView: (UITableView *)tableview
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.messages count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSDictionary *receivedSubjectLine = [self.messages objectAtIndex:indexPath.row];
NSString *messageSubject = [receivedSubjectLine objectForKey:#"node_title"];
[cell.subjectLine setText:messageSubject];
NSDictionary *fromUser = [self.messages objectAtIndex:indexPath.row];
NSString *userName = [fromUser objectForKey:#"name"];
[cell.senderName setText:userName];
NSDictionary *receivedBody = [self.messages objectAtIndex:indexPath.row];
NSString *messageBody = [receivedBody objectForKey:#"body"];
[cell.fullMessage setText:messageBody];
NSDictionary *messageReceived = [self.messages objectAtIndex:indexPath.row];
NSString *timeReceived = [messageReceived objectForKey:#"published at"];
[cell.receivedStamp setText:timeReceived];
return cell;
}
Basically the problem you are getting is due to firstObject is of type Dictionary and you are type casting it to NSMutableArray. Please check below line:
id firstFoundObject = nil; firstFoundObject = filteredArray.count > 0
? filteredArray.firstObject : nil;
If you see you have filteredArray.firstObject as Dictionary in your application which you capture in firstFoundObject but later you are making it NSMutableArray type here:
NSMutableArray *firstObjects = firstFoundObject;
And later when you try to get here, it crashes
NSDictionary *receivedSubjectLine = [firstObjects
objectAtIndex:indexPath.row];
The correct - basic - version of your code should look like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PointsTableIdentifier = #"MyMessagesCell";
MyMessagesCell *cell = (MyMessagesCell *)[tableView dequeueReusableCellWithIdentifier:PointsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyMessagesCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
[cell.subjectLine setText:[self.recvMessage objectForKey:#"node_title"]];
[cell.senderName setText:[self.recvMessage objectForKey:#"name"]];
[cell.fullMessage setText:[self.recvMessage objectForKey:#"body"]];
[cell.receivedStamp setText:[self.recvMessage objectForKey:#"published at"]];
return cell;
}
Though it is not optimised but still it can do work for you.
COUNT ISSUE:
NSMutableDictionary *firstObjects = firstFoundObject;
return [firstObjects count];
In your code above you have inside the numberOfRowsInSection since you have firstFoundObject as dictionary so when you call [firstObjects count] which is a valid call and it returns the number of key in the dictionary.
You have modify it like :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
NSInteger rowCount = filteredArray.count;
self.recvMessage = rowCount? filteredArray.firstObject: nil;
return rowCount? 1: 0;
}
and you have new data which actually stores the filtered object.
#property (nonatomic) NSDictionary *recvMessage;
Hope this helps.
Yes you can do it easily,
You will do it before run tableView,
for example :
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary* NameDictionary=[[NSMutableDictionary alloc] init];
NSString* PreviousName;
int oneTime=0;
for(int i=0;i<[self.messages count];i++){
NSDictionary *fromUser = [self.messages objectAtIndex: i];
NSString *userName = [fromUser objectForKey:#"name"];
if(oneTime==0)
{
PreviousName=userName;
[NameDictionary addObject:[self.messages objectAtIndex: i]];
oneTime=1;
}
if(oneTime!=0)
{
if([PreviousName isEqualToString: userName])
{
}
else{
[NameDictionary addObject:[self.messages objectAtIndex: i]];
}
PreviousName=userName;
}
}
}
When you ask to filter out cells with a senderName property equal to #"Squirrels", you're effectively asking to change your datasource after it has been set. This will cause problems in your numberOfRowsInSection method, which will return more rows than you need if any filtering takes place after the datasource is set.
As one of the comments to your answer suggests, "make a secondary array which contains unique elements of self.messages and work with this array." The array that makes up the datasource of the tableview should require no filtering. The tableview should just be able to present it.
If I had enough reputation to comment on the above answer, I would say that you're right that it doesn't work because self.messages doesn't change. Instead of collecting the "non-duplicate" objects in NameDictionary, consider collecting them in an NSMutableArray. This new, filtered array should be the datasource for your array. You may want to filter this array outside of this ViewController so that once the array arrives at this view controller it can just be assigned to self.messages.
If you're looking to exclude all duplicates, as opposed to just duplicates that appear next to each other, consider this answer.

Program flow issues in ios

I am parsing a json to display the contents in the tableview. I have the array containing parsed json being populated in getReceivedData which is called after the UITAbleView Delegate methods. So it is problem in populating tableview as when the compiler attempts to populate it the array is not yet initialized.
- (void)getReceivedData:(NSMutableData *)data sender:(RestAPI *)sender{
NSError * error=nil;
NSArray *receivedData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSString *dictionaryKey=#"department";
NSString *predicateString=#"software";
NSPredicate *predicate=[NSPredicate predicateWithFormat:#" %K == %# ", dictionaryKey,predicateString];
NSArray *shortlisted=[receivedData filteredArrayUsingPredicate:predicate];
for(int i = 0; i<shortlisted.count; i++)
{
NSDictionary *detailItems=[shortlisted objectAtIndex:i];
NSString *name=[detailItems objectForKey:#"emp_name"];
NSString *designation=[detailItems objectForKey:#"designation"];
NSString *email=[detailItems objectForKey:#"email"];
NSString *phone_no=[detailItems objectForKey:#"phone_no"];
// NSString *image=[detailItems objectForKey:#"url_path"];
dictionary1=[NSMutableDictionary dictionaryWithObjectsAndKeys:
name, #"keyname",
designation, #"keydesignation",
email, #"keyid",
phone_no, #"keyphone",
nil];
[myObject1 addObject:dictionary1];
}
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section{
if(isfiltered==YES){
return [filteredArray count];
}
else{
return [myObject1 count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MyTableCell *cell=[tableView dequeueReusableCellWithIdentifier:#"myCell"];
if(!cell){
[tableView registerNib:[UINib nibWithNibName:#"MyTableCell" bundle:nil]
forCellReuseIdentifier:#"myCell"];
cell=[tableView dequeueReusableCellWithIdentifier:#"myCell"];
}
if(isfiltered==NO)
{
NSDictionary * tmpdict= [myObject objectAtIndex:indexPath.row];
cell.nameLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyname"]];
cell.designationLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keydesignation"]];
cell.idLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyid"]];
cell.phoneLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyphone"]];
cell.mainImg.image = [UIImage imageNamed:[tmpdict objectForKeyedSubscript:#"keyimage"]];
}
else{
NSDictionary * tmpdict= [filteredArray objectAtIndex:indexPath.row];
cell.nameLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyname"]];
cell.designationLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keydesignation"]];
cell.idLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyid"]];
cell.phoneLabel.text=[NSMutableString stringWithFormat:#"%#",[tmpdict objectForKeyedSubscript:#"keyphone"]];
cell.mainImg.image = [UIImage imageNamed:[tmpdict objectForKeyedSubscript:#"keyimage"]];
}
return cell;
}
This window was supposed to view the table
In a mutable dictionary first you have to give object then its key. You are doing wrong
for(int i = 0; i<shortlisted.count; i++)
{
NSDictionary *detailItems=[shortlisted objectAtIndex:i];
NSString *name=[detailItems objectForKey:#"emp_name"];
NSString *designation=[detailItems objectForKey:#"designation"];
NSString *email=[detailItems objectForKey:#"email"];
NSString *phone_no=[detailItems objectForKey:#"phone_no"];
dictionary1=[NSMutableDictionary dictionaryWithObjectsAndKeys:
name,#"keyname",
designation,#"keydesignation",
email,#"keyid",
phone_no,#"keyphone",
nil];
[myObject1 addObject:dictionary1];
}
Actually this is not correct way to intialize dictionary as you did, #"%#" is used %# is a placeholder in a format string for any object.
dictionary1=[NSMutableDictionary dictionaryWithObjectsAndKeys:
name,#"keyname",
designation,#"keydesignation",
email,#"keyid",
phone_no,#"keyphone",
nil];

Cant read dictionary data from plist file in IOS

I have PropertyList.plist file in the "Supporting Files" folder. I have made a dictionary in it. The plist file is:
MY ViewController.m file code is
#implementation GroupedInexedViewController
{
NSDictionary *names;
NSArray *keys;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"PropertyList"
ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc]
initWithContentsOfFile:path];
names = dict;
[dict release];
NSArray *array = [[names allKeys] sortedArrayUsingSelector:
#selector(compare:)];
keys = array;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [keys count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
return [nameSection count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if(cell == nil)
{
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier] autorelease];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
}
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *key = [keys objectAtIndex:section];
return key;
}
Unfortunately the "keys" array doesnt contain any element. Because I made an alert with its count value which is "keys.count" and it was zero. and also the "names" count was also zero. The path variable on vieDidLoad method shows the correct path. but it cant read from the dictionary of the plist file's.
Edit: I used nslog and it shows that in "viewDidLoad" method "names" is able to load the dictionary . but "keys" array is unable to load it.
What #EugeneK said worked but got sigabrt in "cellForRowAtIndexPath" method on the line
cell.textLabel.text = [nameSection objectAtIndex:row];
the error message is
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6832440".
The problem was nameSection variable was appearing as a NSDictionary type object which doesn't support objectAtIndex method.
So what I did I know is not a very good way to do it. I am sure there is some other way. I changed the 'viewDidLoad' method to this,
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"PropertyList"
ofType:#"plist"];
names = [[NSDictionary alloc]
initWithContentsOfFile:path];
keys = [names allKeys];
NSString *key = [keys objectAtIndex:0];
names = [names objectForKey:key];
keys = [[[names allKeys] sortedArrayUsingSelector:#selector(compare:)] retain];
NSLog(#"keys = %# names = %#",keys,names);
}
It works! Any idea how to do it better will be appreciated though.
Martin R is right. Please see comments in your code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"PropertyList"
ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc]
initWithContentsOfFile:path]; //retainCount of dict is 1
names = dict; // you made weak reference to dict
[dict release]; // retainCount is 0 - dict is being dealloced
NSArray *array = [[names allKeys] sortedArrayUsingSelector:
#selector(compare:)]; // you try to get data from dealloced object
keys = array;
}
Try to do the following:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"PropertyList"
ofType:#"plist"];
names = [[NSDictionary alloc]
initWithContentsOfFile:path];
keys = [[[names allKeys] sortedArrayUsingSelector:
#selector(compare:)] retain];
}
And do not forgot to release names and keys in your view controller dealloc.

List Contents of Directory in a UITableView

I am trying to list the contents of Ringtones directory in a TableView, however, I am only getting the last file in the directory in ALL cells, instead of file per cell. This is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Profile_ManagerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cell.hidesAccessoryWhenEditing = YES;
}
cell.accessoryType = UITableViewCellAccessoryNone;
//cell.textLabel.text = #"No Ringtones";
//cell.textLabel.text = #"Test";
NSString *theFiles;
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager directoryContentsAtPath:#"/Test"];
for (NSString *s in fileList){
theFiles = s;
}
cell.textLabel.text = theFiles;
return cell;
}
It loads fine, no errors, when I use NSLog it lists all the files in the directory just fine. I even tried [s objectAtIndex:indexPath.row] but i get objectAtIndex: error. Anyone have any ideas?
I actually love asking questions on here, cause in less than 10 minutes, I answer my own question!
This is how I got the above code to work:
NSMutableArray *theFiles;
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager directoryContentsAtPath:#"/Test"];
for (NSString *s in fileList){
theFiles = fileList;
}
cell.textLabel.text = [theFiles objectAtIndex:indexPath.row];
return cell;
I just made the NSString an NSMutableArray, and that allowed me to use the objectAtIndex. Now to trim the file extension!
You should remove NSString,NSMutableArray and for loop.. the final code should be like this:
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager directoryContentsAtPath:#"/Test"];
cell.textLabel.text = [fileList objectAtIndex:indexPath.row];
return cell;
BTW, this fileList and manager created repeatedly for each cell.. So it is better to make it a global variable for UITableViewController and assign only 1
Your for loop is just iterating over the files and setting theFiles to the current path. So at the end of the loop, theFiles will just be the last string in the collection.
Try something like:
cell.textLabel.text = [fileList objectAtIndex:indexPath.row];

Resources