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.
Related
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.
I have the following code. It results in a sectioned uitableview. However, the words in each section are in reverse order (r before a, x before t). I have tried to use nsdescriptor and selectors in various parts of the code but it results in Xcode throwing nsexception ncsf dictionary invalid selector sent localisedcaseinsensitivecompare. This only occurs when I fiddle with the above - even if I don't add localisedCaseInsensitiveCompare (it works with those instances that are already in place).
Any fresh eyes able to solve this.
Thanks
#implementation RCViewController
static NSString *CellIdentifier = #"Cell Identifier";
#synthesize words;
#synthesize alphabetizedWords;
#synthesize wordDictionary;
#synthesize keys;
-(NSDictionary *)alphabetizedWords:(NSArray *)wordsArray {
NSMutableDictionary *buffer = [[NSMutableDictionary alloc]init];
for (int i=0; i <wordsArray.count; i++) {
NSDictionary *keyValue = [wordsArray objectAtIndex:i];
NSString *word = [[wordsArray objectAtIndex:i]objectForKey:#"Word"];
NSString *firstLetter = [[word substringToIndex:1]uppercaseString];
if ([buffer objectForKey:firstLetter]) {
[(NSMutableArray *)[buffer objectForKey:firstLetter]addObject:keyValue];
}
else {
NSMutableArray *mutableArray = [[NSMutableArray alloc]initWithObjects:keyValue, nil];
[buffer setObject:mutableArray forKey:firstLetter];
}
}
NSArray *bufferKeys = [buffer allKeys];
for (int j; j<bufferKeys.count; j++) {
NSString *bufferkey = [bufferKeys objectAtIndex:j];
[(NSMutableArray *)[buffer objectForKey:bufferkey]sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
NSDictionary *result = [NSDictionary dictionaryWithDictionary:buffer];
return result;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [keys count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *key = [_sortedKeys objectAtIndex:section];
NSArray *wordsForSection = [self.alphabetizedWords objectForKey:key];
return [wordsForSection count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *key = [_sortedKeys objectAtIndex:[indexPath section]];
NSArray *wordsForSection = [self.alphabetizedWords objectForKey:key];
NSString *word = [[wordsForSection objectAtIndex:[indexPath row]]objectForKey:#"Word"];
[cell.textLabel setText:word];
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *key = [_sortedKeys objectAtIndex:section];
return key;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"showDetail" sender:cell];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
detailViewController *destViewController = segue.destinationViewController;
NSString *key = [_sortedKeys objectAtIndex:[indexPath section]];
NSArray *wordsForSection = [self.alphabetizedWords objectForKey:key];
NSString *word = [[wordsForSection objectAtIndex:[indexPath row]]objectForKey:#"Word"];
destViewController.word = word;
destViewController.definition = [[wordsForSection objectAtIndex:[indexPath row] ]objectForKey:#"Definition"];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *path = [[NSBundle mainBundle]pathForResource:#"words" ofType:#"plist"];
NSArray *wordsDictionary = [NSArray arrayWithContentsOfFile:path];
self.words = wordsDictionary;
self.alphabetizedWords = [self alphabetizedWords:self.words];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
self.keys = [self.alphabetizedWords allKeys];
self.sortedKeys = [keys sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You are creating an array of dictionaries. Dictionaries don't support the compare method. You therefore can't use a selector based sort. You need to use a different sort method, like sortUsingComparator, or a predicate. (There are lots of different ways to sort arrays.)
If you just have to reverse the position of element of array you could use following
NSArray *wordArray = [[NSArray alloc] initWithObjects:#"Brian",#"Job",#"Bob",#"Ben",#"Robert", nil];
wordArray = [[wordArray reverseObjectEnumerator] allObjects];
Your output will be : Robert, Ben, Bob, Job, Brian.
I'm a little confused about working with property lists. I've read most of the other questions about this topic, but I'm still very confused since they only go in one layer, so any help would be appreciated.
I would like to load a plist that stores data somewhat like this:
I have three ViewControllers (two TableViewControllers and one blank) in my Storyboard that I want to display different levels of information:
Categories of people (Friends, etc.)
Names of the people in those categories (Bob, etc.)
Information about the people (favorite color, etc.)
How do I read/write files to a plist, and how to I access that information across multiple views?
Once I read the data, how do I display the information in different TableViewControllers?
Let's say that you have a plist file like this:
and this code:
#implementation ViewController
NSDictionary *dictionary;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSMutableArray *array=[[NSMutableArray alloc]init];
array=[NSMutableArray arrayWithContentsOfFile:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"root.plist"]];
dictionary = [array objectAtIndex:0];
}
- (NSString *)applicationDocumentsDirectory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(#"numberOfSectionsInTableView:%lu",(unsigned long)dictionary.count);
return dictionary.count;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[[dictionary allKeys] objectAtIndex:section] capitalizedString];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSArray *peopleArray = [dictionary objectForKey:[[dictionary allKeys] objectAtIndex:indexPath.section]];
cell.textLabel.text = [[peopleArray objectAtIndex:indexPath.row]objectForKey:#"name"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Color:%# - Gender:%#",[[peopleArray objectAtIndex:indexPath.row]objectForKey:#"favorite color"],[[peopleArray objectAtIndex:indexPath.row]objectForKey:#"gender"]];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *key =[[dictionary allKeys] objectAtIndex:section];
NSLog(#"numberOfRowsInSection:%lu",(unsigned long)[[dictionary objectForKey:key] count]);
return [[dictionary objectForKey:key] count];
}
it will give you this output:
(Supposed you have a tableView set up with Delegate and DataSource)
I know that you asked for having the "Friends" and "Enemies" in different TableViews, but I use both in the same tableView but in different sections. But my code can get you started.
If you need extra help about the UITableView, see Apple UITableView Class Reference
If this is necessary, I used this code to generate the example plist-file in my test-project:
NSMutableArray *root=[[NSMutableArray alloc]init];
NSMutableArray *friendsarray = [[NSMutableArray alloc]init];
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setObject:#"Jill" forKey:#"name"];
[dict setObject:#"green" forKey:#"favorite color"];
[dict setObject:#"female" forKey:#"gender"];
[friendsarray addObject:dict];
NSMutableDictionary *dict2 = [[NSMutableDictionary alloc]init];
[dict2 setObject:#"Bob" forKey:#"name"];
[dict2 setObject:#"Blue" forKey:#"favorite color"];
[dict2 setObject:#"male" forKey:#"gender"];
[friendsarray addObject:dict2];
NSMutableArray *enemiesarray = [[NSMutableArray alloc]init];
NSMutableDictionary *dict3 = [[NSMutableDictionary alloc]init];
[dict3 setObject:#"Michael" forKey:#"name"];
[dict3 setObject:#"Red" forKey:#"favorite color"];
[dict3 setObject:#"male" forKey:#"gender"];
[enemiesarray addObject:dict3];
NSMutableDictionary *d = [[NSMutableDictionary alloc]init];
[d setObject:friendsarray forKey:#"friends"];
[d setObject:enemiesarray forKey:#"enemies"];
[root addObject:d];
[root writeToFile:[[self applicationDocumentsDirectory] stringByAppendingPathComponent:#"root.plist"] atomically:YES];
There are numerous examples here in Stack Overflow of reading plist and passing data between ViewControllers. Its advisable to read through them & ideally connect them together to get your solution.
Hope that helps.
You have some example like this : http://iosdevelopertips.com/data-file-management/reading-a-plist-into-an-nsarray.html
it's pretty easy.
Developing a iPAD app, where I'm trying to populate table, This is how i'm doing:
In view did load, I'm creating two dictionary object and adding object as Pdf and Excel.
- (void)viewDidLoad
{
[super viewDidLoad];
arrDocuments = [[NSMutableArray alloc] init];
NSArray *arr1 = [NSArray arrayWithObjects:#"PDF", nil];
NSDictionary *pdf = [NSDictionary dictionaryWithObjects:arr1 forKeys:nil];
NSArray *arr2 = [NSArray arrayWithObjects:#"Excel", nil];
NSDictionary *excel = [NSDictionary dictionaryWithObjects:arr2 forKeys:nil];
[arrDocuments addObject:pdf];
[arrDocuments addObject:excel];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrDocuments count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
//return [arrReceipes count];
NSDictionary *dictionary = [arrDocuments objectAtIndex:section];
NSArray *array = [dictionary objectForKey:[self.sortedKeys objectAtIndex:section]];
return [array count];
}
-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableView *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell ==nil) {
cell = [[UITableViewCell alloc]initWithFrame:CGRectZero reuseIdentifier:MyIdentifier];
}
return cell;
}
With this implementation I'm not able to see table view.Its going to main method and showing me SIGABRT message.Where I'm going wrong??
While creating NSDictionary, you have passed nil in place of keys array,
NSDictionary *pdf = [NSDictionary dictionaryWithObjects:arr1 forKeys:nil];
You should give proper objects and keys to the dictionary. This method expects objects and keys to be given in an array as you can see in its method signature.
+ (instancetype)dictionaryWithObjects:(NSArray *)objects forKeys:(NSArray *)keys
I have a very simple app to learn how to work with sections in UITableView but there is an exception -
2013-09-17 08:46:19.956 Sections[4497:c07] * -[__NSArrayI
objectAtIndex:]: message sent to deallocated instance 0x9566d40
The whole methods are below - need help.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"sortednames" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.names = dict;
NSArray *array = [[_names allKeys] sortedArrayUsingSelector:#selector(compare:)];
_keys = array;
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"%lu", (unsigned long)[_keys count]);
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];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
}
- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *key = [_keys objectAtIndex:section];
return key;
}
You must retain _keys array like that:
_keys = [[[_names allKeys] sortedArrayUsingSelector:#selector(compare:)] retain];
Here you are first taking values in other array and then passing it to _keys..thats not proper way of doing it..
just directly pass the values to _keys like below
_keys = [[_names allKeys] sortedArrayUsingSelector:#selector(compare:)];
also check for self.names, you are doing the same thing there.
Hope this will help you.