iPad লেবেলটি সহ পোস্টগুলি দেখানো হচ্ছে৷ সকল পোস্ট দেখান
iPad লেবেলটি সহ পোস্টগুলি দেখানো হচ্ছে৷ সকল পোস্ট দেখান

বুধবার, ৬ ফেব্রুয়ারি, ২০১৩

Decorator design pattern in Objective C


To extend or modify the behavior of an instance at run-time decorator design pattern is used. Decorating can provide new behavior at run-time for individual objects. Inheritance is used to extend the functionalities of a class. But if you need to add behavior not without changing object, you can do it with decorator pattern.

Let's imagine a scenario. We have a burger shop. Customer can order burger with cheese, french fries, soft drinks etc. We have a component or base class named "Burger". If we call this, we will get only burger. If we also need cheese, french fries or soft drinks, we will decorate them with our burger component.
To do this we need a component class named "Burger" and Decorator class named "Cheese", "French fries" and "Soft drinks". This decorators class will extend the behavior of component "Burger" class and in run time add decorated behavior to components.

Declaration of component class "Burger" goes here:

#import <Foundation/Foundation.h>

@interface Burger : NSObject

-(NSString *)getDescription;
-(double)getPrice;

@end

Implementation of component class "Burger" goes here:

#define burgerPrice 120.0

#import "Burger.h"

@implementation Burger

-(id)init
{
    self=[super init];
    if (self) {
        //do initialization
    }
    return self;
}

//returns the description of burger

-(NSString *)getDescription
{
    return @"Burger";
}

//return price of burger

-(double)getPrice
{
    return burgerPrice;
}

@end

//Declaration of Cheese decorator class

#import "Burger.h"

@interface Cheese : Burger
{
    @private Burger *burger;
}

@property Burger *burger;

-(id)initWithBurger:(Burger *)theBurger;

@end

//implementation of Cheese class

#import "Cheese.h"
#define cheesePrice 30.0;

@implementation Cheese
@synthesize burger;
-(id)initWithBurger:(Burger *)theBurger
{
    self=[super init];
    if (self)
    {
        self.burger=theBurger;
    }
    return self;
}

//Adding cheese description
-(NSString *)getDescription
{
    return [NSString stringWithFormat:@"%@ ,cheese",self.burger.getDescription];
}

//Adding cheese price

-(double)getPrice
{
    return self.burger.getPrice+cheesePrice;
}

@end

//Declaration of French fries class

#import "Burger.h"

@interface FrenchFries : Burger
{
    Burger *burger;
}

@property Burger *burger;

-(id)initWithBurger:(Burger *)theBurger;

@end


//Implementation of French fries  decorators

#import "FrenchFries.h"
#define frenchFriesPries 20;

@implementation FrenchFries
@synthesize burger;

-(id)initWithBurger:(Burger *)theBurger
{
    self=[super init];
    if (self)
    {
        self.burger=theBurger;
    }
    return self;
}

//Add description of French fries

-(NSString *)getDescription
{
    return [NSString stringWithFormat:@"%@, frenc fries",self.burger.getDescription];
}

//Add price of French fries

-(double)getPrice
{
    return self.burger.getPrice+frenchFriesPries;
}

@end

//Declaration of Soft drinks decorators

#import "Burger.h"

@interface SoftDrinks : Burger
{
    @private Burger *burger;
}

@property Burger *burger;

-(id)initWithBurger:(Burger *)theBurger;

@end

//Implementation of Soft drinks decorators 

#import "SoftDrinks.h"
#define softDrinksPrice 50

@implementation SoftDrinks
@synthesize burger;

-(id)initWithBurger:(Burger *)theBurger

{
    self=[super init];
    if (self)
    {
        self.burger=theBurger;
    }
    return self;
}


//Add description of softdrinks

-(NSString *)getDescription
{
    return [NSString stringWithFormat:@"%@, soft drinks",self.burger.getDescription];
}

//Add price of softdrinks

-(double)getPrice
{
    return self.burger.getPrice+softDrinksPrice;
}

