বাংলায় অবজেক্টিভ-সি, সুইফট এবং iOS অ্যাপ ও গেম ডেভ
  • ভূমিকা
  • অবজেক্টিভ-সি ব্যাসিক
    • প্রাথমিক ধারনা এবং Xcode
    • Objective-C এর ভিতরে আমাদের প্রিয় C
    • ফাংশন ও এর ব্যবহার
    • ক্লাস ও অবজেক্ট
    • প্রোপার্টি ও এর অ্যাট্রিবিউটের ব্যবহার
    • মেথড ও এর বিস্তারিত
    • প্রোটোকল
    • ক্যাটাগরি
    • ব্লক ও এর ব্যবহার
    • এক্সেপশন ও এরর হ্যান্ডেলিং
  • অ্যাপ ডেভেলপমেন্ট
    • টুলস সেটআপ এবং একটি সাধারণ হ্যালো ওয়ার্ল্ড অ্যাপ তৈরি
    • iOS অ্যাপে ব্যাসিক ইনপুট আউটপুট ও কিবোর্ড হ্যান্ডেলিং
    • আরও চ্যাপ্টার আসছে ...
  • সুইফ্ট ব্যাসিক
    • সুইফ্ট – অ্যাপলের নতুন চমক, পরিচিতি ও অন্যান্য
    • স্ট্রিং ও ক্যারেকটার টাইপ ভ্যারিয়েবল
    • কালেকশনস (অ্যারে ও ডিকশনারী), ইনুমারেশন ও ক্লোজার
    • ব্রাঞ্চিং ও লুপিং
    • ফাংশন ও মেথড
    • ক্লাস এবং স্ট্রাকচারের মধ্যে পার্থক্য
    • প্রোপার্টি
    • ইনহেরিটেন্স
    • ইনিশিয়ালাইজেশন, ডি-ইনিশিয়ালাইজেশন ও অপশনাল চেইনিং
    • এক্সটেনশন ও প্রোটোকল
  • গেম ডেভেলপমেন্ট
    • গেমস বনাম আপ্লিকেশন্স, গেমস বনাম গেমস (গেমসের প্রকারভেদ)
    • অতিরিক্ত প্রয়োজনীয় টুলস এবং তাদের পরিচিতি, ফ্রেমওয়ার্ক নির্বাচন (স্প্রাইটকিট, কোকোস-২D, ...)
    • স্থানাংক ব্যাবস্থা, দেয়ালের প্রথম ইট
    • ব্যাসিক কিছু ধারনাঃ স্প্রাইট(ছবি), অ্যানিমেশন, ফন্ট, সাউন্ড(শব্দ)
    • গেমঃ মহাকাশ-যুদ্ধ
      • একটি স্পেসশিপ তৈরি
      • গুলি ছোঁড়া
      • প্রতিপক্ষ স্পেসশিপ(গুলো)
      • আক্রমণ
    • গেম-সেন্টার
      • লিডার-বোর্ড (সেরাদের-তালিকা)
      • অ্যাচিভমেন্টস (অর্জন)
      • চ্যালেঞ্জ
  • অ্যাপ্লিকেশন সাবমিট, প্রচার ও সাফল্য
    • অ্যাপল ডেভেলপের আইডি খোলা
    • আসল ডিভাইসে অ্যাপ রান এর পদ্ধতি
    • আরও চ্যাপ্টার আসছে ...
  • অতিরিক্তঃ কিছু সাধারণ প্রশ্ন ও উত্তর
    • অবজেক্টিভ-সি (Objective-C) নাকি সুইফ্ট (Swift)?
    • আরও চ্যাপ্টার আসছে ...
Powered by GitBook
On this page
  1. অবজেক্টিভ-সি ব্যাসিক

ব্লক ও এর ব্যবহার

