PullToRefresh iOS 5 and ARC Tutorial

I’ve been working on my first “official” iPhone app for my company. It’s a basic news app that pulls information from a WordPress powered news site. One of the first features I wanted to add was Pull to refresh. The problem I encountered was that because iOS 5 has only been out for a short time, the standard PullToRefresh libraries (most notably EGOTableViewPullRefresh) hadn’t been updated for iOS 5 or ARC. Converting the code to ARC is easy enough with Xcode’s Refactor tool but I was also looking to use the code on a UIWebView and there was no documentation for how to set that up.

Luckily, I came across a fork of the EgoPullToRefresh code at GitHub called PullToRefreshView, which has a very good README file with directions on how to implement for both a UITableView and a UIWebView. Also, there’s a lot less code that needs to go into your controller as compared to the original EGOTableViewPullRefresh code. It’s not ARC compliant, but it was easy enough to refactor using the Xcode refactor tool. I’ve used it for both a UITableView and a UIWebView, so I figured I would share how I got it working for both and also show a couple of tweaks I added.

So, if you haven’t already gotten it, go get iStopped’s code. Then, after you add PullToRefreshView.h, PullToRefreshView.m arrow.png and arrow@2x.png to your project, go to Edit->Refactor->Convert To Objective-C ARC and refactor to make the files ARC compliant. Once you’ve done that, you can start adding code to your project.

Note: If Xcode complains with the error: existing ivar ‘delegate’ for property ‘delegate’ with assign attribute must be __unsafe_unretained”, change the property from “assign” to “strong.” See this comment for details.

For a UITableView, it’s really simple. First, #import “PullToRefreshView.h”, then add an iVar:

Objective-C
1
2
3
4
@implementation RootViewController
{
PullToRefreshView *pull;
}

Then add the following to your UITableViewController in ViewDidLoad:

Objective-C
1
2
3
pull = [[PullToRefreshView alloc] initWithScrollView:(UIScrollView *) self.tableView];
[pull setDelegate:self];
[self.tableView addSubview:pull];

Next, you simply add the delegate method for when the user pulls to refresh:

Objective-C
1
2
3
4
- (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view;
{
[self reloadTableData];
}

Finally, in your reloadTableData method, call finish

Objective-C
1
2
3
4
5
6
-(void) reloadTableData
{
...
[self.tableView reloadData];
[pull finishedLoading];
}

Your done.

A couple of Tricks

One of the first things I noticed was that my app would freeze while it was loading data. This really annoyed me, probably because I’ve gotten so used to other apps like Facebook or Twitter that still allow you to scroll up and down while the app is reloading it’s data after pulling to refresh. To fix that we change our delegate to look like so.

Objective-C
1
2
3
4
- (void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view;
{
[self performSelectorInBackground:@selector(reloadTableData) withObject:nil];
}

Pretty self explanatory, this basically runs the task in the background.

The second thing I noticed was that there wasn’t a way for me to trigger the Pull to Refresh code without, well, pulling to refresh… I wanted to be able to trigger it when bringing the app back to the foreground. So I had to first create an observer for UIApplicationWillEnterForegroundNotification in my app delegate then I had to modify PullToRefreshView.h to make one of the methods available to my UITableView.

Add the following code to ViewDidLoad:

Objective-C
1
2
3
4
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(foregroundRefresh:)
name:UIApplicationWillEnterForegroundNotification
object:nil];

Next, make a small modification to PullToRefreshView.h, add this line right below – (void)finishedLoading;

Objective-C
1
2
- (void)finishedLoading;
- (void)setState:(PullToRefreshViewState)state_; // <-- New line

Then add this to your UITableView:

Objective-C
1
2
3
4
5
6
-(void)foregroundRefresh:(NSNotification *)notification
{
self.tableView.contentOffset = CGPointMake(0, -65);
[pull setState:PullToRefreshViewStateLoading];
[self performSelectorInBackground:@selector(reloadTableData) withObject:nil];
}

The first line scrolls the view so you can see the loading "screen", the second line sets the state of your pull scrollView to loading and the third is your call to reload your table data. Now your PullToRefreshView will fire when you bring the app back into the foreground.

PullToRefresh a UIWebView

Working with a UIWebView is slightly more complicated because there’s a few more steps involved. In the controller that contains your UIWebView, create an iVar for your scrollView:

Objective-C
1
UIScrollView* currentScrollView;

Next, in ViewDidLoad make the UIWebView a delegate to itself and give it a tag:

Objective-C
1
2
3
// Make webView a delegate to itself
[webView setDelegate:self];
webView.tag = 999;

Now add the following to your ViewDidLoad:

Objective-C
1
2
3
4
5
6
for (UIView* subView in webView.subviews) {
    if ([subView isKindOfClass:[UIScrollView class]]) {
        currentScrollView = (UIScrollView *)subView;
        currentScrollView.delegate = (id) self;
    }
}

Now you can set up your PullToRefreshView scrollView and add it to the webView:

Objective-C
1
2
3
4
5
6
// Set up Pull to Refresh code
PullToRefreshView *pull = [[PullToRefreshView alloc] initWithScrollView:currentScrollView];
[pull setDelegate:self];
pull.tag = 998;
[currentScrollView addSubview:pull];
[self.view addSubview:webView];

You’ll probably get a warning on line 3 ([pull setDelegate:self]), if so, go into the .h file of your controller and #import PullToRefreshView.h then add <PullToRefreshViewDelegate> to your @interface declaration like so:

Objective-C
1
@interface YourViewController : UIViewController <PullToRefreshViewDelegate>

That should squash the warning. Or you could skip all that and typedef the setDelegate method like so: ([pull setDelegate:(id)self]), the choice is yours. Moving right along, add the following to your controller:

Objective-C
1
2
3
-(void)pullToRefreshViewShouldRefresh:(PullToRefreshView *)view {
[(UIWebView *)[self.view viewWithTag:999] reload];
}

Then in your webViewDidFinishLoad method, add the following:

Objective-C
1
2
3
4
- (void)webViewDidFinishLoad:(UIWebView *)wv
{
[(PullToRefreshView *)[self.view viewWithTag:998] finishedLoading];
}

That’s it. Now you have Pull To Refresh working in your UIWebView. Thanks to iStopped for his work on this.

WordPress: Display first image in each post

In a recent WordPress project I was working on, I was looking for a quick way to get the first image from each post to show up in the list of posts. I couldn’t find anything that worked the way I wanted it to, so I came up with this idea using Simple HTML Dom Parser. Download simple_html_dom.php to your computer, then upload it to your theme’s directory.

Then, edit your functions.php file (if it doesn’t exist, go ahead and create it) and add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
function get_first_image($cats, $file) {
$cats_to_exclude = Array('AP', 'Food');
foreach($cats as $cat_obj) {
if (in_array($cat_obj->name, $cats_to_exclude))
return;
}
require_once('simple_html_dom.php');
$obj = new simple_html_dom();
$obj->load($file);
$image = $obj->find('img');
if (sizeof($image) > 0) { ?>
<img src="<?php echo $image[0]->src; ?>" class="img_class" />
<?php
}
}

Then, in your template, do something like this:

1
2
<?php get_first_image(get_the_category(),get_the_content()); ?>
<?php the_excerpt(); ?>

You can configure it to return nothing for specific categories that you want to exclude and don’t forget to style the img_class css class in your stylesheet.

Back to the iPhone

So after sporting a Droid X for almost two years, I recently purchased an iPhone. Yes, I know the rumor is that the iPhone 4s launch is imminent but the truth is nobody really knows. Not to mention, it’s not entirely clear if the iPhone 4s will be available immediately on the Verizon network after it launches or if there will be a delay. Nobody knows the answer to these questions, so I went ahead with my iPhone 4 purchase. Update 10/10/2011: I returned my iPhone 4 today (just under the 14 day return policy) and ordered my iPhone 4s!

In all of the Android vs iPhone posts I’ve red, nobody really talks about the user interface and user experience. It’s always about hardware, megapixels and gigabytes, etc. I’m going to try and jump in to the UI a little and see if I can shed some light on what I feel are the important differences.

The Back Story
The reasons I left the iPhone behind in the first place were that I didn’t like that you have to use iTunes to manage your music, I was very upset that Apple wouldn’t approve the Google Voice application and I didn’t like that Apple feels the need to approve/disapprove applications in the app store based on arbitrary criteria. So, I picked up a Droid X and didn’t look back. The Droid X was a very good phone but in my opinion the Android operating system isn’t as polished as the iPhone.

The Good
For instance, the camera on the iPhone has a much better response than the Android camera. What I mean by that is that in a good light situation, hitting the shutter release button on an iphone generates an immediate picture. Whereas on Android, there’s a good 2 or 3 second delay before the image is captured. This can be (and usually is) a major pain in the ass when you’re trying to capture a moment. With Android, there’s a pretty big emphasis on “managing” your home screens and you usually have to choose a certain number of them up front. With apple, home screens are created as they are needed. And not only can you drag and drop icons between screens on the iPhone, there’s a really cool icon manager within iTunes that you can use as well. Making folders with the iPhone is simply a process of dragging one application icon on top of another, which will automatically create a folder. In Android, you have to explicitly create a folder then add icons to it. Accessing folders within the two systems is also different with the iPhone using a very nice user interface to open the folder. On Android, the interface is kind of ugly with the folder taking up most of the screen. Navigating through contacts is similar between the two operating systems, although the iPhone gets the edge for its interface being more polished than Android. One thing that the iPhone can do that is still (as of this writing) impossible to do out of the box on Android is to take a screenshot of your phone. Pretty unbelievable.

The Bad
First, the biggest thing missing from the iPhone, IMO, is Google navigation. However, there is a really good alternative called Telenav GPS. The other thing I feel is missing form the iPhone are easy access widgets for toggling wifi, notifications and location services. As far as I was able to find, there is no way to easily toggle those services without going into the settings of the iPhone. My last complaint about the iPhone is that even though Google Voice has come a long way (when I left, Apple hadn’t even approved the app yet), the integration is not as seamless on the iPhone as it is on Android. The Android version of Google voice uses the built-in dialer, where as the version for the iPhone has it’s own dialer. It’s not a show stopper, but it is a small annoyance. I kind of miss having my contacts synced from Facebook, but I also kind of don’t miss it because having that many contacts cluttered up my address book. Update: Facebook profile photo syncing is built into the Facebook for iPhone application with the added bonus of not adding new contacts from Facebook, only adding photos to your existing contacts. Also, there is a way (kind of non-intuitive) to sync your contacts up with your google contacts.

Conclusion
While this in no way gives you a complete comparison between IOS and Android, it should give you a small window into the kind of differences that are going to impact you as a user. I believe the iPhone is a much more polished system and provides a more enjoyable user experience.

Get Your Motor Runnin’

I’m a new motorcycle rider, but it’s a passion that has hit me pretty hard. My bike, which I purchased the day I got my motorcycle permit, is a V Star 1300. When I purchased the bike, I wasn’t allowed to test drive it because I only had a permit. Not knowing anything at all about motorcycles, I had only two criteria on which to judge: 1. How the bike looked, 2. how it felt when I sat on it. When it was all said and done, I ended up with my Star.

One of the reasons I’ve become so passionate about motorcycles is because of the fun involved in making customizations. I have a brother who is very knowledgeable when it comes to doing mechanical work and we are both natural born tinkerers, so it’s been very fun and a great learning experience for me.

So far, the mods I’ve done are:

1. lay down the license plate.


2. Lowered it

3. Drilled out the baffle

4. Added an fi2000 Power Pro

5. Installed Hard Krome Sideburner Exhaust System

Not sure what else I’ll be adding, but I’m having a lot of fun so far!

Porting My Number to Google Voice

I recently ported my number to Google Voice, here’s how it went. The first thing I did was read the directions and I saw a warning over and over about how I might be billed an early termination fee from my carrier (Verizon). So, before actually initiating the porting process, I called Verizon to let them know what I was doing to try and avoid any kind of early termination fee, this is where the fun began.

1. First things first, Verizon has no friggin’ clue about number porting with Google Voice. Maybe because it’s new and not a lot of people have done it yet. I talked with so many people at Verizon and I had to explain the process to each and every Verizon employee that I spoke with, including the in-store employees and the over-the-phone employees. I spoke with a first-line support person who I explained the situation to and she eventually transfered me to someone hire up the chain who told me that all of this was possible (after I explained it again) and they promised me that I wouldn’t have to pay an early termination fee, to which they noted in the account. Everything seemed okay at this point so I went ahead with the number port.

2. Things on the Google side were very smooth. I went through the process with relative ease. Google said it would take up to 24 hours to port the number, it took exactly 24 hours (almost to the minute). They also said it would take up to 3 days for me to be able to receive text messages, that took about a day and a half.

3. Once the number porting was complete on Google’s end, I went to the Verizon store in my town to get my new number. When I explained the situation to the Verizon employee I was working with, they all started looking at me like I had 3 heads. They approached the situation with the utmost skepticism. Once they looked into it, and after about an hour in the store, I was told that the number wasn’t done porting on their end and they couldn’t give me a new number for my device because they would have to cancel the port request and my number would be lost. I told them that I didn’t believe this would happen because I was already getting voicemails on Google Voice because people were calling me. I knew the number port was complete. However, this didn’t matter, they couldn’t help me.

4. I went back home and decided to call Verizon and see if I could get this taken care of over the phone. After going through several people and explaining the situation to each of them, I was finally transfered to someone in Verizon’s porting center. After again explaining the situation, he was able to cancel my line. All that was left now was to get a new line and number for my phone. He transfered me to sales who set me up with a new line, which was active after about 30 minutes. I then set that number up as a forwarding number in Google Voice and bam, I was all set.

The process took me about 3 or 4 hours after Google ported my number, mostly because Verizon had no idea what was going on. Honestly, if I wasn’t so patient and determined to get it done, it would have taken days, not hours. Google Voice has many awesome features and porting your number will allow you to take advantage of all those features without having to hand out a new phone number to all your friends and colleagues. So, in the end, it was worth it, but it wasn’t easy. Two things still missing from Google Voice are MMS messaging and the ability to add a forwarding phone that requires an extension to be dialed.

Getting Started with Off-Camera Lighting

I recently sold the majority of my professional photography gear but that doesn’t mean I’m not still a big time hobbyist. In my personal opinion, lighting is what makes the difference between a good photo and a great one. For instance, here’s a pic that I would say has great lighting using a mixture of “3 speedlights, with a 42″ shoot through umbrella as a key.” The photo is by Ross Mytton.

Ghana Street

In most of the portrait photography I’ve done I used two lights max, usually both speedlights with umbrellas using a Canon ST-E2 transmitter to trigger the speedlights, but there are many ways to light a photo both from an equipment standpoint and style standpoint. If you’re new to off-camera lighting, the best place to get started is with Strobist’s Lighting 101 Tutorial. Also, talk to your local camera shop because they can usually show you what you need to get started. Granted, you can always buy cheaper online, but nothing beats having a solid relationship with your local camera shop, trust me.

If you’re looking for great examples of off-camera lighting photography, check out Flickr’s Strobist group.

Home Recording in 2011

So things have changed quite a bit (for the better) in terms of the cost of setting up a home recording studio. The last time I actually bought gear was early in the new millennium and it cost me a lot of cash. Of course, I had purchased some very high end gear, but that aside, it was still much more difficult both from a cost perspective and from a configuration perspective to get set up back then. I just purchased an M-Audio box with both quarter-inch and XLR inputs for 50 bucks from guitar center (president’s day sale), a Akai LPK25 midi controller and a DRV100 Dynamic Cardioid Hand Held Mic. I also had to buy an XLR cable and a guitar cable and I already had a guitar. I had a friend hook me up with the software I needed to get started and so for less than $200 I’m making music again. My last setup was probably close to $10,000 all in. Once I have some good examples, I’ll post.

I’ve Got your Corporate Vocabulary Swingin’

I plan to use increase my thought Bandwidth so that I can Benchmark my Best practices to find any Bottle necks and from there I will Change to increase my Competitive advantage and along the way utilize Conflict resolution without Constraints and exploit my Core competencies along with my Core values using Cutting edge practices to offer concrete Deliverables, which is a Game changer in my opinion. I will find the top thought leaders and start building Positive Momentum via Collaborative efforts and finally Connect the dots and Drill Down deep, sink my teeth in and Emerge victorious. I will Facilitate a Strategic plan and Strategize by Thinking outside the box, after which I will Touch base and create Actionable Customer-centric changes that are Innovative, but also Granular yet Scalable.

Corporate vocabulary makes me want to kick someone in the face…. REALLY hard.