@end


Here's a test program that creates a Burger instance which is fully decorated (i.e., with cheese, french fries, soft drinks), and calculate cost of Burger:



    Burger *burger=[[Burger alloc] init];
    NSLog(@"Ordered item: %@ price: %lf",burger.getDescription,burger.getPrice);
    
    Burger *burgerWithCheese=[[Cheese alloc] initWithBurger:burger];
    NSLog(@"Ordered item: %@ price: %lf",burgerWithCheese.getDescription,burgerWithCheese.getPrice);
    
    Burger *burgerWithCheeseNfrenchFries=[[FrenchFries alloc] initWithBurger:burgerWithCheese];
    NSLog(@"Ordered item: %@ price: %lf",burgerWithCheeseNfrenchFries.getDescription,burgerWithCheeseNfrenchFries.getPrice);
    
    Burger *BurgerWithAll=[[SoftDrinks alloc] initWithBurger:burgerWithCheeseNfrenchFries];
    NSLog(@"Ordered item: %@ price %lf",BurgerWithAll.getDescription,BurgerWithAll.getPrice);


The output of this program is given below:

Ordered item: Burger price: 120.000000
Ordered item: Burger ,cheese price: 150.000000
Ordered item: Burger ,cheese, frenc fries price: 170.000000
Ordered item: Burger ,cheese, frenc fries, soft drinks price 220.000000

শুক্রবার, ২০ এপ্রিল, ২০১২

iOS Gesture Recognizer: Tap, Pinch Zoom, Rotate, Swipe, Pan, Long Press

The UIGestureRecognizer help us detecting and responding to the various UI gestures of iOS devices. UIGestureRecognizer is an abstract class, which provides the following subclasses:
  1. UITapGestureRecognizer
  2. UIPinchGestureRecognizer
  3. UIRotationGestureRecognizer
  4. UISwipeGestureRecognizer
  5. UIPanGestureRecognizer
  6. UILongPressGestureRecognizer

Gesture Recognizer Examples:

We have defined a recognizer for managing taps. We have specified that there are two taps required, with just one touch (finger). The @selector specifies the method that will be called when the gesture is recognized.

// -----------------------------
// One finger, two taps
// -----------------------------
// Create gesture recognizer
UITapGestureRecognizer *oneFingerTwoTaps = 
  [[[UITapGestureRecognizer alloc] initWithTarget:self action: 
@selector(oneFingerTwoTaps)] autorelease];
 
// Set required taps and number of touches
[oneFingerTwoTaps setNumberOfTapsRequired:2];
[oneFingerTwoTaps setNumberOfTouchesRequired:1];
 
// Add the gesture to the view
[[self view] addGestureRecognizer:oneFingerTwoTaps];
Below is a recognizer for two fingers, two taps:
 
// -----------------------------
// Two fingers, two taps
// -----------------------------
UITapGestureRecognizer *twoFingersTwoTaps = 
  [[[UITapGestureRecognizer alloc] initWithTarget:self action: 
@selector(twoFingersTwoTaps)] autorelease];
[twoFingersTwoTaps setNumberOfTapsRequired:2];
[twoFingersTwoTaps setNumberOfTouchesRequired:2];
[[self view] addGestureRecognizer:twoFingersTwoTaps];
The following gestures recognize swipes up and down:
 
// -----------------------------
// One finger, swipe up
// -----------------------------
UISwipeGestureRecognizer *oneFingerSwipeUp = 
  [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:
 @selector(oneFingerSwipeUp:)] autorelease];
[oneFingerSwipeUp setDirection:UISwipeGestureRecognizerDirectionUp];
[[self view] addGestureRecognizer:oneFingerSwipeUp];
 
// -----------------------------
// One finger, swipe down
// -----------------------------
UISwipeGestureRecognizer *oneFingerSwipeDown = 
  [[[UISwipeGestureRecognizer alloc] initWithTarget:self action: 
@selector(oneFingerSwipeDown:)] autorelease];
[oneFingerSwipeDown setDirection:UISwipeGestureRecognizerDirectionDown];
[[self view] addGestureRecognizer:oneFingerSwipeDown];
Two recognize two fingers rotating on a view:
 