ভূমিকাঃ সহজভাবে বলতে গেলে ব্লক হচ্ছে অবজেক্টিভ-সি এর anonymous function. Google ডেফিনেশন অনুযায়ী অ্যানোনিমাস ফাংশন হচ্ছে- An anonymous function is a function that is not stored in a program file, but is associated with a variable whose data type is function_handle. Anonymous functions can accept inputs and return outputs, just as standard functions do. However, they can contain only a single executable statement. এর মাধ্যমে আপনি বিভিন্ন অবজেক্টের মধ্যে ইচ্ছামত স্টেটমেন্ট (Satement) পাস তথা আদান-প্রদান করতে পারবেন যেমনভাবে সাধারণ ডাটা আদান প্রদান করে থাকেন। উপরন্তু ব্লককে ক্লোজার (Closure) হিসেবে ব্যবহার করা হয় যাতে করে তার পক্ষে তার আসে পাশের ডাটা/অবস্থা নিয়ে কাজ করাও সম্ভব হয়। আস্তে আস্তে আমরা এ ব্যপারে বিস্তারিত জানতে চেষ্টা করব।

সিনট্যাক্সঃ ডিক্লেয়ারেশন-

returntype (^blockName) (argumentType);

ইমপ্লিমেন্টেশন-

returntype (^blockName) (argumentType) = ^{
    // Statements
};

এখানে "=" চিহ্নের বাম পাশের অংশটি হচ্ছে একটি ব্লক ভেরিয়েবল এবং ডান পাশের অংশ হচ্ছে ব্লকটি।

উদাহরণ-

void (^simpleBlock) (void) = ^{
    NSLog(@"This is a block that does not return anything and also has no argument!");
};

উপরের এই ব্লককে আমরা simpleBlock(); এভাবে কল করতে পারি।

ব্লক (Block) তৈরিঃ ব্লক তৈরির ব্যাপারটা মোটা মুটি ফাংশন তৈরির মতই। যেভাবে আপনি একটি ফাংশন ডিক্লেয়ার করে থাকেন ঠিক সেভাবেই একটি ব্লক ভেরিয়েবল ডিক্লেয়ার করতে পারেন আবার যেভাবে একটি ফাংশন এর ইমপ্লিমেন্ট করেন সেভাবে একটি ব্লককে ডিফাইন করতে পারেন। এমনকি যেভাবে একটি ফাংশনকে কল করেন ঠিক সেভাবেই একটি ব্লককেও কল করতে পারেন। নিচে একটি সহজ উদাহরণ দেখানো হল,

// main.m

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        // Declare and define the isPlaceOpen block
        BOOL (^isPlaceOpen)(void) = ^ {
            return YES;
        };

        // Use the block
        NSLog(@"Open state of the place is: %hhd ", isPlaceOpen());
    }
    return 0;
}

"^" চিহ্নটি ব্যবহার করে isPlaceOpen কে একটি ব্লক হিসেবে চিহ্নিত করা হয়। এটাকে অবজেক্টিভ-সি এর "*" পয়েন্টার চিহ্নের মতই মনে করতে পারেন অর্থাৎ শুধুমাত্র ডিক্লেয়ার করার সময় এটা গুরুত্বপূর্ণ কিন্তু এর পরে এটাকে সাধারণ ভেরিয়েবলের মতই মনে করে ব্যবহার করতে পারেন। নিচে আরেকটি উদাহরণ দেখি যেখানে আমাদের ব্লকটি দুইটি double টাইপের প্যারামিটারও গ্রহণ করে এবং সেগুলো ব্যবহার করে অল্প কিছু হিসাব করার পর একটি double টাইপ ডাটা রিটার্ন করে।

// main.m

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        // Declare the block variable
        double (^priceAfterTax)(double rawPrice, double totalTax);

        // Create and assign the block to the variable
        priceAfterTax = ^(double price, double tax) {
            return price + tax;
        };

        // Call the block
        double total = priceAfterTax(400, 40);

        NSLog(@"Total price after considering tax is: " @"%.2f Tk.", total);
    }
    return 0;
}

