The Dangling Pointer

Sh*t my brain says and forgets about

Diversity in Developers

| Comments

I had an excellent weekend at CocoaConf Chicago meeting interesting people and reconnecting with many as well.

One of the subjects that was brought up in Brittany Tarvin’s Friday Keynote talk was that of women in the technology field. I had the pleasure of meeting Brittany at SecondConf and it was great to see her challenge to encourage women (and girls) to be software engineers brought to CocoaConf. Her talk stirred a lot of discussion, especially in the reverse panel discussion Saturday. The overwhelmingly positive response to her message was inspiring. Nowhere before have I experienced such open-minded discussions and outright admittance that we can all do more for women and other minorities in the tech field.

I talked with a Brittany at SecondConf about the topic of the disadvantages women have when dealing with a white male dominated field. I admitted to her that I have similar experiences being gay and working for companies that have a “brogrammer” type of atmosphere. I left one job because I felt there was no way I could be open about myself there. The job had the typical “brogrammer” atmosphere - mostly if not all male development staff, a good majority right out of college, discussions of a sexual nature, and pressure to conform ever-present. The job became too much when I worked on-site at a client install for nearly a month. Discussions of going to “titty bars” and frequent use of the word fag and gay topped my list of offensive remarks.

I’m usually the type of person who lets things slide, opting for a neutral reaction. Instead of trying to fix everything at the company, I left. My current employer has been fantastic, and I feel no need to have to hide who I am. I am certainly more productive and my coworkers see me as a part of the team. I’m by nature an outgoing person (you can thank my mom the social butterfly) - so being the “shy” one at the more conservative company should have been a flag to myself.

Geeks need to be more empathetic and understand that not everyone thinks the same way. Parents need to encourage their children to do what they want to do and not limit them to things that are pink if they’re girls and blue if they’re boys. When you’re at work, don’t make assumptions that just because you work with someone means that you understand them completely. We all are unique people and we all have beliefs and emotions. I’m not asking for you to accept these emotions and beliefs, but just respect that they are there and try to work together.

I encourage you to get involved in school outreach programs to teach children about technology. Open their minds at a young age and enforce the idea that we all can be what we want to be. Gender/race/sexual orientation bias is not acceptable in this day and age.

Simply put: Quit being a dick.

Please check out Brittany’s work at Tumblr and Twitter. Check out Brittany’s employer Fading Red whom also actively supports her.

Scrolling to Hidden Table View Cells

| Comments

I’m currently using BSKeyboardControls to add that fancy Next/Previous/Done buttons to the top of the keyboard on the iPad. I have noticed, however, that while scrolling through the fields in a UITableView, the cursor would sometimes disappear and the keyboard would be detached (typing does nothing).

I threw some logging together and make a discovery - scrolling to a UITableViewCell far off the screen that is UIView.hidden == YES doesn’t allow subviews to receive the becomeFirstResponder message.

And the logs:

The solution (the only one I could come up with) is to fire off a message to the text field after a short delay to become the first responder. This seems to solve the problem.

Adding the Fancy Search Magnifying Glass to Your UITableView

| Comments

So you’re working on a search screen or popover with UITableViewController and you’re wondering how to get that fancy search magnifying glass in your search results, right?

In my example, I have my table view sourced by a simple array of data. This may not be the case for you, but you get the idea from the example. Simply add the constant UITableViewIndexSearch as the first section header title - UITableView will understand to replace the {search} text from that constant with the locale-specific image indicating search.

Then, you want to show the search bar when that icon is selected. Normal behavior when selecting an index in the right hand gutter is to scroll to that section header. The search magnifying glass, however, signifies the search bar section. The key is that you have to use a UISearchDisplayController and tell the table view to scroll up to the search bar’s rectangle:

Pretty simple! This feature isn’t well documented in the Apple API but it’s quite handy for making your app feel native.

Bringing in Your Own Hardware to Work

| Comments

As a consultant, I have to move around to various companies as part of my job. Sometimes I am able to stay with the same client for months, sometimes weeks. The one thing that continues to be an issue wherever I go is the availability of a suitable development environment for me to start working on day one. I typically bring in my own laptop so that I can get started as quickly as possible. This is only if the client allows it.

I’ve worked at a number of fortune 500 companies, and typically the answer to the “may I use my own hardware?” question is a solid NO. An exception to that answer was my last client - they are a large company with nearly $19 billion in revenue and yet they have an open policy about outside hardware. They outwardly tell people (at least in the IT areas) that you (employees/consultants) can bring in faster computers and better hardware than we can probably provide. Have at it.

