Application crashes when searching ONE word - objective-c

I'm making my UISearchBar working and i've noticed that if i type a word, just ONE, contained in more controllers (for example "a") and i select a row, i get an unexpected crash. If i search for more than a word it works, even if contained in more than 1 controller.
i'm getting a NSRangeException:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 9 beyond bounds [0 .. 8]'
at line
cellValue = [array objectAtIndex:indexPath.row];
of my code (i have 3 sections)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
//Get the nib
NSString *cellValue = nil;
if(searching)
cellValue = [copyListOfItems objectAtIndex:indexPath.row];
else {
NSDictionary *dictionary =[listaOggetti objectAtIndex:indexPath.row];
NSArray *array = [dictionary objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row];
}
NSDictionary *dict = [listaOggetti objectAtIndex:indexPath.section];
NSArray *array = [dict objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row] ; //here's the error
if (indexPath.section == 0)
{
if ([cellValue isEqual: #"FirstNib"]){
FIrstViewController *firstController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
[self.navigationController pushViewController:appsController animated:YES];
[firstController release];
if ([cellValue isEqual: #"SecondNib"]){
secondViewController *secondController = [[SecondViewController alloc] initWithNibName:#"secondViewController" bundle:nil];
[self.navigationController pushViewController:secondController animated:YES];
[secondController release];
}
//and so on
}
if (indexPath.section == 1){
if ([cellValue isEqual: #"ThirdNib"]){
ThirdViewController *firstController = [[ThirdViewController alloc] initWithNibName:#"ThirdViewController" bundle:nil];
[self.navigationController pushViewController:ThirdController animated:YES];
[ThirdController release];
}
//and so on
}
if (indexPath.section == 2) {
if ([cellValue isEqual #"FourthNib"]){
FourthViewController *firstController = [[FourthViewController alloc] initWithNibName:#"FourthViewController" bundle:nil];
[self.navigationController pushViewController:FourthController animated:YES];
[FourthController release];
}
}
(the line is not the one in the IF state)
Now. I know that it goes over the array, trying to access to the 10th element.
Passing the mouse over the line "array" here
cellValue = [array objectAtIndex:indexPath.row] ;
It tells me there are 9 objects on it, while there should be 45, as i declared them here, for the key #"Elementi":
- (void)viewDidLoad {
[super viewDidLoad];
listaOggetti = [[NSMutableArray alloc] init];
NSArray *arrayDesk = [NSArray arrayWithObjects: #"First",#"Second",#"Third"..#"9th", nil];
NSArray *sortedDesk = [arrayDesk sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictDesk = [NSDictionary dictionaryWithObject:sortedDesk forKey:#"Elementi"];
NSArray *arrayLion = [NSArray arrayWithObjects:#"First1",#"Second1" ... #"30th", nil];
NSArray *sortedLion = [arrayLion sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictLion = [NSDictionary dictionaryWithObject:sortedLion forKey:#"Elementi"];
NSArray *arrayRestore = [NSArray arrayWithObjects:#"First2",#"Second2" ... #"6th", nil];
NSArray *sortedRestore = [arrayRestore sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSDictionary *dictRest = [NSDictionary dictionaryWithObject:sortedRestore forKey:#"Elementi"];
[listaOggetti addObject:dictDesk];
[listaOggetti addObject:dictLion];
[listaOggetti addObject:dictRest];
copyListOfItems = [[NSMutableArray alloc] init];
self.navigationItem.title = NSLocalizedString(#"TIPS", #"Tips");
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"window.png"]];
//Add the search bar
self.tableView.tableHeaderView = searchBar;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
searching = NO;
letUserSelectRow = YES;
CGRect bounds = self.tableView.bounds;
bounds.origin.y = bounds.origin.y + searchBar.bounds.size.height;
self.tableView.bounds = bounds;
}
Shouldn't it see all the object for the key #"Elementi"? I'm on it from days, i can't understand how to solve, though.
Any help appreciated
*EDIT *
I noticed that
NSDictionary *dict = [listaOggetti objectAtIndex:indexPath.section];
has only 9 elements, as well as in the first array, but i have 3 dictionaries: dictDesk, dictLion, dictRest.
How can i do to select all the 45 elements in the NSDictionary?
*EDIT 2 *
Thanks to pengOne, i finally filled a global array with my 45 elements,this way
NSMutableArray *allObjects = [[NSMutableArray alloc] init];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:0] objectForKey:#"Elementi"]];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:1] objectForKey:#"Elementi"]];
[allObjects addObjectsFromArray:[[listaOggetti objectAtIndex:2] objectForKey:#"Elementi"]];
Now all i need to do it's to adapt something like this
NSDictionary *dictionary =[listaOggetti objectAtIndex:indexPath.row];
NSArray *array = [dictionary objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row];
to the global array i've done, so it can let me search and select contents, either from tableView and SearchView.

The error tells you that you are sending this message:
[array objectAtIndex:9];
when array has 9 object, and it only responds to
[array objectAtIndex:0];
...
[array objectAtIndex:8];
The lines you need to investigate are:
NSArray *array = [dictionary objectForKey:#"Elementi"];
selectedRow = [array objectAtIndex:indexPath.row];
Check [dictionary objectForKey:#"Elementi"]. It appears to be an NSArray with 9 objects, when it needs to be an NSArray with at least 10 objects in order to access the object at index 10.
For your viewDidLoad method, it looks to me like listaOggetti is an NSMutableArray with 3 objects: dictDesk has 9 elements, dictLion has 30 elements, and dictRest has 6 elements.
To fix this error, you will need to change the number of rows in section 0 to be 9, the number of rows in section 1 to be 30 and the number of rows in section 2 to be 6.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString* cellValue=#"";
if (searching)
cellValue = [copyListOfItems objectAtIndex:indexPath.row];
else{
NSDictionary *dictionary = [listaOggetti objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Elementi"];
cellValue = [array objectAtIndex:indexPath.row];
}
if ([cellValue isEqual: #"Apps on specific Desks"] || [cellValue isEqual: #"Applicazioni su più Scrivanie"]){
AppsViewController *appsController = [[AppsViewController alloc] initWithNibName:#"AppsViewController" bundle:nil];
[self.navigationController pushViewController:appsController animated:YES];
[appsController release];
}
}

Related

Sorting keys and cellForRowAtIndexPath

I'm new to iOS programming. I have to sort my keys in my NSDictionary or more like reverse the order of my keys.
What my current keys right now are like this;
Oh! And I do not have values for my keys as they are taken out from my XML.
NSDictionary (called GradDict);
2012 S1
2012 S2
I want it to be like this;
2012 S2
2012 S1
Here are my codes to sort it;
In parserDidEndDocument:
NSEnumerator *enumerator = [gradDict keyEnumerator];
id key;
while ((key = [enumerator nextObject])) {
NSLog(#"Key:%#",key);
NSLog(#"%#", [gradDict objectForKey:key]);
}
self.sort = [key sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
In cellForRowAtIndexPath:
ModuleCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ModuleCell"];
if (!cell)
{
cell = [[[NSBundle mainBundle] loadNibNamed:#"ModuleCell" owner:nil options:nil] objectAtIndex:0];
}
NSString *period = [self.sort objectAtIndex:indexPath.section];
NSMutableArray *periodArray = [gradDict objectForKey:period];
Module *m = [periodArray objectAtIndex:indexPath.row];
[cell.moduleNameLabel setText:[m moduleName]];
[cell.moduleCreditLabel setText:[[NSString alloc] initWithFormat:#"%d", [m moduleCredits]]];
[cell.moduleGradeLabel setText:[m moduleGrade]];
cell.contentView.backgroundColor = [UIColor colorWithRed:0.75 green:0.93 blue:1 alpha:1];
[self.tableView setSeparatorColor:[UIColor colorWithRed:0.55 green:0.55 blue:0.55 alpha:1]];
return cell;
Am I doing the sorting wrongly?
And how am I to do the cellForRowAtIndexPath?
If I understand correctly you need to sort the data in the dictionary, right?
But the dictionary sorting is not saved. You can sort the keys and then create an array.

NSMutableArray- removeObject results with removing object and a nil element

Firstly, I am new with Objective C.
I have my class Song that has a pair of attributes.
In my main class i got a variable allSongs that is a NSMutableArray and in this array have I added all my song-objects.
My problem comes when trying to call [self.allSongs removeObject:OBJECT];
Using the debugger, I can see that before the call, the list looks as expected. But after the call it will result that the targeted object will be removed but also the first element in the array will turn to nil.
Is this a common pointer problem or what?
Here is my code:
in h file
#property (nonatomic, strong) NSMutableArray *songs;
#property (nonatomic, strong) NSMutableArray *allChapters;
in m file
- (void)viewDidLoad
{
self.chosenChapter = [[NSString alloc]initWithFormat:self.chosenChapter];
self.allChapters = [[NSMutableArray alloc]init];
//Chapter names and chapter page range
chapters = [[NSArray alloc]initWithObjects:#"chapter1", #"chapter2", #"chapter3", nil];
chaptersRange = [[NSArray alloc]initWithObjects:#"25", #"51", #"88", nil];
//Filnames of every song
files = [[NSMutableArray alloc] initWithObjects:#"test", #"Feta_fransyskor", nil];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: #"page" ascending: YES];
self.songs = [[NSMutableArray alloc]init];
for(int i = 0; i < chapters.count; i++){
Song *chapter = [[Song alloc]init];
[chapter setPage:(NSString *)self.chaptersRange[i]];
[chapter setTitle:(NSString *)self.chapters[i]];
[self.allChapters addObject:chapter];
[self.songs addObject:chapter];
}
NSString *filePath;
int i;
for (i = 0; i < files.count; i++) {
filePath = [[NSBundle mainBundle] pathForResource:files[i] ofType:#"txt"];
if(filePath){
NSError *error;
NSString *textFromfile = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error: &error];
/*
index
0 for page number
1 for title name
2 for melody name
3 -> for lyrics
*/
NSMutableArray *newLineseparatedText = (NSMutableArray *)[textFromfile componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
if(newLineseparatedText){
Song *newSong = [[Song alloc]init];
[newSong setPage:newLineseparatedText[0]];
[newSong setTitle:newLineseparatedText[1]];
[newSong setMelody:newLineseparatedText[2]];
[newLineseparatedText removeObjectAtIndex:0]; //remove page number
[newLineseparatedText removeObjectAtIndex:0]; //remove title name
[newLineseparatedText removeObjectAtIndex:0]; //remove melody name
[newSong setLyric:[newLineseparatedText componentsJoinedByString:#"\n"]];
[songs addObject:newSong];
}
}
}
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[super viewDidLoad];
}
-(void)addChapters{
for(int i = 0; i < self.allChapters.count; i++){
if([self.songs containsObject:self.allChapters[i]] == false)
[self.songs addObject:self.allChapters[i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: #"page" ascending: YES];
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
-(void)addChapters{
for(int i = 0; i < self.allChapters.count; i++){
if([self.songs containsObject:self.allChapters[i]] == false)
[self.songs addObject:self.allChapters[i]];
}
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]initWithKey: #"page" ascending: YES];
[self.songs sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
-(void)removeChaptersExcept:(Song *) chapter{
for(int i = 0; i < self.allChapters.count; i++){
if(self.allChapters[i] != chapter && [self.songs containsObject:self.allChapters[i]])
[self.songs removeObject:self.allChapters[i]];
}
}
last line of this code is were i get an error, as the mutableArray has a couple of nil elements.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.chosenChapter isEqualToString:#"Alla"]){
[self addChapters];
}
else{
Song *chapter = nil;
for(int i = 0; i < self.allChapters.count; i++){
if([((Song *)self.allChapters[i]).title isEqualToString:self.chosenChapter]){
chapter = self.allChapters[i];
break;
}
}
[self addChapters];
[self removeChaptersExcept:chapter];
}
NSString *cellIdentifier = nil;
UITableViewCell *cell = nil;
NSString *page = ((Song *)self.songs[indexPath.row]).page;
and here are some screen bumps
This is before removing first object
This is after the first object was removed. You see how one element disapeared as expected and the other is set too nil?
Sometimes the Variables View shows incorrect values.
An array can't contain nil values, so this is definitely a case where the values are wrong.
You state that your application crashes on this line:
NSString *page = ((Song *)self.songs[indexPath.row]).page;
My guess is that self.songs[indexPath.row] simply doesn't have a property called page.
Try to replace this line with this code:
Song *s = self.songs[indexPath.row];
if (s == nil)
{
NSLog("Song is nil! How can that be?");
}
else
{
NSLog("Page is %#", s.page);
}
It will help you pin-point the problem. Good luck.

Error: index 1 beyond bounds [0 .. 0]

I am a rookie in Xcode and I have been using the UITableViewController which shows this error.
This is the error message:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
* First throw call stack:
(0x1c91012 0x10cee7e 0x1c330b4 0x36d0 0xc58d5 0xc5b3d 0xacce83 0x1c50376 0x1c4fe06 0x1c37a82 0x1c36f44 0x1c36e1b 0x1beb7e3 0x1beb668 0x1665c 0x2132 0x2065)
libc++abi.dylib: terminate called throwing an exception
(lldb)
This is my code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row0"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while ( objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
if (indexPath.row == 1) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row1"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while (objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
if (indexPath.row == 2) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row2"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while ( objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
if (indexPath.row == 3) {
NSString *strURL = [NSString stringWithFormat:#"http://localhost:8888/GetDetail.php?choice=row3"];
NSArray *arrayImagesNames = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:strURL]];
arrayDataFromServer2 = [[NSMutableArray alloc]init];
NSEnumerator *enumForNames = [arrayImagesNames objectEnumerator];
id objName;
while ( objName = [enumForNames nextObject]) {
[arrayDataFromServer2 addObject:[NSDictionary dictionaryWithObjectsAndKeys:objName, #"name", nil]];
}
NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
row1 = [nn intValue];
NSLog(#"%d", row1);
CompanyProfileViewController *profile = [self.storyboard instantiateViewControllerWithIdentifier:#"Profile"];
[self.navigationController pushViewController:profile animated:YES];
profile.profileid = row1;
NSLog(#"%d", profile.profileid);
}
}
When I click on the second cell (index.row == 1) this error would occur.
I have used breakpoint and the error was on the line:
"NSString *nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];"
Please Help!
Swift 4
after more time i am get the love for this Error 😄
when you use the tableView from the storyboard and implementing in your code :
hint that and compare :
between the number of section and numberOfRowsInSection == storyboard and code
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 3
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
You have an array and you have either 0 or 1 elements in it. Now you are trying to extract 2nd element from it, [0] is first, and [1] is second.
EDIT:
As you are not sure when the array will contain 1 or more objects. Therefore you can use as:
NSString *nn=nil;
if([arrayDataFromServer2 count]>1){
nn = [[arrayDataFromServer2 objectAtIndex:indexPath.row] objectForKey:#"name"];
}

cancel button on search bar does not cancel correctly

I have a search bar, i can search now, but when I enter a text to search, and click the cancel button. It does not give me back my first stage, meaning full of the items in the table.
For example: I search the item with word: a, it gives me all the a items, yes, it is right now, but when i hit the cancel button, i want the programme gives me all the items exist, not just a items.
Here is the code: please help me out. Thank you so much.
- (void)searchBarCancelButtonClicked:(UISearchBar *)aSearchBar
{
searchBar.text = #"";
[searchBar resignFirstResponder];
letUserSelectRow = YES;
searching = NO;
self.tableView.scrollEnabled = YES;
NSLog(#"what text after cancel now: %#", searchBar.text);
[self.tableView reloadData];
}
- (NSMutableArray *) searchTableView {
NSString *searchText = searchBar.text;
NSLog(#"search text: %#", searchText);
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSMutableArray *tempArr = [[NSMutableArray alloc] init];
for (NSDictionary *dTemp in arrayData)
{
NSString *tempStr = [dTemp objectForKey:#"url"];
NSLog(#"sTemp string: %#",[ NSString stringWithFormat:#"%#", tempStr]);
NSRange titleResultsRange = [tempStr rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
NSLog(#"1 count :%d", [resultArray count]);
[resultArray addObject:dTemp];
NSLog(#"2 count :%d", [resultArray count]);
[tempArr addObject:resultArray];
[resultArray release];
resultArray = [NSMutableArray new];
}
}
if (resultArray != nil) {
[resultArray release];
}
return tempArr;
}
- (void)searchBar:(UISearchBar *)aSearchBar textDidChange:(NSString *)searchText
{
NSLog(#"what text after cancel now: %#", searchBar.text);
if([searchText length] > 0) {
[sortedArray removeAllObjects];
searching = YES;
letUserSelectRow = YES;
self.tableView.scrollEnabled = YES;
NSMutableArray *searchArray = [self searchTableView];
sortedArray = [[NSMutableArray alloc] initWithArray:searchArray copyItems:YES];
for (int i = 0; i<[sortedArray count]; i++) {
NSLog(#"this is the search array: %#", [[sortedArray objectAtIndex:i] class]);
}
NSLog(#"sorted array: %d", [sortedArray count]);
}
else {
searching = NO;
letUserSelectRow = NO;
self.tableView.scrollEnabled = NO;
}
[self.tableView reloadData];
}
You don't need to override any of UISearchBar methods to accomplish this. The new way of doing this relies on the UISearchDisplay controller instead (specifically on shouldReloadTableForSearchString).
Declare your view controller to conform to UISearchDisplayDelegate protocol, and keep two instance variables: your model as NSArray (all data) and a filtered array as NSMutableArray (a subset of your data). The code you presently have in "searchTableView" would filter the content of the model and place it into the filtered NSMutableArray. Then you would override the following UITableView methods: -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section and -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath. In each, before returning, make a comparison to determine whether your tableView argument is equal to self.searchDisplayController.searchResultsTableView. If it is, the user is looking at the filtered list and your should use the content of the filtered NSMutableArray to create the view, otherwise, the user is looking at the whole data set and you should use the content of the NSArray that holds your model. Take a look at the following Apple code for a simple example of what I described:
http://developer.apple.com/library/ios/#samplecode/TableSearch/Introduction/Intro.html

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.