UICollectionView's performBatchUpdates crash iOS7 - ios

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.

Related

Load Specific Part of NSArray in UICollectionView

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.

Casting tableViewCell as UIPickerView exactly how it is done with UIDatePicker for inline date picker not working

I am attempting to use an inline PickerView in my application, and it works fine except for one thing. when I try to set the row of the picker to a specific row based on a data argument my application crashes.
UITableViewCell *associatedTypePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];
UIPickerView *targetedPickerView = (UIPickerView *)[associatedTypePickerCell viewWithTag:kTypePickerTag];
if (targetedPickerView != nil){
NSLog(#"type picker ! = nil");
NSDictionary *itemData = self.dataArray[self.datePickerIndexPath.row-1];
Type *type = [itemData valueForKey:kDateKey];
NSInteger row = [[self types] indexOfObject:type];
[targetedPickerView selectRow:row inComponent:0 animated:NO];
}
I am getting this error:
-[UITableViewCell selectRow:inComponent:animated:]: unrecognized selector sent to instance 0x8ecba70
2014-07-22 23:47:23.384 MyGIJournal[16636:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITableViewCell selectRow:inComponent:animated:]: unrecognized selector sent to instance 0x8ecba70'
does anyone know why this is crashing? it seems like casting like this to a UIPickerView isn't working, which doesn't make much sense cause this is the exact same way I do it for the UIDatePicker and it worked for that... Any help or advice would be greatly appreciated, Thanks!

A strange UITableView crash : NSRangeException

I have encountered a strange crash on my code.
Here's the code :
UIView *tableHeaderView = self.tableView.tableHeaderView;
CGRect frame = tableHeaderView.frame;
frame.size.height = 0;
tableHeaderView.frame = frame;
self.tableView.tableHeaderView = tableHeaderView;
The crash occurred on the last line of the code.
And, here is the log
Terminating app due to uncaught exception 'NSRangeException', reason:
'*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(0x345ae2a3 0x3c25397f 0x344f9b75 0x1a7055 0x363ebb8f 0x363d702b 0x363d7599 0x363d740d 0x3642b22b 0x1a0d77 0x363d5595 0x3642a14b 0x3642a091 0x36429f75 0x36429e99 0x364295d9 0x364294c1 0x364764d1 0x36428861 0x36428713 0x364a4399 0x364508fb 0x36691619 0x364a39b9 0x364a1fe7 0x26c8a1 0x221997 0x34ee96fd 0x34e291f9 0x34e29115 0x3428b45f 0x3428ab43 0x342b2fcb 0x344f474d 0x342b342b 0x3421703d 0x34583683 0x34582ee9 0x34581cb7 0x344f4ebd 0x344f4d49 0x380b82eb 0x3640a301 0x10819f 0x3c68ab20)
libc++abi.dylib: terminate called throwing an exception
I really don't have any idea what happened on my code.
Any advice are helpful for me!
Thank you.
You definitely initialise some array in your class firstly check your array by placing NSLog that it should have some value or it is null. I think it is null thats why they creating a problem.
If you want to change the headerView for a table, this is the proper way to do it:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *headerView = [[UIView alloc] initWithFrame:kHeaderFrame];
return headerView;
}

Getting "unrecognized selector sent to instance" error message on 1 of 4 background image loads within same code?