// -----------------------------
// Two finger rotate  
// -----------------------------
UIRotationGestureRecognizer *twoFingersRotate = 
  [[[UIRotationGestureRecognizer alloc] initWithTarget:self action: 
@selector(twoFingersRotate:)] autorelease];
[[self view] addGestureRecognizer:twoFingersRotate];
And finally, two finger pinch:
 
// -----------------------------
// Two finger pinch
// -----------------------------
UIPinchGestureRecognizer *twoFingerPinch = 
  [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:
 @selector(twoFingerPinch:)] autorelease];
[[self view] addGestureRecognizer:twoFingerPinch];

// -----------------------------
// Two finger pan
// ----------------------------- 
panGesture = [[[UIPanGestureRecognizer alloc] initWithTarget:self action: 
@selector(panGestureMoveAround:)] autorelease];
    [panGesture setMaximumNumberOfTouches:2];
    [panGesture setDelegate:self];
 
// -----------------------------
// Long Press Gesture
// ----------------------------- 
UILongPressGestureRecognizer *longPressRecognizer = 
         [[UILongPressGestureRecognizer alloc]
         initWithTarget:self 
         action:@selector(longPressDetected:)];
    longPressRecognizer.minimumPressDuration = 3;
    longPressRecognizer.numberOfTouchesRequired = 1;
    [self.view addGestureRecognizer:longPressRecognizer];
    [longPressRecognizer release];
 

Gesture Recognizer Action Methods:

For each of the above definitions, below are the associated action methods.
 
/*--------------------------------------------------------------
* One finger, two taps 
*-------------------------------------------------------------*/
- (void)oneFingerTwoTaps
{
  NSLog(@"Action: One finger, two taps");
}
 
/*--------------------------------------------------------------
* Two fingers, two taps
*-------------------------------------------------------------*/
- (void)twoFingersTwoTaps {
  NSLog(@"Action: Two fingers, two taps");
} 
 
/*--------------------------------------------------------------
* One finger, swipe up
*-------------------------------------------------------------*/
- (void)oneFingerSwipeUp:(UISwipeGestureRecognizer *)recognizer 
{ 
  CGPoint point = [recognizer locationInView:[self view]];
  NSLog(@"Swipe up - start location: %f,%f", point.x, point.y);
}
 
/*--------------------------------------------------------------
* One finger, swipe down
*-------------------------------------------------------------*/
- (void)oneFingerSwipeDown:(UISwipeGestureRecognizer *)recognizer 
{ 
  CGPoint point = [recognizer locationInView:[self view]];
  NSLog(@"Swipe down - start location: %f,%f", point.x, point.y);
}
 
/*--------------------------------------------------------------
* Two finger rotate   
*-------------------------------------------------------------*/
- (void)twoFingersRotate:(UIRotationGestureRecognizer *)recognizer 
{
  // Convert the radian value to show the degree of rotation
  NSLog(@"Rotation in degrees since last change: %f", [recognizer rotation] *  
(180 / M_PI));
}
 
/*--------------------------------------------------------------
* Two finger pinch
*-------------------------------------------------------------*/
- (void)twoFingerPinch:(UIPinchGestureRecognizer *)recognizer 
{
  NSLog(@"Pinch scale: %f", recognizer.scale);
}
 
/*--------------------------------------------------------------
* Two finger pan
*-------------------------------------------------------------*/ 
-(void)panGestureMoveAround:(UIPanGestureRecognizer *)gesture;
{
    UIView *piece = [gesture view];
 
//We pass in the gesture to a method that will help us align our touches
 so that the pan and pinch will seems to originate between the fingers 
instead of other points or center point of the UIView
    [self adjustAnchorPointForGestureRecognizer:gesture];
 
    if ([gesture state] == UIGestureRecognizerStateBegan ||
 [gesture state] == UIGestureRecognizerStateChanged) {
 
        CGPoint translation = [gesture translationInView:[piece superview]];
        [piece setCenter:CGPointMake([piece center].x + translation.x, [piece center].y+ 
translation.y*0.1)];
        [gesture setTranslation:CGPointZero inView:[piece superview]];
    }else if([gestureRecognizer state] == UIGestureRecognizerStateEnded)
    {
       //Put the code that you may want to execute when the UIView became 
       larger than certain value or just to reset them back to their original
       transform scale
    }
} 

