Sunday, August 31, 2008

What Robert Penner Never Told You About His 'Easing Equations'

In his epic work "Programming Macromedia Flash MX" Robert Penner introduced his easing equations to the world. Of course, the equations were standard curves used in interpolation throughout animation programming. However, these curves had never before been available in Flash. (Later, Macromedia would add them to the standard Flash libraries.)

Interestingly, it turns out that these curves with the names NSAnimationEaseInOut, NSAnimationEaseIn, NSAnimationEaseOut had existed on OS X/NeXTStep computers for nearly 15 years before Penner would bring them to Flash. Of course, the developers of Flash must have used NSAnimations before they brought the term 'easing' to the mainstream through the Flash UI. (Outside of Flash/COCOA the term 'easing' is never used in formal academic circles and is always refered to as interpolation.)

It infact appears that many ActionScript classes have Object-C/COCOA ancestors such as hitTest, NSURLRequest, NSURL, and many more.

Wednesday, August 27, 2008

Add, Set, and Delete Cookies in UIWebView with NSHTTPCookieStorage

NSHTTPCookieStorage allows you to update the cookies for every request made from your application. UIWebViews will respond to this changes in cookies at run time and NSHTTPCookieStorage allows you to listen for changes in cookies as the are normaly set in the browser.

To get the cookies for any url use:
NSHTTPCookieStorage* cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray* theCookies = [cookieStorage cookiesForURL:[NSURL URLWithString:@"http://example.com"]];


This makes it possible to easily login or logout a user from a website presented in your UIWebView.

Checkout NSHTTPCookieStorage* for all the details.

Labels: , , ,

Monday, August 25, 2008

AdMob Ads break in UIWebView

AdMob ads are broken in UIWebViews (a UIWebView is an iPhone native browser control) for two reasons.
  • AdMob requires a user agent and when you tell AdMob you are on an iPhone AdMob will provide ads with direct links to the App Store. This would be great, but Apple servers respond with "Internal Server Error" when AdMob ads link to the appstore through UIWebView. The same links work great in iPhone Safari.
  • When a page containing a UIWebView loads with an AdMob ad, the page is instantly redirected to about:blank. Canceling this redirect in shouldStartLoadWithRequest causes other links on the page to become unresponsive!
  • If you know how to get this working please comment.

Update: after some badgering AdMob has responded here.

Labels: , , ,

Sunday, August 24, 2008

Simple iPhone image loader class uses NSThread and NSData dataWithContentsOfURL.

This class, APSSimpleWebImageView, extends the UIImageView class with the method
- (void) loadStringURL:(NSString*)url.

loadStringURL takes the URL of the image you wish to load and loads that image asynchronously.
Download Example Code Here

Create an APSSimpleWebImageView as you would a normal UIImageView and then
invoke loadStringURL with the NSString url of the image you wish to load as follows:
APSSimpleWebImageView* myImageView = [[APSSimpleWebImageView alloc] initWithFrame:CGRectMake(0,0,100,100)];
[myImageView loadStringURL:@"http://example.com/image.jpg"];

(For the complete code listing download the example code.)

Following are a few points of interest from the sample code:
  • (onLoadSuccess andonLoadFailure are optional call backs that can be used to receive notification that the image has appeared.)


  • To load asyncrounsly we invoke NSData dataWithContentsOfURL on a new thread, using NSThread detachNewThreadSelector.

    [NSThread detachNewThreadSelector:@selector(performAsyncLoadWithURL:)
    toTarget:self withObject:[NSURL URLWithString:urlString]]


  • We must create an autrelease pool in performAsyncLoadWithURL: to prevent the new thread from leaking. (Each thread must have an autorelease pool.)

  • performAsyncLoadWithURL: will then block its thread as it performs the image load:
    NSData* imageData = [NSData dataWithContentsOfURL:url options:NSMappedRead error:&loadError];

  • Finally after the image has loaded, we will invoke our load complete call back on the main thread
    [self performSelectorOnMainThread:@selector(loadDidFinishWithError:)
    withObject:loadError waitUntilDone:YES];


    Notice waitUntilDone:YES causes our loading thread to block while the approprate loadDidFinish method is invoked on the main thread. This prevents our imageData object from getting released by the autorelease pool that will be drained in the last line of performAsyncLoadWithURL.

Download Example Code Here



Saturday, August 23, 2008

Asynchronous image loading on the iPhone NSURLConnection or NSThread and NSData dataWithContentsOfURL

In order to load images asyncornisly on the iPhone you must choose to use NSURLConnection or NSData dataWithContentsOfURL along with NSThread. I have decided to use threads to do my asynchronous image loading in spite of the following and rather hilarious warning from the Apple Threading Programming Guide.

"If you do not fully understand the implications of your design choices, you might encounter synchronization or timing issues, the severity of which can range from subtle behavioral changes to your application imploding gloriously and destroying user data. (Granted, it takes a lot of effort for you to cause your application to implode gloriously, but the fact that it is possible should serve as a warning not to skimp on your planning efforts.)"

When I am done, I shall publish my asynchronous web image loader in hopes that it may be helpful.

Load web image into iphone native applicaiton UIImage with no NSURLConnection code required

It turns out it is trivial to load images into iPhone native applications.
This simple function will do all of the work. No UIWebView required no NSURLConnection required. Just dataWithContentsOfURL.

-(UIImage*) newUIImageWithURLString:(NSString*)urlString
{
return [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]]];
}

Usage:

UIImage* myUIImage = [self newUIImageWithURLString:@"http://example.com/images/myimage.jpg"];

That's it!

It is important to note that +(NSData*) dataWithContentsOfURL:(NSURL*)url blocks. This will not do an asynchronous load. :( I am looking into another more involved solution that will load images on a separate thread.

Labels: , , ,

@property and assign, retain, copy

From The Objective-C 2.0 Programming Language here is how assign retain and copy will be effectively implemented by @synthesize and how they should be functionally implemented by you if not synthesized.

property = newValue;
// retain
if (property != newValue)
{
[property release];
property = [newValue retain];
}
// copy
if (property != newValue)
{
[property release];
property = [newValue copy];
}

Labels: , , ,