The risk of this position is that of viruses and loss of corporate intellectual property via those personal machines being brought in. The reality of the decision is, it’s not much different than having VPN from home. I, as a developer, need a high quality workstation with lots of RAM. Developing server-based applications requires a lot of resources when testing in a development environment. When asking for a machine less than a year old with 8GB of RAM, I got the typical pushback from desktop support telling me that I shouldn’t be running server applications on a workstation. What? That’s my JOB.

One of my coworkers, a consultant, had been there over a year and already brought in his own monitors and a workstation. I followed suit and brought in my own laptop and monitors. Our productivity skyrocketed having the right equipment for the job. Yes, it’s frustrating not getting the equipment you should expect to do your job. Corporate red tape frequently stifles innovation.

There are positives and negatives for letting people bring in their own hardware. Implement controls to prevent unauthorized connections into corporate file shares and move on is what I say. Think of it this way - you’re paying top dollar to get me in as a consultant. Wouldn’t you want me to be the most effective I can be?

Spring 3.1’s PropertyPlaceholderConfigurer

| Comments

Spring 3.1 brought a lot of good changes to the framework but with any version change, behaviors can be different. Spring does a good job documenting most of this API changes but there is one that I apparently missed or underestimated the impact of.

Property files can be “imported” into the Spring context so that the values can be inserted into configuration using ${ } with the property value inside of the brackets. This is a handy feature that I use frequently in my Spring projects. The PropertyPlaceholderConfigurer has been replaced by PropertySourcesPlaceholderConfigurer in Spring 3.1. One minor difference between them is the latter has the ability to read @Value annotations for direct injection of property values. The other side effect is that the 3.1 class puts system properties ahead of your property file’s values. 3.0, on the other hand, let your property file win if a name matched one as a system parameter.

I ran into this problem because my 3.0 configuration had a replacement parameter for a data source name injected by JNDI. The JNDI name is different between environments at my client, so I had to parameterize it. In Spring 3.0, my configuration was as so:

You’ll notice the context:property-placeholder element has a single properties file. The values read in are:

and they are used in my JNDI configuration:

When I switched to 3.1, I updated the XML namespace to point at 3.1. This changes things behind the scenes to go to PropertySourcesPlaceholderConfigurer. If you want to retain the original 3.0 behavior, you can keep the XMLNS at 3.0 or add system-properties-mode=”FALLBACK”.

I suspected something was happening with the behavior when I saw in the log files that the data source couldn’t be cast as a string. I pulled out my hair trying to figure it out and ended up renaming pavDataSource to PavDataSource and it worked fine. This problem came back up deploying to another environment having the lower case name and I have no ability to change it. Switching back to 3.0 behavior fixed this because I suspect a system parameter was being created with pavDataSource as the name.

Confusing and frustrating as hell, but the simple mode switch made it right as rain.

Maven & Eclipse Target Folder + Validation Stabbyness

| Comments

Does using Maven with Eclipse make you stabby when you spend an hour waiting for Eclipse to finish validating files? You may not realize it, but Eclipse is indexing/validating files inside of your project’s target folders! Yes kids, this is annoying and time consuming. The target folders also end up showing results in the “Open Type” and “Open Resource” windows. I’m sure we’ve all experienced the duplicate results when searching for a class or resource.

Why does it do this? Eclipse has a feature built in that will, by default, exclude folders that have been marked as “derived”. Normally folders like your source output folders (bin for example) are marked for you. Well, Eclipse doesn’t automatically mark the target folder as “derived” so it treats it like a regular folder. Right click your target folder in Eclipse and click the check box for “derived” - magically the folder is now excluded even from the Open Type and Open Resource windows.

But wait.

Next time you run a Maven “clean”, the target folder is deleted and the check box reset for derived. How do you avoid that? In your parent project (or current project if you have a single module) add the following to your plugin definitions:

This will force Maven to use version 2.4.1 of the “clean” plugin - if you’re using Maven 3 you can probably remove the version line. After version 2.3 of the plugin, excludeDefaultDirectories became available. This little gem will only delete the target content and leave the folder alone for you.

Enjoy!

Resizing a UITextView Automatically With the Keyboard

| Comments

One of the biggest UI no-nos you can perform in iOS is creating a UITextView that assumes the size of the keyboard on the screen before the keyboard even shows up. You should be dynamically resizing your text views by looking at the dimensions of the keyboard, and not assuming you know the dimensions.

Why? Try enabling a Japanese keyboard and see how your app performs. You’ll notice that the keyboard is taller than the English keyboard - it’s to give room to a typeahead area for creating the glyphs. Now how does your app behave?

There is a quick and easy way you can resize automatically. In my example, I have a new view with a nearly full screen-sized text view showing. When the user taps into the text view, the text view is then resized to leave a bit of gap around it and the keyboard displays underneath.

