Posts tagged ‘iPhone SDK’

objc_msgSend EXC_BAD_ACCESS error after moving operations to a GCD block

The subject says it all. After trying to improve the responsiveness of my app by using a Grand Central Dispatch block to run some code asynchronously, the code in my main queue GCD block was failing with an objc_msgSend EXC_BAD_ACCESS error. Bugger.

The error itself typically describes sending a message to an object that has been released and is no longer valid, but I am not sure how that could have happened just by moving some operations inside of GCD blocks.

The way that I fixed this was to go into the diagnostics tab in the Edit Scheme window, and I turned on the Enabled Guard Malloc option. Then, when I ran the app, it showed me more specifically where the issue was. The problem turned out to be that I was using an autorelease array that was becoming invalid as a result of going into and coming out of the GCD blocks. I switched the array to a retained object, and everything started working fine again.

Just don’t forget to turn off the Enable Guard Malloc when you are done testing.

And if you have not yet checked out the coolness of Grand Central Dispatch, you are missing out on a valuable tool.

UILabel sizeToFit malfunction

For some reason, my use of UIView’s sizeToFit method was not working as expected. What I got when I tried to send my UILabel controls through this method was that they ended up being sized down too far, and as a result text was either eliminated from the label, or an ellipsis appeared at the end. I tried just about every combination of UILineBreakMode and numberOfLines I could think of, with no combination fixing the problem.

So what I ended up doing was to just manipulate the UILabel’s frame in the table view’s cellForRowAtIndexPath method. Here is a code snippet:

if (feedIndex == SECTION_CUSTOMER_AND_JOB_INFO) 
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CELL_CUSTOMER_AND_JOB_INFO];
 
    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"SummaryCustomerAndJobInfoCell" owner:self options:NULL];
        cell = cellCustomerAndJobInfo;
    }
 
    // the next line uses the tag property of the label as set in the nib file
    UILabel *lbl = (UILabel *)[cell viewWithTag:1];
 
    NSString *text = @"Set your multiple line\ntext to display here...";
    CGSize constraint = CGSizeMake(lbl.frame.size.width, 20000.0f);
    CGSize size = [text sizeWithFont:lbl.font constrainedToSize:constraint
                       lineBreakMode:UILineBreakModeWordWrap];
 
    lbl.text = text;
    [lbl setFrame:CGRectMake(lbl.frame.origin.x, lbl.frame.origin.y, 
                                      lbl.frame.size.width, size.height)];
 
    return cell;
}

By the way, don’t forget to do the same kind of size calculations in your heightForRowAtIndexPath delegate method.

This past Wednesday was a day of great sadness for me, as I had to put my 15 year old schipperke to sleep. Good bye Captain Kirk, you were an ornery little cuss but we loved you anyway. :'(

Just being thorough

I always get a little nauseous when looking through someone else’s code and seeing things like this:

res = sqlite3_exec(database, [select UTF8String], NULL, NULL, &errorMsg);
if (res != outcome) {
    [testStringCapture appendFormat:@"%@,",obj]; //changed 2/2/2011
}
else {
    [testStringCapture appendFormat:@"%@,",obj]; //changed 2/2/2011
}

Alas, a little later on in the same method was some code that soothed my sensibilities as it is kind a perfect fit into the whole “do something here” theme:

res1 = sqlite3_exec(database, [select1 UTF8String], NULL, NULL, &errorMsg1);
if (res1 != outcome1) {
 
}
else {
 
}

As per usual, these code snippets are unedited (except for some formatting) portions of production code.

Search bar and correction don’t play nice together

I just discovered something about the iOS platform that may not be readily apparent at first glance.

If you are using textDidChange method of a UISearchBar to interactively scan through your table’s data source (and let’s face it, who using the UISearchBar isn’t??), and you have the correction property of the search bar set to anything other than no, your textDidChange method can fire unexpectedly with a different searchTerm than you had expected, which can cause your table data to be out of sync.

BTW, Happy Mother’s Day to all mothers out there.

And an extra special Happy Birthday message to Joe Bonamassa. If you do not know who Joe Bonamassa is, feel shame for a few minutes, then go to iTunes, Amazon, Pandora, or wherever it is that you get music, punch up some of Joe’s music, and then turn it up loud. You’ll thank me later.

Xcode 4 exception breakpoint

Did you ever have Objective-C code that would fail with an exception (such as asking for an objectAtIndex beyond the bounds of the array), but by the time you got word of it, all the stack trace had in it was the obj_msgsend and main? Yeah, I hate that.

Well I discovered that you can add a breakpoint to your project that will immediately break when the exception happens. To do this with Xcode 4, click on the Breakpoints symbol (2nd from the right) in the Navigator pane, click the + button at the bottom of the pane, and select Add Exception Breakpoint. From the bubble that appears, I selected Objective-C from the Exception choice (although I suspect you can safely leave it at all if you desire), and I left the Break selection at On Throw. Once you click Done, you should then have a new exceptions breakpoint in the list.

This was instrumental in helping me track down an issue on an app rescue that I am currently working on.

By the way, here is an awesome line of code that I found in the aforementioned app rescue. My brain hurts from looking at the code for long stretches of time, but there are some nice nuggets like this sprinkled in the code:

Assets *ass = [[Assets alloc]init];

Hello, Let’s Talk! Peer-Peer Communication using GameKit, Sockets, and Bonjour. (CIDUG meeting, March 22, 2011)

Justin Munger gave a presentation on iPhone peer-to-peer communications at the Columbus iPhone Developer User Group on March 22, 2011. He had some great examples of applications he had put together that used GameKit and sockets to implement a simple chat type application.

I have been thinking of doing some peer-to-peer communcation in one of my applications, so his sample code should hopefully come in handy.