ক্লোজার (Closure)ঃ শুরুতেই বলা হয়েছে যে, সাধারণভাবে একটি ব্লক, ক্লোজার হিসেবেও ইমপ্লিমেন্টেড হয়। যেমন নিচের উদাহরণটি দেখে আমরা বিশ্লেষণ করতে পারি এখানে ক্লোজার ফিচার কোথায়,

// main.m

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        NSString *foodGenre = @"Italian";

        NSString *(^getFullItemName)(NSString *) = ^(NSString *itemName) {
            return [foodGenre stringByAppendingFormat:@" %@", itemName];
        };

        NSLog(@"%@", getFullItemName(@"Pizza"));    // Honda Accord
    }
    return 0;
}

আবারও বলি, ফাংশনের মতই একটি ব্লকের মধ্যে থেকে আপনি সেটার লোকাল ভেরিয়েবলগুলো, তার কাছে যে প্যারামিটারগুলো পাস করা হয়েছে সেগুলো এবং যেকোনো গ্লোবাল ভেরিয়েবল অ্যাক্সেস করতে পারবেন। কিন্তু ক্লোজার হিসেবে ব্লকের ব্যবহারের ফলে আপনি কিছু নন-লোকাল ভেরিয়েবলকেও ব্লকের মধ্যে থেকে অ্যাক্সেস করতে পারবেন। নন-লোকাল ভেরিয়েবল হচ্ছে ব্লকের বাইরের কোন ভেরিয়েবল কিন্তু ব্লকের Lexical Scope এর আওতাভুক্ত। উপরের উদাহরণে foodGenre সেরকম একটি নন-লোকাল ভেরিয়েবল যেটাকে getFullItemName ব্লকের মধ্যে থেকেও ব্যবহার করা গেছে।

মেথড প্যারামিটার হিসেবে ব্লক ব্যবহারঃ একটি পূর্ণ ব্লককে যেকোনো মেথডের প্যারামিটার হিসেবেও ব্যবহার করা যায়। ওই ব্লক যে কাজটা করে মূলত সেই কাজটিকেই একটা প্যাকেজ সরূপ একটি প্যারামিটার হিসেবে যেকোনো মেথডের কাছে দেয়া যায়। নিচে সেরকম একটা উদাহরণ দেখবো আমরা। প্রথমে আপনার প্রজেক্টকে এমনভাবে সাজিয়ে নিন যাতে সেখানে Food.h, Food.m এবং main.m এই ৩টি ফাইল থাকে নিচের মত করে,

// Food.h

#import <Foundation/Foundation.h>

@interface Food : NSObject

- (void)performActionWithCompletion: (void (^) ()) completionBlock;

- (void)calculatePriceWithTax: (double (^) (double price)) taxCalculatorBlock;

@end
// Food.m

#import "Food.h"

@implementation Food

- (void)performActionWithCompletion:(void (^) ()) completionBlock {

    NSLog(@"Started cooking...");
    completionBlock();
}

- (void)calculatePriceWithTax: (double (^) (double price)) taxCalculatorBlock {
    NSLog(@"Total price is: %f", taxCalculatorBlock(400));
}

@end
// main.m

#import <Foundation/Foundation.h>
#import "Food.h"

int main(int argc, const char * argv[])
{

    @autoreleasepool {
        Food *process = [[Food alloc]init];

        [process performActionWithCompletion: ^{
            NSLog(@"Cooking is finished and this block has been called to intimate action is performed.");
        }];

        [process calculatePriceWithTax: ^(double totalPrice) {
            return totalPrice + 40;
        }];

    }
    return 0;
}
Previousক্যাটাগরিNextএক্সেপশন ও এরর হ্যান্ডেলিং

Last updated 6 years ago

