Why are multiple touches causing my iPhone app to crash? - iphone

In my app, I am getting the row index as the user taps on the row or selected row. But if a row is tapped twice, my app crashes.
What could be causing this behavior, and how can I fix it? Here's the code I'm using:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
abc *xyz = [[abc alloc] init];
dcs = [allHadits objectAtIndex:indexPath.row];
hk = dcs.kokid;
[dcs release];
}

Do you mean tapping on the same row twice makes it crash? If so, it might be because of the [dcs release]. I don't know what dcs is (unless that's supposed to be xyz) but grabbing a pointer to the object in the array and then calling release on it might be releasing the object in the array, making it crash next time the row is hit. Delete the [dcs release] and see if it still crashes. My memory management isn't the greatest though so I could be wrong.

Don't release dcs. Why are your variables named so poorly?

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.

Display Alert if tableView has no Results

I previously thought I could answer this question with a simple array count (my mistake). I am trying to display an alert to the user id a tableView has no results. I cannot simply place the count in the viewDidAppear method because the web query that populates the JSON and tableView takes a few seconds to populate. I cannot simply place this in:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath {
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows]
lastObject]).row){
//loading complete
}
}
Because nothing gets called in this method if there are no results. Does anyone have any recommendations for this - been searching for over 4 hours and have pulled nearly all my hair out.
Please feel free to un-downvote this questions if it has been made more suitable for SO - this questions massive downvotes have cost me my ability to ask questions...
NSInteger count = [array count];
NSlog("array count : %d",[array count];
This will give you array count in your console.
You cannot check the row count in viewDidAppear because an asynchronous NSURLConnection is used to fetch the JSON data that populates the table view.
The correct way is to call reloadData in connectionDidFinishLoading, after you have updated your data source with the response from the URL request. At that point you know if the number of rows is zero or not, and there is no need to wait for the table view update to complete.

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.

UITableView occasional crash while appending rows

My app has a UITableViewController that is getting an "Invalid Update: invalid number of rows in section 0..." after appending rows. Thing is, it happens only in %0.2 of sessions. Our app, has millions of sessions so the crashes are adding up.
The flow is simple. It's part of a feature that matches a user's music with our catalog of videos. A background thread makes a series of requests. A request goes out, response comes back with results, then those results get appended to a tableView within one of our tabs. The requests go in batches and can add up to lots of resulting rows. So rather than call reloadData after a batch comes in, I wanted to append them properly. Works awesome, but occasionally crashes.
I was able to reproduce this one time on a device. It has never happened on simulator. As far as I know, the crash is reasonably random, although it mostly happens on 3gs. The fewest # of crashes come from 4s.
Here's the code. A response comes back. In this case, allMatches is every match so far (the data source for the table). batchMatches is the number of new artists. Both are arrays:
[self.tableView beginUpdates];
NSMutableArray *paths = [[NSMutableArray alloc] init];
for (int i = [allMatches count] - [batchMatches count]; i < [allMatches count]; ++i) {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
[paths addObject: indexPath];
}
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:NO];
[self.tableView endUpdates];
[paths release];
Code is pretty simple. It just appends rows to the end, one for each result. Never deletes. An example of full exception message is "Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (131) must be equal to the number of rows contained in that section before the update (131), plus or minus the number of rows inserted or deleted from that section (20 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out)." Numbers are all over the place in actual crash reports, so it's not a specific batch number.
Like I said, it almost always works. And it crashes usually on 3GS. I'm wondering if this could possibly be a framework bug. I could always call reloadData after each batch returns but it results in ugly flashing of table cells each time. On purpose I triggered the exception and it seems after that the table is dead, so I couldn't do a try/catch with a reloadData as a fallback in the catch block.
Can anyone out there shed some light? Apologies for length of this post.
EDIT: The server requests are done using NSOperationQueue, so they are on a background thread. When the response returns, I post a notification on the main thread, which causes the table code to run. The notification is posted like this:
NSNotification *notification = [NSNotification notificationWithName:notificationName object:self];
[self performSelectorOnMainThread:#selector(postNotification:) withObject:notification waitUntilDone:NO];
Post notificiation is simply a wrapper around [[NSNotificationCenter defaultCenter] postNotification:notification]. So the table code should be on the main thread.
My guess is, you are executing the table view update in a background thread. You should do that on the main thread instead.
Place your code inside a dispatch_async block.
dispatch_async(dispatch_get_main_queue(), ^(void) {
// ..
});

iPhone SDK SSCollectionView load item from thread

I have an SSCollectionView which is modeled after NSCollectionView and UITableView. It calls a function to load each item at an indexPath.
I want to asynchronously load images into each one of those paths.
- (SSCollectionViewItem *)collectionView:(SSCollectionView *)aCollectionView itemForIndexPath:(NSIndexPath *)indexPath {
....
[self startLoadingItem:item indexPath:indexPath];
return item;
}
-(void)startLoadingItem:(SSCollectionViewItem *)collectionViewItem indexPath:(NSIndexPath *)indexPath
{
[SEThreadInvocation detachNewThreadSelector:#selector(loadItem:indexPath:) toTarget:self withObjects:collectionViewItem,indexPath, nil];
}
SEThreadInvocation is just a subclass of NSThread so that I can send more than one object to a selector.
-(void)loadItem:(SSCollectionViewItem *)collectionViewItem indexPath:(NSIndexPath *)indexPath {
...
collectionViewItem.imageView.image = imageToDisplay;
}
What is happening is that the code initially works, but every time the collection reloads (often) it puts images all over the collection view randomly.
I believe this is because my SSCollectionViewItem is pointing to a different memory location each time and my item is not thread safe, so it is just stamping my images all over the place when they change in memory.
Also, I thought it might be replacing the images in memory, so I replaced it with numbers and the numbers bounce all over the collection view when reloading as well.
How can I make my objects thread safe in this context?
SSToolkit has a sample Catalog project which has a SSCollectionView demo. It loads images in the way you are needing.