Last item in UITableView unreachable with textLabel.text - iphone

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.

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.

UICollectionView Assertion failure in deleteItemsAtIndexPaths

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.

Problem with NSManagedObjectContext crashing app

I have a navigation based app that uses Core Data for storage. The schema for this particular section is as follows:
Scene hasMany Tasks hasMany DeviceCommands
Tasks also have many other objects besides DeviceCommands (like DelayCommands etc), but this is beyond the scope of the problem (I think).
DeviceCommands also link to a parent object as follows:
Device hasMany DeviceCommands
Now, the user can create a new Task, which pops up a modal view to select the Device. When you select a device, a tableview is pushed with the DeviceCommands that belong to the Device. When you select a DeviceCommand, it assigns it to the Task with task.deviceCommand = device.deviceCommand. For some reason, and this only happens in this section of the app, the app crashes with the following output in the console:
2010-10-26 15:37:33.337 livOS4[47226:207] Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. * -[NSMutableArray objectAtIndex:]: index 35 beyond bounds [0 .. 0] with userInfo (null)
Index 35 refers to the index of the DeviceCommand in the UITableView and NSFetchedResultsController. Through a process of trial and error I've discovered that the NSMutableArray is the array with the Devices. If I add a new Device to the app, the array bounds are [0 .. 1].
I added an observer for NSManagedObjectContextObjectsDidChangeNotifications but it crashes before the observer receives anything.
Can anyone help or offer any advice for fixing this?
I have the same problems with NSFetchedResultsController.
Problem disappear then I add this to my viewController
- (void)dealloc
{
self.fetchedResultsController.delegate = nil;
self.fetchedResultsController = nil;
}
Fixed it this morning. Turned out to be a problem with how I was assigning the NSFetchedResultsController delegate.

ExecuteFetchRequest intermittently throwing exception with same parameters. "not key value coding-compliant for the key"

EDIT Thanks to Matt's post I now understand that I should not be trying to access 'started' as an array. However, if that is the case, I would like to know why this code appears to be working in other places. It still seems to me that this should be "one-or-the-other." It should work or it shouldn't.
ORIGINAL
I'm using the same fetch request in various parts of my code to find the most recent game:
Game *lastGame = [[[CoreDataAccess managedObjectContext] fetchObjectsForEntityName:#"Game" withPredicate:#"started == started.#max"] anyObject];
'Game' is an NSManagedObject and 'started' is a date attribute. 'started' is set exactly once per object in awakeFromInsert. It is never changed after that. Game is never directly instantiated, but it has three subclasses. I have tried making Game both abstract and concrete, but neither has any effect on this problem.
I'm using an NSManagedObjectContext category to perform the fetch, as shown on cocoa with love here http://cocoawithlove.com/2008/03/core-data-one-line-fetch.html.
The error I am getting is the following:
Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. [<__NSDate 0xebb1130> valueForUndefinedKey:]: this class is not key value coding-compliant for the key #max. with userInfo {
NSTargetObjectUserInfoKey = "2010-11-06 11:16:53 GMT";
NSUnknownUserInfoKey = "#max";
}
It looks to me like the predicate might be trying to apply #max to a single NSDate, instead of all 'started' attributes in all games. I'm not sure though. I'm not very good with predicates, and it took me a lot of trial and error to make this one. I don't understand how the exact same fetch can have errors in different places, though.
The fetch is not part of an NSFetchedResultsController, but I am using a fetchedResultsController in the class where I'm getting the error. For example:
- (void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath{
Game *game = [self.frc objectAtIndexPath:indexPath];
Game *lastGame = [[[CoreDataAccess managedObjectContext] fetchObjectsForEntityName:#"Game" withPredicate:#"started == started.#max"] anyObject]; // Sometimes we get past this line, sometimes we don't...
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"EEE, MMM d, yyyy h:mm a"];
if (game != lastGame)
cell.detailTextLabel.text = [format stringFromDate:game.started];
else
cell.detailTextLabel.text = #"In Progress";
[format release];
...
}
and also here:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
Game *lastGame = [[[CoreDataAccess managedObjectContext] fetchObjectsForEntityName:#"Game" withPredicate:#"started == started.#max"] anyObject];
if (lastGame == [frc objectAtIndexPath:indexPath])
return NO;
return YES;
}
This exact fetch is performed several times in several places, for example on startup, but it only crashes in one class. As I said it is intermittent, but it seems to be sometime after I create a new Game object. The game is created in one tab, and the code above is from a second tab which shows history.
I have seen a similar error here. In that case the problem was solved by restarting the computer, which finally allowed XCode to realize that the attribute had been deleted from the model. I have tried that, and I'm still experiencing the problem. I have also tried deleting and recreating the 'started' attribute in the model. I have also read the Core Data Troubleshooting Guide, but was unable to find any help there either.
Predicates are applied to one source object at a time. If your source object does not have an array property, you can't use an array operator.
In your case, the predicate says:
Look at a given "Game". If its own
"started" property is equal to its own
"started" property with the #max KVC
array operator applied, then this
predicate will be true.
This is not what you want. The only situation where you'd use a KVC array operator in a predicate is where a property on an object is an array. e.g.
Fetch every "Season" where the "games.#max.homeTeamScore > 50" (i.e. seasons where a home team scored more than 50 in a game). This would work because the "games" property on a "Season" would be an array, so games.homeTeamScore would also be an array.
However, the "started" property on a single Game is not an array. The array you want to operate on is actually the array of all games, which is not a property of a game.
The only twisted way you could access the array of all games would be to fetch the array of all games first, then apply the array operator outside the predicate and then on the inside of the predicate only apply the equality test.
i.e. fetch all games first, then refetch with:
fetchObjectsForEntityName:#"Game" withPredicate:#"started == %#", [allGames valueForKey:#"#max.started"]
But this is not the smart thing to do either.
Ultimately, the correct way to fetch the game with the latest starting date as you're trying to do, can't be done with the single line fetch method.
You'll need to create a variant of the method that allows you to setSortDescriptors: on the fetch request (to sort by "started", descending) and then setFetchLimit:1 on the fetch request to only get first result.

issue with array

Getting error in this line :
NSString *nmm =[narr objectAtIndex:1];
error shows :
'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index
(1) beyond bounds (1)'
It looks like your array only got one value (which you can accesss at index 0, not index 1).
You should probably start by checking the contents of narr at run time. It sounds like the contents aren't what you would expect them to be at the desired point in execution. Right before the line you posted in your question, use an NSLog call to log the contents of the array like this:
NSLog(#"Contents of array: %#", narr);
Then run the app and check the console after the error arises. Put some time into learning how to use NSLog, breakpoints, and the GDB console - they will end up saving you lots of frustration when debugging.
Your comments on unset's answer raise another point: Why are you storing multiple pieces of data inside the same string? Wouldn't it be easier to separate name, lname and id into separate strings and place each into its own array cell? Then you could access them using [narr objectAtIndex:] without having to worry about parsing the string every time you need one of those pieces of information.