BTW, happy 80th birthday to the best… and, most dashing… starship captain… ever seen on the small or big screen, William Shatner. Make sure to read with the dramatic pauses for full effect.

Double tap a table view cell on a UITableViewController

So I have one of those nifty UITableViewController views in my application, and since the app is now starting to get a bit more complex, I wanted to have a quick way to be able to do multiple things with a cell from that view.  Unfortunately, if you use the UITableViewCellStyleDefault style to create your cell, there is not much you can do with it, other than to have an accessory type.  This is how I started using the cells, allowing the user to set a cell to be selected or not selected (setting the cell accessoryType to UITableViewCellAccessoryCheckmark or UITableViewCellAccessoryNone).

In order to perform a different function on the cell, I figured that it couldn’t be too hard to allow the user to double tap the cell to do something other than turn the check mark off and on again or vice versa.  As per usual with the iPhone platform, it took a bit of digging.

At first, I thought I could use a UIGestureRecognizer to detect the double tap.  Unfortunately, our apps are still trying to support 3.1.3 OS users, and the UIGestureRecognizer requires 3.2.

So with a bit more digging, I found a solution on Stack Overflow that I “borrowed”.  Unfortunately, that code was a bit rough and required some minor tweaks and fixes, so here below is how to do this.

First, you need to make sure to add the necessary ivars to your class header file:

int tapCount, tappedRow, doubleTapRow;

Then, here is the code that you will need in your implementation file.  Those of you familiar with the UITableViewDelegate will see something familiar and something to extend it.

#pragma mark -
#pragma mark Table view delegate
 
- (void)tapTimerFired:(NSTimer *)aTimer
{
    // timer fired, there was a single tap on indexPath.row = tappedRow
 
    // do something here with tappedRow
 
    [cell setSelected:NO animated:YES];  // maybe, maybe not
 
    if (tapTimer != nil)
    {
        tapCount = 0;
        tappedRow = -1;
    }
}
 
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
 
    // checking for double taps here
    if (tapCount == 1 && tapTimer != nil && tappedRow == indexPath.row)
    {
        // double tap - Put your double tap code here
        [tapTimer invalidate];
        tapTimer = nil;
 
        //NSLog(@"double tapped the cell");
        doubleTapRow = tappedRow;
 
        [cell setSelected:NO animated:YES];  // maybe, maybe not
 
        // do something here with doubleTapRow
 
        tapCount = 0;
        tappedRow = -1;
    }
    else if (tapCount == 0)
    {
        // This is the first tap. If there is no tap till tapTimer is fired, it is a single tap
        tapCount = 1;
        tappedRow = indexPath.row;
        tapTimer = [NSTimer scheduledTimerWithTimeInterval:0.2 target:self 
                selector:@selector(tapTimerFired:) 
                userInfo:nil repeats:NO];
    }
    else if (tappedRow != indexPath.row)
    {
        // tap on new row
        tapCount = 0;
        if (tapTimer != nil)
        {
            [tapTimer invalidate];
            tapTimer = nil;
        }
    }
}

As it says in the code, you may or may not want to turn off the cell selection, it is up to you whether you need to do that or not. Also, you may want to play around with the time factor where the tapTimer is created if it does not work as well as you would like.

Missing GCC 4.2 options in Xcode Build tab

I was missing some GCC 4.2 options (such as a nice way to do some preprocessor definitions) in an older project of mine, and I knew that I had done something similar on a newer project.

As it turns out, for some reason it seems to put these options back in the Project Info window if you change your Code Signing Identity option.  I changed it (and the Any iOS option below it) to a different profile, then changed them back to iPhone Developer, and the missing options suddenly appeared in my older project.

Here is a link to the Stack Overflow question and answer:

Missing GCC 4.2 options in Project Info / Build tab in Xcode 3.2.5

By the way, Happy New Year everyone.  I hope you all had a nice 2010 holiday season.

Rejection

It had to happen sooner or later.  The dreaded red light of rejection descended on one of my new application submissions.

They got me on the old “App Store Review Guidelines, Metadata section, 3.5: Small and large app icons should be similar, so as to not to cause confusion” gambit. (By the way, there is no need to read that twice, the seemingly grammatically incorrect wording above is straight from the e-mail I received as well as being on the App Store Review Guidelines web site. Go to https://developer.apple.com/appstore/resources/approval/guidelines.html to see for yourself after you have logged into your developer account.)

It is true, the 57×57 icons I used for the two applications were not just scaled down versions of the 512×512 images that I put on iTunes Connect, I wanted to use smaller images for the app icons, and scaling them up would have made for a couple of messy images for the iTunes App Store.

Strangely enough, I submitted these two similar applications at the same time, and the other one managed to make it through, despite the fact that the application’s 57×57 icon was not very similar to the 512×512 icon I uploaded to iTunes Connect.

Oh well. The offending app has been resubmitted, hopefully it will get approved before they take the Christmas break.

More iPhone code signing issues

Here’s a little nugget that I just learned about code signing your iPhone app that I probably was able to get around before by the  bumble-around-trying-everything-under-the-sun-before-stumbling-on-the-right-combination method.

Your build settings in the Target override your build settings in the project.

This is obvious to me now looking back at it, but I am very nearly 100% sure that this was tripping me up on the previous projects that I have tried to submit to the App Store.

It probably says this somewhere in the Apple documentation, but I am too tired to look for it to verify that it is in there.  Now if I can just get the UIAutomation tool in Instruments doing what I need it to do.  I used to remove the logElementTree function out of the js file after I figured out how deep something was buried in the hierarchy, but I got tired of retyping it so I just leave the line in there now and just move it down to the next block of new functionality I am trying to exercise.