The text view without a keyboard

After the user taps in the text view, the keyboard appears. An example of an English keyboard is at left and a Japanese keyboard at the right. Notice any difference? What should happen is your app just figures out how much space you have left after the keyboard is displayed and resize accordingly. If you switch between keyboards, you have to account for visual changes as well. Here is the code I wrote to handle this properly:

UITableView resize excerpt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
- (void)viewWillAppear:(BOOL)animated {
    [textView setText:_notesText];

    // Register notifications for when the keyboard appears 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

- (void)viewWillDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)keyboardWillShow:(NSNotification*)notification {
    [self moveTextViewForKeyboard:notification up:YES];
}

- (void)keyboardWillHide:(NSNotification*)notification {
    [self moveTextViewForKeyboard:notification up:NO];
}

- (void)moveTextViewForKeyboard:(NSNotification*)notification up:(BOOL)up {
    NSDictionary *userInfo = [notification userInfo];
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;
    CGRect keyboardRect;

    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

    [UIView beginAnimations:@"ResizeForKeyboard" context:nil];
    [UIView setAnimationDuration:animationDuration];
    [UIView setAnimationCurve:animationCurve];

    if (up == YES) {
        CGFloat keyboardTop = keyboardRect.origin.y;
        CGRect newTextViewFrame = textView.frame;
        originalTextViewFrame = textView.frame;
        newTextViewFrame.size.height = keyboardTop - textView.frame.origin.y - 10;

        textView.frame = newTextViewFrame;
    } else {
      // Keyboard is going away (down) - restore original frame
        textView.frame = originalTextViewFrame;
    }

    [UIView commitAnimations];
}

The view controller adds an observer for when the keyboard shows up and disappears. When the keyboard is coming up, we record the original frame of the text view - this makes it easier to restore the text view when the keyboard goes away. In this specific instance, the keyboard cannot be dismissed since enter is set to put carriage returns in the text box.

Fixing Layer Transparency Issues in Xcode

| Comments

If you’re looking to get higher frame rates and general application performance tweaks from your iOS application, you may need to take a look at transparent settings on your subviews. Any time you set a subview to be transparent, the OS has to blend multiple layers together to figure out the end flattened result. This blending takes CPU cycles and can impact performance of your app - especially in something as simple as a UITableViewCell.

Luckily there is an easy way to find these problems using Xcode’s companion tool, Instruments.

One of the instrumenting tools you can use on an app deployed to a device is Core Animation. The Core Animation instrument has a bunch of fancy switches you can flip.

That will turn on a visual indicator to show where multiple transparent layers exist on the screen. For example, the main table view of my app MigraineDiary shows the following:

To get your app into Instruments, simply select the “Profile” menu item under “Product”. This will build your app and launch Instruments. Make sure you have your device selected and not the iOS Simulator. Any areas that are heavily colored in red should be reviewed by you to ensure you’re not setting layers transparent that don’t need to be. This includes using [UIColor clearColor]!

You’ll notice transparency indicators in red on system components like the tab bar and nav bar. There isn’t much you can do about these, so you can really just ignore them. If you’ve overridden behaviors, however, you may wish to review your code to make sure you’re not breaking something.

Switched to Octopress

| Comments

I’ve moved my blog over from Wordpress to Octopress. I’ve been loving every minute of it. I don’t get the opportunity to use Ruby and Rails in my daily job. Switching over to Octopress which uses Jekyll for rendering has a welcome change. Everything now is a static page rather than running on a MySQL database.

Sass and Compass make CSS and HTML so much easier to use. I’ve never been a design expert although I do use CSS and HTML all the time. This takes the complexity out of making a visually appealing site while conforming to standards without even having to think about it. Love love love.

I exported all of my Wordpress entries using David Winter’s wordpress-to-jekyll PHP script. Dead simple and it exported everything as text. None of the images from my previous posts came with, but I can deal with that.

Google Data API

| Comments

I’ve started to mess around with the Google Data APIs recently to help support my Migraine Diary iOS application. Specifically I want users to be able to export their journal entries into a Google Spreadsheet rather than just a plain CSV file. I am using the Objective-C client that Google built and have come across a number of issues or gotchas.

  • The Objective-C client is badly documented - a number of Google Data API calls have zero examples and translating REST calls into Objective-C classes is a challenge.
  • OpenAuth 2 is surprisingly easy to use
  • Google provides very little troubleshooting assistance even with their client
  • Objective-C is very new compared to the Python, .NET and Java clients

That being said, I am making progress. I’ll most likely share my finalized code to create a simple spreadsheet here so others have a jumping off point.