Wednesday, March 23, 2011

release Vs drain in autorelease pool

An autorelease pool stores objects that are sent a release or autorelease message and are deallocated when the autorelease pool itself is drained.

If a question like "what to use?  'drain' or 'release' ? comes in your mind, below is the simple resolve for your question.

release:
In a reference-counted environment, since an autorelease pool cannot be retained , this method causes the receiver to be deallocated. When an autorelease pool is deallocated, it sends a 'release' message to all its autoreleased objects. Also, In a garbage-collected environment, this method is a no no.

- (void)release

drain:
In a reference-counted environment, releases and pops the receiver; in a garbage-collected environment, triggers garbage collection if the memory allocated since the last collection is greater than the current threshold.

- (void)drain

Conclusion:
From the above brief discussion it is clear that, we should always use 'drain' over 'release' for an autorelease pool(be the Cocoa or Cocoa touch).



Wednesday, March 16, 2011

Determine if string is numeric only

 In Objective-C there is no in-built method which determines whether the given string is numeric only or is an alphanumeric, but has provided ways to do that.


The objective can be achieved using the NSCharacterSet class, which provides a set of characters.
Using below method we can identify the whether the string is numeric or alphanumeric.


- (void)testNumeric{
      NSString *result=@"2011";
      if([self isNumeric:result]){
// Numeric
        }else{
  // Alphanumeric
        }
}
- (BOOL)isNumeric:(NSString*)inputString{
        BOOL isValid=NO;
       NSCharacterSet *alphaNumbersSet = [NSCharacterSet decimalDigitCharacterSet];
       NSCharacterSet *stringSet = [NSCharacterSet characterSetWithCharactersInString:inputString];
       isValid = [alphaNumbersSet isSupersetOfSet:stringSet];
       return isValid;
}


decimalDigitCharacterSet is a character set containing the characters in the category of Decimal Numbers,i.e, the set with all numeric characters.


Method characterSetWithCharactersInString: returns the character set containing the characters in the given string, i.e, the set with characters '2','0','1','1' in our case.


Using the two sets, we determine whether all characters of inputString is contained in alphaNumbersSet.


Happy coding.

Wednesday, March 2, 2011

Auto Play youtube video in iPhone / iPad


Playing a youtube video in iOS sdk can be done in two ways:
1) Invoke the native youtube player in the device.
2) Open the youtube video link in a WebView.
3) Autoplay the youtube video using WebView .

Method 1:
This method utilizes the Apple's URLScheme to play youtube video by launching the youtube application on the device. This involves a simple call to the openURL method of UIApplication class as below:

NSURL *url=[NSURL URLWithString:@"http://www.youtube.com/v/IkvXcvb7rkg?f=user_favorites&app=youtube_gdata\"];
[[UIApplication sharedApplication] openURL:url];



This method may seem easy, but it's at the cost that the video will be played in other application
and your application will not be called even after the video playing is finished.
There is no other way to return to your application after video playing is done.

Method 2:
This method involved a little bit of tweak around the UIWebView control.
In this method a youtube embed code is constructed and is loaded in the WebView control in the application.
The WebView displays the video thumbnail and a play button over the thumbnail. As the user taps on the play
button the video is launched in QuickTime player and after the video playing is done, control is returned to the application.



                                                           (YouTube video in WebView with play button )

So, with a little bit of tweak we can retain the control in the application.

    NSString *htmlString =@"<html><head>"
        "<meta name = \"viewport\" content = \"initial-scale = 1.0, user-scalable = no, width = 212\"/></head>"
        "<body style=\"background:#FFFFF;margin-top:20px;margin-left:0px\">"
        "<div><object width=\"320\" height=\"240\">"
        "<param name=\"wmode\" value=\"transparent\"></param>"
        "<embed src=\"http://www.youtube.com/v/Hu684V2lB3Q?f=user_favorites&app=youtube_gdata\""
        "type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"320\" height=\"240\"></embed>"
        "</object></div></body></html>";

    [webView loadHTMLString:htmlString baseURL:nil];



Method 3:
This method takes takes the 'Method 2' one step ahead by utilizing the delegate methods of WebView control
to auto play the video in QuickTime player as soon as the WebView loading is finished.



(Playing video in QuickTime player)


You need to assign the class as WebView delegate:

webView.delegate=self;

The idea is to find the play button on the WebView and send the button touch event to the control to play the video.

Complete code will look like this:

    NSString *htmlString =@"<html><head>"
        "<meta name = \"viewport\" content = \"initial-scale = 1.0, user-scalable = no, width = 212\"/></head>"
        "<body style=\"background:#FFFFF;margin-top:20px;margin-left:0px\">"
        "<div><object width=\"320\" height=\"240\">"
        "<param name=\"wmode\" value=\"transparent\"></param>"
        "<embed src=\"http://www.youtube.com/v/Hu684V2lB3Q?f=user_favorites&app=youtube_gdata\""
        "type=\"application/x-shockwave-flash\" wmode=\"transparent\" width=\"320\" height=\"240\"></embed>"
        "</object></div></body></html>";

    webView.delegate=self;
    [webView loadHTMLString:htmlString baseURL:nil];
   
- (void)webViewDidFinishLoad:(UIWebView *)_webView {
    UIButton *b = [self findButtonInView:_webView];
    [b sendActionsForControlEvents:UIControlEventTouchUpInside];
}

- (UIButton *)findButtonInView:(UIView *)view {
    UIButton *button = nil;
   
    if ([view isMemberOfClass:[UIButton class]]) {
        return (UIButton *)view;
    }
   
    if (view.subviews && [view.subviews count] > 0) {
        for (UIView *subview in view.subviews) {
            button = [self findButtonInView:subview];
            if (button) return button;
        }
    }
    return button;
}

I prefer Method 3 over all the methods but you choose the one that suits your need.
Happy coding...