I am using an NSArray to load objects into my UICollectionView. The UICollectionView has a UIPageViewController associated with it where I am grabbing the index for each page. Depending on what page you are on, I want to load different objects.
I try to do that using the following:
NSDictionary *dictionary = [[NSDictionary alloc] init];
if (self.index == 0) {
dictionary = [self.imageArray objectAtIndex:indexPath.row];
} else if (self.index == 1) {
dictionary = [self.imageArray objectAtIndex:12 + indexPath.row];
NSLog(#"%#", self.imageArray);
} else if (self.index == 2) {
dictionary = [self.imageArray objectAtIndex:24 + indexPath.row];
}
Where self.index is the page you are on.
However, I keep getting the following crash:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 48 beyond bounds [0 .. 47]'
However, my array does have 48 objects. There are 12 objects loaded on each page.
Does it have anything to do with me setting the dictionary each time? Only thing I could think of....
Help would be appreciated.
Instead of using those ugly ifs and twisted logic, try to structure your model better. One way of doing this would be to have an array of arrays: each page an array of images. You'd know the pages count from the model and accessing the right image would be as simple as self.images[self.index][indexpath.row] You could also use an UIcollectionview with each page a section.
Related
I am trying to create a dynamic top menu.
I have to get some data from a json request and display this data in one of the sections of the top menu. I'm new in Objective-C. I also tried with NSMutableArrays and I had an error. Only one MutableArray and I can show the top menu. I am following this third party framework for top menu “https://github.com/dopcn/DOPNavbarMenu”.
- (DOPNavbarMenu *)menu {
if (_menu == nil) {
[strArray objectAtIndex:0];
NSLog(#"Random Selection is:%#",strArray);
_menu = [[DOPNavbarMenu alloc] initWithItems:#[strArray] width:self.view.dop_width maximumNumberInRow:_numberOfItemsInRow];
_menu.backgroundColor = [UIColor blackColor];
_menu.separatarColor = [UIColor whiteColor];
_menu.delegate = self;
}
return _menu;
}
-(void)loadData
{
strResponse=[dictionary objectForKey:#"data"];
strMsg=[strResponse valueForKey:#"Text"];
NSLog(#“string message is :%#",strMsg);
NSLog(#"String Response is :%#",strResponse);
NSLog(#"Text Response is: %#",strMsg);
strArray = [[NSMutableArray alloc] init];
[strArray addObject:strMsg];
NSLog(#"Array values are - %#", strArray);
}
Array values are: Life Style,Care Plans,Trackers/Diaries,Questionnaires/Assessments.
but i got exception like this:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
Ok, per your comment
but i want to call menu method before loadData finishes
the issue lies here :
_menu = [[DOPNavbarMenu alloc] initWithItems:#[strArray] width:self.view.dop_width maximumNumberInRow:_numberOfItemsInRow];
Before loadData is run, I assume that strArray is nil. This causes this part #[strArray] to fail - this creates a new array with strArray as its only element, which cannot be nil.
I also assume that you wanted to rather pass strArray itself there, not wrap it in another array.
Now, if you call menu before populating strArray in loadData, there will likely be no items present in the menu, unless you have a way to update it with new items after loadData finishes.
To summarise : to fix your immediate issue, you should change the above line to this :
_menu = [[DOPNavbarMenu alloc] initWithItems:strArray width:self.view.dop_width maximumNumberInRow:_numberOfItemsInRow];
which should work, but there won't be any items present in the menu, because of reasons explained above.
I noticed a strange difference in how performBatchUpdates:completion: method of UICollectionView works in iOS7 (bad - crashes) and iOS8 (good). Here's the code I use:
[self.swapItems removeObject:self.swapItems[indexPath.row]];
[self.swapItemsGrid performBatchUpdates:^{
[self.swapItemsGrid deleteItemsAtIndexPaths:#[indexPath]];
} completion:^(BOOL finished) {
[self layoutViews];
}];
In iOS8 it works fine, while in iOS7 it crashes with the following error:
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
A little debugging has shown that in iOS8 the performBatchUpdates:completion: method calls the data source method collectionView:numberOfItemsInSection:, while in iOS7 it doesn't, hence the error where a cell is attempted to be created with the data of an object that is in the data array no more.
Has anyone else run into this issue? Perhaps you have a solution in mind?
self.swapItemsGrid might does not have item at index indexPath.
To avoid this, use this to check indexPath exits in array or not:
-(BOOL)checkIndexPathExits:(NSIndexPath*)indexPath inArray:(NSArray*)array{
if (indexPath.section < array.count) {
if (indexPath.row < [array[indexPath.section] count]) {
return YES;
}
}
return NO;
}
Hope this could help.
Scenario = I have a PFQueryTableViewController that needs different sized cells at each indexPath depending upon values returned from the query. If the image is "Landscape size" that would be one size, and if its "Portrait size" than that is another.
1) I create a NSMutableArray in .h file to hold the sizes.
#property (strong, nonatomic) NSMutableArray *rowHeightArray;
2) For each objects I check for the value in cellForRowAtIndexPath and add it to the array.
if ([object[#"orientation"] isEqual:#"left"] || [object[#"orientation"] isEqual:#"right"]) {
[rowHeightArray addObject:[NSNumber numberWithFloat:378]];
}
else {
[rowHeightArray addObject:[NSNumber numberWithFloat:488]];
}
(there are more than just these two possibilities but I think that is enough to get the point across)
ISSUES
3) Now I need to place the correct height to the correct cell. Problem is when I try...
return self.rowHeightArray[indexPath.row];
In heightForRowAtIndexPath it "yells" at me with:
returning 'id' from a function with an incompatible result type 'CGFloat' (aka 'float')
and alternatively I also tried
return [self.rowHeightArray[indexPath.row]floatValue]
this stops "yelling" at me but when i try to run this it errors out:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
Question = How do I accomplish what I'm trying to do here and have it 'work'?
Two problems:
heightForRowAtIndexPath: is called before cellForRowAtIndexPath:. So your current approach is calculating the height too late. You need to calculate it in heightForRowAtIndexPath: or earlier (in viewDidLoad, or when your PFQuery finishes, for example).
You're returning an NSNumber object not a CGFloat. You need to unbox it:
NSNumber *heightNumber = self.rowHeightArray[indexPath.row];
return [heightNumber floatValue];
Of course this won't work with your current implementation, since (as rmaddy points out) self.rowHeightArray is empty. So if you want to use this array, you need to make sure it's populated before heightForRowAtIndexPath: gets called.
To elaborate on #AaronBrager's correct answer, load, then build the float array before the datasource gets called. This can be done in the hook the PFTable vc gives you called. To answer your question in comments, there's no need for the indexPath, since we know that the self.objects array indexes, the indexes you build here, and the indexes passed to the datasource method will all correspond (0..self.objects.count-1):
- (void)objectsDidLoad:(NSError *)error {
self.rowHeightArray = [NSMutableArray array];
for (PFObject *object in self.objects) {
NSString *orientation = object[#"orientation"];
NSNumber *height;
if ([orientation isEqualToString:#"left"] || [orientation isEqualToString:#"right"]) {
height = #378.0;
} else {
height = #488.0;
}
[self.rowHeightArray addObject: height];
}
[super objectsDidLoad:error];
}
hi i am new to iphone programing,i am using EGOPhotViewer and want to show images by using this code,
for ( recipeImages in recipeImages.imgArray) {
photo = [[MyPhoto alloc] initWithImageURL:[NSURL URLWithString:recipeImages.recipie_img_url]name:recipeImages.recipe_name];
NSLog(#"%#",recipeImages.recipie_img_url);
MyPhotoSource *source = [[MyPhotoSource alloc] initWithPhotos:[NSArray arrayWithObjects:photo ,nil]];
photoController = [[EGOPhotoViewController alloc] initWithPhotoSource:source];
}
[APPDELEGATE.navigationController pushViewController:photoController animated:YES];
and i get this error
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2147483648 beyond bounds [0 .. 0]'
*** First throw call stack:
(0x225f012 0x2084e7e 0x2214b44 0x9e1e4 0xa46c4 0x1b45dc9 0x22b90c5 0x2213efa 0x1a7a482 0x1a8d73b 0xa9d7c 0xa6a4e 0xa5081 0xa0499 0x10af753 0x10afa7b 0x10bd590 0x10c55bd 0x10c5eab 0x10c64a3 0x10c6098 0x5bad6 0x2098705 0xfcf920 0xfcf8b8 0x1090671 0x1090bcf 0x108fd38 0xfff33f 0xfff552 0xfdd3aa 0xfcecf8 0x2c15df9 0x2c15ad0 0x21d4bf5 0x21d4962 0x2205bb6 0x2204f44 0x2204e1b 0x2c147e3 0x2c14668 0xfcc65c 0x263a 0x2545)
libc++abi.dylib: terminate called throwing an exception
i solved this by writing this code
NSMutableArray *localImagesArray = [[NSMutableArray alloc] init];
for ( recipeImages in recipeImages.imgArray) {
photo = [[MyPhoto alloc] initWithImageURL:[NSURL URLWithString:recipeImages.recipie_img_url]name:recipeImages.recipe_name];
NSLog(#"%#",recipeImages.recipie_img_url);
NSLog(#"%#", [photo debugDescription]);
[localImagesArray addObject:photo];
}
MyPhotoSource *source = [[MyPhotoSource alloc] initWithPhotos:localImagesArray];
photoController = [[EGOPhotoViewController alloc] initWithPhotoSource:source];
[APPDELEGATE.navigationController pushViewController:photoController animated:YES];
}
[__NSArrayI objectAtIndex:]: index 2147483648 beyond bounds [0 .. 0]'
2147483648 is NSNotFound. Somewhere in your code, or the code of a library you are using, something like indexOfObject: is being used on one array, and that index is being used to get a value from another array, and it is failing.
Your for loop looks very suspect. You're assigning a value to photoController at the end of each iteration, meaning only the value you assign last will actually get used. I'm not familiar with the library you're using but you probably want to be building up an array of MyPhoto objects before passing them to a single photoController.
Make sure initWithImageURL: name: inside MyPhoto returns self.
Verify this with NSLog(#"%#", [photo debugDescription]);
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
index 0 beyond bounds for empty array error
I am a hobbyist in iOS programming. And I always have the same problem while programming.
I think that I don't understand the memory management issue.
This is my actual project:
h-File:
a NSMutableArray containing NSStrings
NSMutableArray *pictureStrings;
#property (nonatomic,retain) NSMutableArray *pictureStrings;
in the m-File:
#synthesize pictureStrings;
and in the viewDidLoad Method
pictureStrings = [[NSMutableArray alloc] init];
in the dealloc Method
[pictureStrings release];
okay. I am working with an asynchronous URL Request which gets a number of strings and in the connectionDidFinishLoading Delegate Method the values get stored to pictureStrings
[pictureStrings addObject:aString];
BUT
when I read values in the cellForRowAtIndexPath Method like
if (pictureStrings != nil) {
cell.textLabel.text = [NSString stringWithFormat:#"%#", [pictureStrings objectAtIndex:indexPath.row]];
}
my App crashes with the message:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array'
Where is my fault?
Please help me!
Yours, Raphael.
Greetings from Austria
Your crash is not a memory management issue. Your crash is that you're reading past the end of an array. We know that pictureStrings is non-nil at that point, because if it was nil then the objectAtIndex: method would have silently just returned nil (because messaging nil returns nil [1]). Oh and not to mention you have the if around the call to objectAtIndex: anyway - but you can safely remove that really as you shouldn't need it.
So, the only thing that can really be happening here is that your [pictureStrings addObject:aString] are not being called before the table view is reloaded. However, that would be quite odd because I assume you are doing something like return pictureStrings.count in the table view's tableView:numberOfRowsInSection: data source method. If there really were zero elements in the array then the table view wouldn't be asking for any rows and you wouldn't get this crash.
I think your problem is likely to be that you're not adding the strings to the array. You could check by breakpointing that code and seeing what is happening.
Also, consider changing your code to set the cell's text to this:
cell.textLabel.text = [pictureStrings objectAtIndex:indexPath.row];
You said they are already strings so why bother going through a stringWithFormat: call?
[1] Caveat: Doesn't always return nil - read up about it for more information.