UICollectionView Assertion failure in deleteItemsAtIndexPaths - iphone

Here is my error:
*** Assertion failure in -[PSUICollectionView _endItemAnimations], /SourceCache/UIKit_Sim/UIKit-2372/UICollectionView.m:2801
I'm calling it like this:
[self.collectionView deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForItem:1 inSection:1]]];
Why is this happening, any ideas?

Do you remove the item from your model as well? So, for example, if the number of rows, sections and the content they present is taken from a dictionary of arrays whose keys represent the sections and each array the rows, then if you delete one row with deleteItemsAtIndexPaths you're responsible to update the dictionary accordingly. UICollectionView will not do it for you.

Note that you are trying to delete index 1 from section 1. Both index and section starts at 0.
i did it like this:
NSMutableArray *forms; // datasource item data for all the cells
int indexToDelete; // Set to the index you want to delete
...
[self.collectionView performBatchUpdates:^(void){
[forms removeObjectAtIndex:indexToDelete]; // First delete the item from you model
[self.collectionView deleteItemsAtIndexPaths:#[[NSIndexPath indexPathForRow:indexToDelete inSection:0]]];
} completion:nil];

Check that your collection view is not busy with something else when you call deleteItemsAtIndexPaths: .
I experienced the same problem with insertItemsAtIndexPaths: method, and it turned out that it was caused by a bug in my code - I called [myCollectionView insertItemsAtIndexPaths:] immediately after calling [my collectionView reloadData] . So, at the moment of calling insertItemsAtIndexPaths: my collection view was reloading its data. After I fixed this bug, the problem with assertion failure has gone.

Related

App crashes when adding names to UIPickerView

When I click a button, a UIAlertView prompts the user to type a name. This name is then created as a new 'Customer' object and inserted into a mutable array.
There is a separate mutable array called 'CustListByName', which stores a list of all names.
The problem im having is that when adding a second or third name, the app crashes. Sometimes it happens on the second try, other times on the third try. There is no information given in the debugger except for (lldb). The program reports EXC_BAD_ACCESS and then it dumps me to a screen with a bunch of assembly code.
The crash is happening in these lines of code:
Essentially, it clears the array of names and then repopulates it based upon the object array. I've studied in step by step with a breakpoint but everything seems correct up until the point of crash. It is also confusing why this happens on the second or third try, never the first.
[custListByName removeAllObjects];
for (Customer *object in custListByObject) {
[custListByName addObject:object->name];
}
Here is the code where a customer is created and inserted everytime the new customer button is clicked:
Customer *tempCust = [[Customer alloc] init];
tempCust->name =[[alertView textFieldAtIndex:0] text];
[custListByObject addObject:tempCust];
[tempCust release];
I would really appreciate help with this, thanks!
What I suspect is happening is that the UIPickerView is attempting to load a row using information from your customer array after you have already cleared it, and before you repopulate it. This would cause a bad access error.
What you may consider doing instead, is keeping two arrays, an NSMutableArray for loading the customers, and an NSArray as the actual data source for the UIPickerView. Then right before you reload the UIPickerView, you say:
dataSourceArray = [loadingArray copy];
[pickView reloadAllComponents];
Hopefully this helps.
Edit:
Here's what your updated code would look like if your loading array was called loadingCustListByName:
[loadingCustListByName removeAllObjects];
for (Customer *object in custListByObject) {
[loadingCustListByName addObject:object->name];
}
custListByName = [loadingCustListByName copy];
[pickView reloadAllComponents];
Doing this will ensure that the UIPickerView's datasource array always matches up with the number of rows it thinks it has.

ios - NSLog showing that detailedView is not displayed in the right order

I am trying to pass data from one ViewController to another using storyboard.
Please note this log message:
2012-11-13 22:25:41.711 Modern Notes[8991:15d03] DetailView - (null)
2012-11-13 22:25:41.714 Modern Notes[8991:15d03] MainView - {
CurrentDate = "2012-11-13 05:12:46 +0000";
NoteInString = "This is the first note. It will appear here while testing the app.";
}
You will see that DetailView - has nothing and that MainView show the contents off an array.
The Array is passed on from the MainView. Now both log Messages are generated by this line:
NSLog(#"DetailView - %#", _notedict);
and
NSLog(#"MainView - %#", noteDetailViewControler.notedict);
Where notedict is the Dictionary that holds the information. As you can see (i think) in theory both Log messages should display this array right??
Now it seems strange to me that DetailView is being shown in the Log before MainView where I think it should be the other way around??
Cheers for any tips and happy to provide any details if needed.
EDIT:
ok, so this is where I am sorting my details out:
in the method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
I have a line
noteDetailViewControler.notedict = [_listNotes objectAtIndex:indexPath.row];
Now I think my problem is that this line is only set locally and is not carried over to another viewcontroller - am I right??
Obviously _notedict is not yet set, or already removed again, when you log it in the DetailView. You need to show us, when (in which method) you initalize the data, when you log it and when you show the mainView / detailView. We can not not help anymore with the information given right now.

Last item in UITableView unreachable with textLabel.text

I'm populating a UITableView with an array of items I retrieve from the interwebs.
The code in question selects an item from a list populated from an array from the interwebs, then sends a request back to a different php script->sql table etc based on the item selected. The issue i'm having is the entire list is populating correctly, but when using the last item in the list/tableview the array.textLabel.text is apparently.. non existant. Everything sends off fine, but this one last item (doesnt matter how many items i have in the array the very last one just doesnt ... remain or something) and it selects nothing.
Then when sending the 2nd request, it gives me an out of bounds error because the last item doesn't exist and it says im trying to pull something thats not there.
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSArray objectAtIndex:]: index 1 beyond bounds [0 .. 0]'
This is how it makes the array it uses to populate:
NSArray *listItems = [parsedOutput componentsSeparatedByString:#","];
restList = [[NSArray alloc] initWithArray:listItems];
the row count is based on [restList count]; etc.
and to call the text I use:
restName = [tableView cellForRowAtIndexPath:indexPath];
sendName = restName.textLabel.text;
Any idea why the very last element doesn't seem to exist even though its listing and selectable?
The error tells you exactly what's happening. You are attempting to access an index that is outside the bounds of the array. So either you are accessing the wrong array or you are accessing 1 past the actual end of the array. Try to NSLog the array just before the line the error comes up and see if it indeed has the right elements in it as well as output index.row you are trying to access keeping in mind that arrays are zero-indexed.

why does "numberOrRowsInSection" get called mid-way through "viewDidLoad"?

BACKGROUND:
Within my viewDidLoad I am loading test calendar data (via EventKit) to the iPhone. I am noting that when the table view loads the first time it does not see this data.
When I look at the sequence of log messages I see that it goes something like this:
Logging here:
[AppointmentListController viewDidLoad] Starting
[AppointmentListController populateTestData] Populating the test data now
[AppointmentListController tableView:numberOfRowsInSection:] Number of rows = 0
[AppointmentListController viewDidLoad] Loading the existing calendar events
[AppointmentListController viewDidLoad] Ending
QUESTION(S)
Why does "numberOrRowsInSection" get called mid-way through "viewDidLoad"? I ask this as this is what I am seeing (is this what should happen?).
If this is normal that you can't be sure viewDidLoad will complete before numberOrRowsInSection, then this would imply you need a "[self.tableView reloadData]" at the end of your "viewDidLoad" method to make sure it does update?
The tableView:numberOfRowsInSection: method is likely called because you configured something on your table view (maybed you've added it to its superview) and it therefor needed to know its metrics. It does not magically trigger by itself out of the blue. Either make sure to prepare your data before you configure the UI elements or call reloadData near the end, but I'd find the former to be "cleaner".
This is perfectly normal....
Call [self.tableView reloadData]
; at the end of viewdidload

NSFetchedResultsController not updating UITableView's section indexes

I am populating a UITableViewController with an NSFetchedResultsController with results creating sections that populate section headers and a section index. I am using the following method to populate the section index:
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [fetchedResultsController_ sectionIndexTitles];
}
and now I've run into a problem. When I add a new element to the NSManagedObjectContext associated with the NSFetchedResultsController, the new element is saved and appropriately displayed as a cell in the UITableView ... except for one thing. If the new element creates a new SECTION, the new section index does not show up in the right hand margin unless I pop the UINavigationController's stack and reload the UITableViewController.
I have conformed to the NSFetchedResultsControllerDelegate's interface and manually invoke
[self.tableView reloadSectionIndexTitles];
at the end of both these delegate methods:
controller:didChangeSection...
controller:didChangeObject...
and while I can debug and trace the execution into the methods and see the reload call invoked, the UITableView's section index never reflects the section changes.
Again, the data shows up - new sections are physically visible (or removed) in the UITableView but the section indexes are not updated.
Am I missing something?
Looks like this is a bug we're all having. See http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html for what looks to me like a fairly nasty too-many-lines-of-code solution. I went with this:
- (void)viewWillAppear:(BOOL)animated; {
// This is a dumb hack required by this bug: http://iphonedevelopment.blogspot.com/2009/11/i-know-youre-tired-of-hearing-about.html
[self.tableView reloadData];
}
It may be inefficient but unless you have reams and reams of data it probably won't do any harm. And it's only 1 line of code. So, when apple fixes their bug, you can easily take it out.
Question already 2 months old, but I ran into the same problem today. It seems like -reloadSectionIndexTitles is not working at all, so I tried a couple of potential hacks which of the following works for me:
#implementation UITableView (JKAdditions)
- (UIView *)indexView {
Class indexClass = NSClassFromString(#"UITableViewIndex");
for(UIView *subview in self.subviews){
if([subview isKindOfClass:indexClass]) return subview;
}
return nil;
}
- (void)reloadSectionIndexTitles {
UIView *indexView = [self indexView];
[indexView performSelector:#selector(setTitles:) withObject:[self.dataSource sectionIndexTitlesForTableView:self]];
[indexView setNeedsDisplay];
}
#end
I really have no idea if Apple would reject your App because of this hack, but it seems like the only option for me. Reloading the whole tableView is simply not what I want since I then have to deal with all kinds of animation problems.
I hope this helps anyone having the same problems!
To combine the accepted answer with Alex Reynolds's answer with the delay, just call reloadData with a delay that corresponds to the animation duration, so 0.4 or 0.3 seconds.
In my case, I stick the delayed method call into controller:didChangeSection:atIndex:forChangeType: (it's a Core Data app).
The result, when a section is added or deleted, is the standard animation of the cell, followed by the index being updated when the data is reloaded.
It's ugly and makes me cringe, but I am okay with the result. I also submitted a bug to Apple, #8589547.
Try putting it at the end of -controllerDidChangeContent:, somewhere after [self.tableView endUpdates].
Another thing I do (that works for me, can't guarantee it will work for you) is perform a selector after a very short delay, e.g.:
[self performSelector:(#selector(refreshSectionIndex)) withObject:nil afterDelay:0.2];
// ...
- (void) refreshSectionIndex {
[self.tableView reloadSectionIndexTitles];
}
Core Data and NSFetchedResultsController in particular seem buggy as hell, where delegate table view updates get out of sync with the fetched data, causing the application to crash. I really hope Apple is taking steps to fix the bugs in these frameworks in the 4.0 SDK. It's pretty frustrating.