/*--------------------------------------------------------------
* Long press
*-------------------------------------------------------------*/ 
- (IBAction)longPressDetected:(UIGestureRecognizer *)sender 
{
    statusLabel.text = @"Long Press";
}

বুধবার, ২১ মার্চ, ২০১২

Create .ipa file or submitting app to appstore with static library like Core-Plot

In one of my project for beta testing, I select "Product->Archive". The archiving completes successfully, and the Organizer shows the archive file that was just created.

I select the archive, click on the "Share" button, it prompts me for location  to store it, and then creates a .xcarchive package to the location. I was expecting it to generate a .ipa, but it never presented me with any options.

 
Then I try to submit app and Xcode 4 was giving me the following error: “[Your App Name] does not contain a single-bundle application or contains multiple products. Please select another archive, or adjust your scheme to create a single-bundle application.”



It was a static library adding issue. I am specifically using Core Plot and it’s instruction set hasn’t been updated for Xcode 4 yet.  Here are the things I had to do to get Core Plot to bundle correctly with my App to submit it:
  1. Click on the Core Plot project which should be a child of your App’s project.
  2. Click on the Project CorePlot-CocoaTouch and go to the Build Settings.  Set “Skip Install” to Yes.
  3. Click on the CorePlot-CocoaTouch target and set “Skip Install” to Yes.
  4. Click Build Phases and under Copy Headers, move all of the Public and Private entries to the Project section.
You should then be able to build your project for Archive and submit to Apple.

শুক্রবার, ৩ ফেব্রুয়ারি, ২০১২

Sending formatted email

Hi guys, in this tutorial I will show you how to send email using iPhone mail apps. Sending email from mail apps is easy and comfortable. You need to just use a mailto url + stringByAddingPercentEscapesUsingEncoding + HTML.

Easier way to send e-mail on your iPhone application is using a mailto url.

        NSURL *url = [[NSURL alloc] initWithString:@"mailto:me@me.com?subject=subject&body=Hi"];

        [[UIApplication sharedApplication] openURL:url];

Of course you can use a format to include your own dynamic text, but the url string must be url escaped. Cocoa provides a nice way to escape URLs with stringByAddingPercentEscapesUsingEncoding:
So, we can escape URL from email body as following way: 
NSString *encodedBody =[eMailBody stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

The only problem left was representing tabular data. The body parameter of mailto is actually parsed as HTML.
So, amazing as it seems, this code works:


            NSString *eMailBody = @"<table><tr><td style='text-align:right'><b>Name</b>:</td><td>Zubair</td></tr><tr><td style='text-align:right'><b>Surname</b>:</td><td>Raihan</td></tr><tr><td style='text-align:right'><b>Occupation:<b/></td><td>Programmer</td></tr></table>";
           
            NSString *encodedBody =[eMailBody stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
           
            NSString *urlString =[NSString stringWithFormat:@"mailto:me@me.com?subject=HiPhone&body=%@", encodedBody];
            NSURL *url = [[NSURL alloc] initWithString:urlString]; 
            [[UIApplication sharedApplication] openURL:url];



That’s it now we are ready for sending email using mail apps.

Device vs Simulator
Since the iPhone simulator does not have a Mail.app, you can use e-mail URLs only in the actual device. As a matter of fact, it’s better to create specific simulator/device code:

#if TARGETIPHONESIMULATOR           

     //compiler specific code           

#else           

     // device specific code           

#endif


In my app, I use a UIWebV iew in the simulator code, so I can preview the email HTML text in the simulator.