How to send tweets on iOS 5 and stay compatible with older versions

November 1st, 2011

With the new Twitter framework it's much easier to integrate apps with this service, except when you have to run on older iOS versions. If integration is not imperative and you can skip Twitter feature for older clients you still have to write your code in a way that the app does not crash on iOS 4 or earlier.

The first step is to add Twitter framework to the project. You do it as usual but change 'Required' setting to 'Optional' so if the framework is not available the app will be able to start anyway.

Next in your view controller import <Twitter/Twitter.h> and add the following method:

- (IBAction)tweet:(NSString *)text image:(UIImage *)image {
  if ([TWTweetComposeViewController canSendTweet]) {
    TWTweetComposeViewController *controller =
      [[[TWTweetComposeViewController alloc] init] autorelease];
    [controller setInitialText:text];
    if (image) {
      [controller addImage:image];
    }
    [self presentModalViewController:controller animated:YES];
  }
}

It will work on iOS 5 but won't on earlier versions and the reason is that we try to load TWTweetComposeViewController class and fail to do so. What we should do is to remove the direct reference to it and load it in a 'safe' way:

- (IBAction)tweet:(NSString *)text image:(UIImage *)image {
  Class cclass = NSClassFromString(@"TWTweetComposeViewController");
  if (cclass && [cclass canSendTweet]) {
    id controller = [[[cclass alloc] init] autorelease];
    [controller setInitialText:text];
    if (image) {
      [controller addImage:image];
    }
    [self presentModalViewController:controller animated:YES];
  }
}

This second implementation will work on any iOS version. The same approach could be used in all other cases when you have to make use of some new iOS feature and stay compatible with previous releases.

Disappointed with Adfonic

October 27th, 2011

I've tried to use Adfonic in Deviations app and see how it compares to AdMob. I gave it a part of the screen next to the AdMob so they use the same 320x50 size. Over the last several days Adfonic reports 2306 impressions and 0 clicks. I guess it's time to say goodbye to Adfonic.

I'm also playing with InstallWall and AppCircle; so far I can't say that they were a great success but let's see how it goes.

If you know some other services to promote or monetize the app I'd be happy to try...

Evolution of Objective-C properties

October 27th, 2011

I'm writing code in Objective-C for just several years but it's quite amazing to see how the language, compiler and its primary IDE, Xcode, evolve. And the language in particular. Initially it was a thin addition to the C language to provide notion of objects and it remained so for a long time, but now every year we see new features coming to the language. Below I have two classes, DataBagX and DataBagY to illustrate the changes.

The first class, DataBagX, is the class that I would have written in 2008. Note that there is no special syntax for properties: you have to define instance variables, getters and setters. What you call property is a pure naming convention; you have to analyze public methods to figure out that there are two properties: prop1 and prop2.

What many people really hate about this approach to class definition is that instance variables are exposed in public interface file. It's not just wrong logically because you reveal implementation details but you also have to add forward class definitions for contained objects or include their header files, which are completely irrelevant to the clients of the class being defined.

The positive side of such definition is simplicity—you don't have to know much of the language to understand what's going on. Here are instance variables, and there are methods that work with them.

DataBagX.h

@interface DataBagX : NSObject {
@private
  int _prop1;
  double _prop2m;
}

- (int)prop1;
- (void)setProp1:(int)prop1;
- (double)prop2;
- (void)setProp2:(double)prop2;

@end

DataBagX.m

#import "DataBagX.h"

@implementation DataBagX

- (int)prop1 {
  return _prop1;
}

- (void)setProp1:(int)prop1 {
  _prop1 = prop1;
}

- (double)prop2 {
  return _prop2m / 2;
}

- (void)setProp2:(double)prop2 {
  _prop2m = prop2 * 2;
}

@end

Fast forward to 2011: here is the same class rewritten using the new language features. The most noticeable thing is that interface contains just necessary information in a very compact form. We have two properties? So here they are: just a keyword of property definition, type and name. All the implementation details go into implementation file.

And implementation is quite spectacular too: for ordinary properties it's just enough to synthesize it in one line. Also note how definition of instance variables is possible in implementation file, right where it should be from the beginning.

DataBagY.h

#import 

@interface DataBagY : NSObject

@property int prop1;
@property double prop2;

@end

DataBagY.m

#import "DataBagY.h"

@implementation DataBagY {
@private
  double _prop2m;
}

@synthesize prop1 = _prop1;

- (double)prop2 {
  return _prop2m / 2;
}

- (void)setProp2:(double)prop2 {
  _prop2m = prop2 * 2;
}

@end

These are just several improvements that you will encounter most frequently but change class definitions quite dramatically. I'd recommend you to watch WWDC 2011 videos to learn more about the Objective-C and "Session 322 - Objective-C Advancements in Depth" in particular.