I have created 4 buttons named cell1, cell2 cell3 and cell4
I am attempting to set the background image in the following for loop.
Cells 1, 2 and 4 load successfully with the background image.
I received the following message for cell3.
All cells were created the same, the tag for each button was set 1, 2, 3 and 4.
I am a loss as to why cell3 (button) does not load. I have reviewed similar previously answered question on this topic but am drawing a blank.
Here is the code that is failing:
for (int i = 1; i <= 4; ++i) {
UIButton *cellIndex = (UIButton *)([self.view viewWithTag:i]);
NSLog(#"==> viewDidLoad cellIndex1 = (%i)", cellIndex.tag);
[cellIndex setBackgroundImage:[UIImage imageNamed:#"L0background.png"] forState:UIControlStateNormal];
}
Here is the results for the background load:
2013-08-30 09:50:07.898 match[863:11f03] ==> viewDidLoad cellIndex1 = (1)
2013-08-30 09:50:07.899 match[863:11f03] ==> viewDidLoad cellIndex1 = (2)
2013-08-30 09:50:07.899 match[863:11f03] ==> viewDidLoad cellIndex1 = (3)
2013-08-30 09:50:07.900 match[863:11f03] -[UIView setBackgroundImage:forState:]: unrecognized selector sent to instance 0x7d68230
2013-08-30 09:50:07.901 match[863:11f03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView setBackgroundImage:forState:]: unrecognized selector sent to instance 0x7d68230'
*** First throw call stack:
(0x1912012 0x1695e7e 0x199d4bd 0x1901bbc 0x190194e 0x27bf 0x6bb1c7 0x6bb232 0x60a3d5 0x60a76f 0x60a905 0x613917 0x22f5 0x5d7157 0x5d7747 0x5d894b 0x5e9cb5 0x5eabeb 0x5dc698 0x277ddf9 0x277dad0 0x1887bf5 0x1887962 0x18b8bb6 0x18b7f44 0x18b7e1b 0x5d817a 0x5d9ffc 0x202d 0x1f55 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Your cellIndex is declared inside the for loop. Its local to the for loop. You are trying to set a background image outside the for loop where it has no knowledge of cellIndex object. Have you declared a cellIndex object outside that for loop?
If not, then you will have to set the background image inside your for loop.
The problem is clear: [self.view viewWithTag:i]) is returning an UIView instead of an UIButton when i is 3.
You can verify that yourself by adding NSLog(#"Returned view: %#", cellIndex) just below that line. This log will also show which view is returned. You can then use that information to identify the culprit. I suspect that there's another view in the view hierarchy with 3 as tag. Double-check your XIBs/Storyboards to make sure the only view that has 3 as its tag is your button.
Like the others have said, UIView does not respond to the method in question. The object at index 4 is not a UIButton.
To help guard against this crash, do this:
UIButton *buttonObject;
for (int i = 1; i <= 4; ++i) {
id cellIndex = [self.view viewWithTag:i];
if ([cellIndex isKindOfClass:[UIButton class]]) {
buttonObject = (UIButton *)cellIndex;
NSLog(#"==> viewDidLoad cellIndex1 = (%i)", cellIndex.tag);
[buttonObject setBackgroundImage:[UIImage imageNamed:#"L0background.png"] forState:UIControlStateNormal];
} else {
NSLog(#"Not a button, returned %#",[cellIndex class]);
}
}

When i click an item in my collection view i got this error

I have a collectionview but when i tried to click the image the it showing this error ? The whole application is a tabbar application ,so all other tabs are working . except the last tab images.
iam taking images from plist for displaying it into collectionview
this is error
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI
objectAtIndex:]: index 0 beyond bounds for empty array'*** First throw call stack: (0x1e92012
0x1969e7e 0x1e47b44 0x58b91 0x56686 0x137cf 0x98f1c7 0x98f232 0x98f4da 0x9a68e5 0x9a69cb 0x9a6c76
`0x9a6d71 0x9a789b 0x9a7e93 0x9a7a88 0xd03e63 0xcf5b99 0xcf5c14 0xdaf5d9 0xdc1182 0xdc1394 0x197d705
0x9bb93c 0x9bb9ac 0x197d705 0x9bb93c 0x9bb9ac 0xb751d3 0x1e5aafe 0x1e5aa3d 0x1e387c2 0x1e37f44
0x1e37e1b 0x3c0f7e3 0x3c0f668 0x8adffc 0x287d 0x27a5) libc++abi.dylib: terminate called throwing an exception
This is the didselect method and preparesegue for passing that array to another viewcontroller
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"bookItem"]) {
NSDictionary *currentBook = [[_freeBooks objectForKey:#"freebook"] objectAtIndex:[[[self.collectionView indexPathsForSelectedItems] objectAtIndex:0] row]];
NSLog(#"%#", currentBook);
GMMDetailpage *detailpage = (GMMDetailpage *)[segue destinationViewController];
detailpage.bookDetails = currentBook;
NSLog(#"%#",detailpage.bookDetails);
}
}
The value of current book is printing and its fine.... but after this it executes some other system codes and then it shows exception .check image
You are doing two array accesses, so the error comes from the fact that one of the two arrays is empty.
The two arrays are
[self.collectionView indexPathsForSelectedItems]
and
[_freeBooks objectForKey:#"freebook"]
Check both the array independently and find out which one is the empty one.

Resources