খেয়াল করুন, প্রথমে আমরা একটি ব্লক ভেরিয়েবল ডিক্লেয়ার করেছি তারপর আসল ব্লকটিকে সেই ভেরিয়েবলে অ্যাসাইন করেছি এবং তারপর ভেরিয়েবলের নাম ধরে সেই ব্লককে ব্যবহার বা কল করেছি। প্রোগ্রামটি রান করালে নিচের মত আউটপুট আসবে।

উপরের কোড গুলো দেখুন এবং বোঝার চেষ্টা করুন, প্রথমেই আমরা Food ক্লাসের ইন্টারফেসে দুইটি মেথড ডিক্লেয়ার করেছি যে দুটো মেথড প্যারামিটার হিসেবে দুই ধরনের দুইটি ব্লক গ্রহণ করে। প্রথম মেথডটির নাম performActionWithCompletion: এবং এটি এমন একটি ব্লককে প্যারামিটার হিসেবে গ্রহণ করে যে ব্লকটির কোন কিছু রিটার্ন করে না এবং যার কোন আর্গুমেন্টও নাই। কিন্তু দ্বিতীয় মেথডটি একটি ব্লককে তার প্যারামিটার হিসেবে গ্রহণ করে যে ব্লক একটি double টাইপ ডাটা রিটার্ন করে এবং যার একটি আর্গুমেন্টও আছে। এখন এই দুইটি মেথড এর ইমপ্লিমেন্টেশন লিখেছি Food.m ফাইলে। অর্থাৎ এই দুইটি মেথড কি কাজ করবে তার ডেফিনেশন। প্রথম মেথডটি শুরুতেই একটি ম্যাসেজ প্রিন্ট করবে এবং তারপর ওর কাছে প্যারামিটার হিসেবে আসা ব্লকটিকে কল করবে। তো, এক্ষেত্রে কি ঘটবে? ওই completionBlock নামক ব্লকের মধ্যে যা করতে বলা হয়েছে তাই ঘটবে। অর্থাৎ ওখানে লিখে রাখা আরও একটি ম্যাসেজ প্রিন্ট হবে। দ্বিতীয় মেথড এর কাজ হচ্ছে, তার কাছে আসা ব্লকটিকে কল করবে। কিন্তু যেহেতু ওই ব্লকটির প্যারামিটার আছে তাই ওকে কল করার সময় একটি ভ্যালুও পাস করে দিবে। আর ব্লক কল করা মানে কি? ওই ব্লকের মধ্যে যা করতে বলা হয়েছে তাই করবে। এক্ষেত্রে ওই ব্লকটি একটি ডাটা রিটার্ন করে এবং আসলে calculatePriceWithTax: মেথডটি সেই রিটার্ন করা ডাটাকেই নিজের মধ্যে থেকে প্রিন্ট করে। main.m ফাইলে আমরা উপরে উল্লেখিত মেথড দুইটি কল করেছি এবং তাদের প্যারামিটার হিসেবে দুইটি ভিন্ন রকম ব্লক কে পাঠিয়ে দিয়েছি। প্রোগ্রামট রান করালে নিচের মত আউটপুট আসবে,

ব্লক টাইপ ডিফাইন করাঃ typedef এর মাধ্যমে একটি ব্লক টাইপ তৈরি করা যায় যাতে করে ব্লক ব্যবহারের সময় এর সিনট্যাক্স এলোমেলো না হয়ে যায় এবং ওই ব্লকটিকে আরও সহজ এবং সংক্ষেপ নামে ব্যবহার করা যায়। এ ব্যাপারে এবং উপরের টপিক গুলোর আরও বিস্তারিত থাকবে আমাদের সম্ভাব্য কাগুজে বইয়ে। বই এর আপডেট পেতে লাইক দিয়ে রাখতে পারেন ।

Originally Posted

এখানে
Here
Screen Shot 2014-06-11 at 1.20.13 PM
Screen Shot 2014-06-11 at 2.23.24 PM