যারা iOS app ডেভলপমেন্ট করতে চান, অন্য কোন ল্যাঙ্গুয়েজে কাজ করে অভ্যস্ত এবং দ্রুত অবজেকটিভ সি আয়ত্ব করতে চান তাদের জন্য এই ডকুমেন্ট
কোন প্রোগ্রামিং ল্যাঙ্গুয়েজ জানা থাকতে হবে কারন টিউটোরিয়াল লেখার সময় ধরেই নেয়া হয়েছে আপনি কোন প্রোগ্রামিং ল্যাঙ্গুংয়জ জানেন, আগে কোন ল্যাঙ্গুলেয় না জানা থাকলে এই ডকুমেন্ট দুর্বোধ্য মনে হতে পারে।
ফোকাস করা হয়েছে অবজেকটিভ সি এর নিজস্ব বিষয়গুলোতে যেন ডেভলপার খুব দ্রুত শিখতে পারেন।
সাধারণ স্ট্রাকচার:
#import <Foundation/Foundation.h> // এটা হলো ফাউন্ডেশন ফ্রেমওয়ার্ক ইম্পোর্ট করা, Foundation ফোল্ডারে Foundation.h নামে একটি হেডার ফাইল আছে সেটাকে ইম্পোর্ট করা হলো।
int main(int argc, const char * argv[]){ // এটা মেইন মেথড, প্রোগ্রাম এক্সিকিউশন এখান থেকে শুরু হয়।
@autoreleasepool{ // মেথড কিছু রিটার্ন করলে মেথডের অবজেক্টগুলো অটোমেটিক খালি(nil) করে দেয়। এই autoreleasepool ব্লকের ভিতরে উদাহরণের কোড গুলো লিখব।
NSLog("Hello world"); // কনসোলে কিছু প্রিন্ট করে দেখতে। জাভার println() এর মত
}
return 0;
}
LOG:
কোন কিছু কনসোলে প্রিন্ট করে দেখতে NSLog ব্যবহার করা হয়। এখানে NS এসেছে Next Step থেকে, আর NeXTSTEP হলো এ্যাপলের অনেক পুরাতন একটি অপারেটিং সিস্টেম।
উদা:
NSLog(@"Hello world");
কোন টেক্সট লেখা বা স্ট্রিং লিখতে হলে @ লিখে “ডাবল কোটেশনের” ভিতরে লিখতে হবে। এখানে @ চিহ্নটি কম্পাইলার ইন্ডিকেটর। এতে কম্পাইলার বুঝতে পারে যে এটা অবজেকটিভ সি এর স্ট্রিং।
Concatenation of string:
উদা:
int appleAmount = 4;
int penAmount = 3;
NSLog(@"There are %i apples and %i pens", appleAmount, penAmount);
প্রথম লাইনে- appleAmount নামে একটি ভেরিয়েবল নেয়া হয়েছে যার ভেলু 4 এসাইন করা হয়েছে।
তৃতীয় লাইনে- কোন লেখার মাঝে বা শেষে অন্য লেখা যোগ করতে হলে প্লেস হোল্ডার ইন্ডিকেটর(%i) দিতে হবে।
উদাহরণে int এর জন্য %i ব্যবহার হয়েছে। এভাবে
ফ্লোটিং পয়েন্ট float এ %f
সিঙ্গেল কারেক্টার char এ %c
একাধিক লেখা যোগ করতে ধারাবাহিকভাবে পর পর ভেরিয়েবল গুলা কমা কমা দিয়ে লিখতে হবে। উদাহরণে লগ লাইনে, প্রথম ভেরিয়েবলের( appleAmount) ডাটা প্রথম %i কে ইন্ডিকেট করবে।
আউটপুট হবে : There are 4 apples and 3 pens
If else-
int numOfSomething = 8;
if(numOfSomething > 5){
NSLog(@"It is too much");
} else{
NSLog(@"It is not too much");
}
সাধারন if স্টেটমেন্ট । অন্যান্য লেঙ্গুয়েজের মতই if এ ==, <> || && এগুলো ব্যবহার করা যায়। comparison operator পরে দেখানো হয়েছে।
Switch case default:
উদা:
int amount = 3;
switch (amount){
case 1:
NSLog(@"This is one");
Break;
case 2: // no break used so that if amount is 2 then case 3 will also execute
case 3:
NSLog(@"This is three");
Break;
default:
NSLog(@"This is out of range");
Break;
}
এখানে কোন বিশেষ কিছু নাই। এটা অন্যান্য ল্যাঙ্গুয়েজের মতই।
Operators and Expressions:
Arithmetic operators are + – * /
উদা:
int a = 33;
int b = a +7;
b += 8;
Operator precedence (কোন অপারেটরের কাজ আগে হবে):
উদা:
result = 2 + 3 * 10; // এখানে ১০ এর সাথে ৩ গুন হবে আগে তারপর ২ যোগ হবে।
result = (2 + 3) * 10; // এখানে আগে ২ এর সাথে ৩ যোগ হবে তারপর ১০ গুন হবে।
Equality and comparison:
উদা:
if( a == b){
}
এখানে == এর যায়গার দরকার মত এগুলো ব্যবহার করা যায়: (!= , >, <, >=, <=)
Logical and / or:
if( a==b && e==f ){
}
if( a==b || e==f ){
}
টিপস: এখানে এন্ড বা অর এর ক্ষেত্রে বাড়তি ( ) ব্যবহার করা যায় বুঝার সুবিধার জন্য।
if( (a==b) || (e==f) ){
}
Modulus:
int a = 4;
int remainder = a % 2; // result will be 0
Increment and decrement:
a++
a–
অথবা
++a
–a
এখানে a++ হলো a = a+1;
আর a– হলো a = a-1;
যদি ++ বা — ভ্যারিয়েবলের আগে দেয়া হয় তবে অই লাইন এক্সিকিউশনের সময়ই ভ্যারিয়েবলের সাথে ১ যোগ হবে আর পরে দেয়া হলে অই লাইন এক্সিকিউশনের পর ভেরিয়েবলের সাথে ১ যোগ হবে।
Ternary :
int c = 6;
int d = 7;
int a = (c > d)? c: d;
এটা if else এর সংক্ষিপ্ত রুপ।
এটাকে এভাবে লেখা যায় –
if (c > d){
a = c;
} else {
A = d;
}
Loop:
int a;
for (int a = 0; a < 10; a++){
NSLog(@"The value is %i", a);
}
//------------------------------------------
while ( a < 10 ) {
NSLog(@"The value is %i", a);
a++;
}
//------------------------------------------
do{
NSLog(@"The value is %i", a);
a++;
}while( a < 10 );
লুপের মাঝে break এবং continue ব্যবহার করা যায় অন্য ল্যাঙ্গুয়েজের মতই।
Function:
int makeSum(int a, int b){
return a+b;
}
এটা সাধারণ ফাংশন। অবজেকটিভ সি তে ফাংশন লিখতে হবে সেই মেথড কল করার আগে। যদি মেইন মেথডে ফাংশান কল করা হয় তবে মেইন মেথডের আগে লিখতে হবে।
মেথড কল করার পরে ফাংশান লিখতে হলে প্রটোটাইপ (Prototype) বলে দিতে হয় আগে। এখানে প্রটোটাইপ হলো ফাংশানের বডি ছাড়া বাকি অংশটুকু।
উদা:
#import <Foundation/Foundation.h>
int makeSum(int a, int b); // এটা প্রটোটাইপ
int main(int argc, const char * argv[]){
@autoreleasepool{
int r = makeSum(5, 6); // এখানে মেথড কল করা হলো
}
}
int makeSum(int a, int b){ // মেথড
return a+b;
}
Data type:
ভেরিয়েবলের নাম কেস সেনসিটিভ, শুরুতে নিউমেরিক থাকা যাবে না। আন্ডারস্কোর ব্যবহার করা রিকমেন্ডেড না কিন্তু ব্যবহার করা যায়।
Premitive data types are:
int
float
double
char
BOOL
Composite data types are:
NSDate *today = [NSDate date]; // এখানে অনেক int নিয়ে এই NSDate
NSString *myString = @”Touhid Apps!”; // অনেক char নিয়ে NSString
Numeric :
int এটার range -2,147,483,648 থেকে +2,147,483,648
unsigned int এটা 0 থেকে +4,294,967,295
long int এর range 32 bit এ শুধু int এর মতই, 64 bit এ -9223372036854775808 থেকে +9223372036854775808
long long int এ ৩২ এবং ৬৪ বিট দুইটাতেই -9223372036854775808 থেকে +9223372036854775808
লেখার ক্ষেত্রে একটি বিষয় – আগের লাইনে modifier ব্যবহার করা হলে পরের লাইনে টাইপ না বলে শুধু modifier ব্যবহার করলে আগের লাইনের টাইপ ধরে নেয়।
উদা:
unsigned int a = 45464;
unsigned b= 666666; //এখানের ডাটা টাইপ int
প্লেস হোল্ডার ইন্ডিকেটর(%i):
long long int এর জন্য %lli
unsigned int এর জন্য %u
//—————————————————
short int এর রেন্জ -32767 থেকে +32767
int এর ভিতর দশমিক কোন সংখ্যা রাখা যাবে না। রাখলে দশমিকের পরের অংশটুকু থাকবে না।
ফলাফল ভুল আসবে। এজন্য float অথবা double ব্যবহার করতে হবে।
float হলো 4 bit
double হলো 8(Eight) bit
উদা:
float a = 5.8f; // float এর ক্ষেত্রে শেষে f লিখাটা বেস্ট প্রেক্টিস
double b = 7.2;
ফ্লোটিং এর প্লেস হোল্ডার ইন্ডিকেটর তিন রকম করে করা যায়। (%f, %e, %g)
%e সায়েন্টিফিক নোটেশন সহ দেখায় তাই এটা সবচেয়ে নিখুঁত
%g টা ভ্যারিয়েবল অনুসারে একটা মান দেখায়
উদা:
float a = 33.3f;
এই a কে (%f, %e, %g) এই তিন রকমের প্লেস হোল্ডারে প্রিন্ট করলে তিন রকম ফল আসবে।
float a = 33.3f;
এবং
double b = 33.3;
কম্পিউটারের ডাটা স্টোর করার পদ্ধতির কারণে এই দুইটাকে %f দিয়ে প্রিন্ট করলে দুই রকম ফল আসবে।
Char:
char oneLetter = ‘T’;
প্রিন্ট করতে %c
BOOL:
অবজেকটিভ সি তে boolean কে BOOL এবং তার ভেলু true/false না হয়ে YES/NO এভাবে লেখা হয়।
BOOl isGood = YES;
BOOL isOn = NO;
প্রিন্ট করে দেখতে %i ব্যবহার করতে হবে। আর প্রিন্ট হবে YES এর জন্য 1 এবং NO এর জন্য 0
Scope:
Scope দুই রকম। Local এবং Global
কোন মেথড অথবা লুপের ভিতরে ভেরিয়েবল ডিক্লেয়ার করলে তা অই ফাংশান কিংবা লুপের ভিতরেই এক্সেস করা যাবে, বাইরে থেকে করা যাবে না। এটা হলো লোকাল স্কোপ।
যদি #import সেকশনের পরেই কোন ভেরিয়েবল ডিক্লেয়ার করা হয় তবে তা যে কোন মেথডের কিংবা লুপের ভিতর থেকে ধরা যাবে। এটা হলো Global scope ।
Enum:
যদি এমন হয় যে ই কর্মাসের জন্য প্রোগ্রাম লিখছেন, এখন একটি শার্টের তিন রকম সাইজ আছে – small, middle, large
এই তিনটি কে কাজে লাগানোর জন্য 1 হলে small, 2 হলে middle, 3 হলে large এভাবে ধরে কোডে ব্যবহার করা যায় কিন্তু এটা কোডিং এর ক্ষেত্রে সহজ বোধ্য না আবার মনে নাও থাকতে পারে কোনটাকে কি ধরা হয়েছিল আর যদি এটা কয়েকশো রকম হয় তাহলে তো আরো জটিল হয়ে যায় বিষয়টা। এক্ষেত্রে enum ব্যবহার করে বিষয়টাকে সহজবোধ্য করা যায়।
উদা:
enum shartSizes{
small,
middle,
large
}
int main(int argc, const char * argv[]){
enum shartSizes selectedShirt = middle;
if( selectedShirt == large){
// do something
}
}
উদাহরণ অনুসারে – shartSizes এ যে তিনটা সাইজ রাখা হয়েছে সেগুলো ডিফল্টভাবে 0, 1, 2 এভাবে ইনডেক্সিং থাকবে। এক্ষেত্রে selectedShirt হলো ভ্যারিয়েবল আর shartSizes হলো ডেটা টাইপ।
ইচ্ছা করলে এগুলোকে কাস্টম ভ্যালু দিয়ে এ্যাসাইন করে রাখা যায়।
enum shartSizes{
small = 4,
middle = 5,
large = 6
}
যেহেতু ইনাম ব্যবহার করতে সরাসরি এগুলোর ভ্যালু ব্যবহার করা হবে না তাই ভ্যালু ইচ্ছা মত দেয়া যায় অথবা না দিলেও চলে, কম্পাইলার ভ্যালু বসিয়ে নেয়।
String:
NSString *name = @”Touhid apps!”;
অবজেকটিভ সি তে String নামে কোন ডেটা টাইপ নেই। স্ট্রিং এর জন্য ব্যবহার করতে হবে NSString. এটা ফাউন্ডেশন ফ্রেমওর্য়াকের অংশ। এটার নামের সাথে পয়েন্টার ব্যবহার করতে হয় এস্টারিক চিহ্ন ব্যবহার করে। এটা ভেরিয়েবলের নামের অংশ নয়। ডিক্লেয়ার করার সময়ই শুধু পয়েন্টারের চিহ্ন দিতে হবে। পরে ব্যবহারের সময় লাগবে না। ভ্যালু লেখার সময় আগে @ দিয়ে ডাবল কোটেশনের ভিতরে লিখতে হবে। এক্ষেত্রে প্লেস হোল্ডার ইন্ডিকেটর হলো %@
অবজেকটিভ সি তে সকল অবজেক্ট হলো পয়েন্টার টাইপ।
অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং (OOP)
Class & Object:
Class: ক্লাস হলো অবজেক্টের ব্লু প্রিন্ট (Blue print) . অবজেক্ট কি কি নিয়ে গঠিত হবে তা থাকে এই ক্লাসে। ক্লাসের কিছু উপাদান থাকে আর থাকে কাজ। মনে করি গাড়ি একটি ক্লাস আর এর উপাদান হলো চাকা, ইঞ্জিন, রং এবং কাজ হলো গাড়ির ইঞ্জিন স্টার্ট হয়, হর্ণ বাজে, ব্রেক করা যায় । কোড চিন্তা করলে- উপাদানগুলোকে ক্লাসে ভেরিয়েবল আকারে আর কাজ গুলোকে মেথড আকারে রাখা যায়।
এভাবেও চিন্তা করা যায়: ক্লাস হলো একটি ফাইল যা যাতে ভেরিয়েবল আর মেথড থাকে। এই ক্লাসকে আমরা অবজেক্ট হিসেবে ডিক্লেয়ার করতে পারি যতবার খুশি তত বার। যখন প্রোগ্রাম রান করা হয় তখন ডিক্লেয়ার করা অবজেক্ট গুলো একই ক্লাসের অনুসারে গঠিত হয়। যেমন: গাড়ির অবজেক্টগুলো রান করালে প্রয়োজন মত এক এক সময় এক এক রঙের এক এক রকম চাকার গাড়ির অবজেক্ট তৈরি হবে। অবজেক্ট হলো ক্লাসের instance ;
উদা:
NSString *name = @”Touhid”;
NSString *phone = @”iPhone”;
এখানে NSString হলো ক্লাস আর Touhid হলো অবজেক্ট এবং name হলো অবজেক্টের রেফারেন্স। এভাবে ইচ্ছা মত একই ক্লাস থেকে একাধিক অবজেক্ট তৈরি করা যায়। এখানে name এবং phone এই দুটি অবজেক্ট তৈরি করা হয়েছে একটি ক্লাস(NSString) থেকে।
* এই এস্টারিক চিহ্নটি পয়েন্টার বুঝানো হয়।
Pointers:
অবজেক্টিভ সি তে সকল অবজেক্টে এক্সেস করা হয় পয়েন্টারের মাধ্যমে।
আমরা যদি লিখি int amunt = 786;
এখানে পয়েন্টার নেই, এখানে int হলো প্রিমিটিভ টাইপ এর জন্য মেমোরিতে 4 বাইট যায়গা লাগে। যখন আমরা int ডেটা নেই তখন এটা মেমোরিতে 4 বাইটের একটা যায়গা দখল করে রাখে। এই যায়গায় 4 বাইটের যে কোন ডেটা রাখা যায়। এটা নির্দিষ্ট পরিমান যায়গা দখল করে। এখানে রাখা হয়েছে 786, এই সংখ্যার সাথে কিছু যোগ বিয়োগ গুন ভাগ যাই করা হোক, 4 বাইট যায়গার মধেই সব হবে। কিন্তু একটা অবজেক্ট কত বড় হবে তা নির্দিষ্ট নয়।
NSString *something = @”Hello how are you?”;
এখানে লেখা কত বড় হবে এবং তা কত যায়গা দখল করবে তা আগেই বলা যায় না। এখানে পয়েন্টারের মাধ্যমে অবজেক্টের মেমোরির এড্রেস রাখা হয়। জাভাতেও একই কাজ করা হয় শুধু পয়েন্টারের এস্টারিক চিহ্ন হাইড করা থাকে।
অবজেকটিভ সি তে কোন অবজেক্ট লিখতে হলে এই এস্টারিক দিতে হবে কিন্তু ব্যবহারের সময় এস্টারিক লাগবে না। এস্টারিক নামের অংশ নয়।
NSString *something;
something = @"Hello how are you?";
পরে ব্যবহারের সময় এস্টারিক দেয়া যাবে না।
Methods:
অবজেকটিভ সি তে মেথড কল করার পদ্ধতি অনেকটা ভিন্ন। জাভাতে অবজেক্ট এর পর ডট দিয়ে মেথড কল করা যায় কিন্তু অবজেকটিভ সি তে স্কয়ার ব্রাকেট দিয়ে অবজেক্ট লিখে একটা স্পেস দিয়ে মেথডের নাম দিতে হয় , মেথডের পর প্যারেন্থেসিস( ) দিতে হয় না।
উদা:
জাভাতে: myObject.myMethod();
অবজেকটিভ সি তে: [myObject myMethod];
মেথড কোন কিছু রিটার্ন করলে এভাবে:
জাভাতে: String name = myObject.myMethod();
অবজেকটিভ সি তে: NSString *name = [myObject myMethod];
আর্গুমেন্ট থাকলে:
জাভাতে: String name = myObject.myMethod(arg);
অবজেকটিভ সি তে: NSString *name = [myObject myMethod:arg];
একাধিক আর্গুমেন্ট থাকলে:
জাভাতে: String name = myObject.myMethod(arg, arg2);
অবজেকটিভ সি তে: NSString *name = [myObject myMethod:arg another:arg2];
যখন মেথড তৈরি করব তখন মেথডের নামের আগে যদি + চিহ্ন দেই তার মানে এটা ক্লাস মেথড অর্থাৎ জাভাতে যেমন মেথডকে static করলে সরাসরি ক্লাস থেকে কল করা যায় তেমন করে ক্লাস থেকে কল করা যায়। যদি – চিহ্ন দেই তাহলে তা হবে ইনস্টেন্স মেথড অর্থাৎ ক্লাস থেকে অবজেক্ট তৈরি করে তারপর কল করতে হবে।
Object creation:
কোন ক্লাস থেকে অবজেক্ট এলোকেশন এবং ইনিশিয়ালাইজেশন করতে হয় এভাবে:
Student নামে একটা ক্লাস আছে এক্ষেত্রে –
জাভাতে : Student student = new Student();
অব.সি তে: Student *student = [[Student alloc] init];
আমরা জাভাতে একাধিক কনস্ট্রাক্টর নিয়ে ইনিশিয়ালাইজ করতে পারি একই ভাবে অব.সি তে করা থাকলে কল করতে হবে এভাবে:
জাভাতে: Student student = new Student(“Touhidul Islam”);
অব.সি তে: Student *student = [[Student alloc] initWithName@”Touhidul Islam”];
এখানে init কিংবা initWithName হলো ইন্সটেন্স মেথড অর্থাৎ মেথডের শুরুতে – চিহ্ন আছে।
Custom Class Creation:
অবজেক্টিভ সি তে দুইটা ফাইল মিলে একটা ক্লাস তৈরি হয়। একটা হলো হেডার ফাইল যার এক্সটেনশন হয় (.h) আরেকটা হলো মেথড ফাইল যার এক্সটেনশন হয় (.m),
হেডার ফাইলে:- Foundation.h import করা থাকে, ইন্টারফেস থাকে এভাবে:
@interface MyClassName : NSObject
এখানে MyClassName হলো আপনার দেয়া ক্লাসের নাম এবং কোলন চিহ্নের পর NSObject হলো এক্সটেন্ড করা ক্লাস। সাধারনত কাস্টম ক্লাসগুলো এই NSObject ক্লাসকে এক্সটেন্ড করে।
মেথড ফাইল:- এখানে হেডার ফাইল import করা থাকে আর থাকে ইমপ্লিমেন্টেশন এভাবে:
@implementation MyClassName
এই দুটি ফাইলে একটি কমন জিনিস হলো @end এর মাধ্যমে ফাইলের শেষ বুঝানো হয়।
হেডার ফাইলে প্রোপার্টি বা ভেরিয়েবল গুলো লিখতে হবে এবং মেথড ডিক্লেয়ার করতে হবে।
প্রোপার্টি লিখতে হবে @interface এবং @end এর মাঝে।
উদা:
@interface MyClassName : NSObject
@property NSString *name;
@property NSDate *dob;
-(void) myMethod;
@end
এভাবে প্রোপার্টি এবং মেথড ডিক্লেয়ার করতে হবে। এখানে মেথড হলো -(void) myMethod;
– চিহ্ন মানে হলো এটা ইনস্টেন্স মেথড, (void) হলো রিটার্ন টাইপ myMethod হলো মেথডের নাম, এখানে মেথডের বডি লিখা যাবে না কারন এটা ইন্টারফেস।
এখন মেথড ফাইলে (.m) এসে @implement MyClassName এবং @end এর ভিতরে বডি সহ মেথড লিখব।
উদা:
@implementation MyClassName
-(void) myMethod{
// your code here
NSLog(@”Hello is it me you looking for?”);
}
@end
নতুন ক্লাস হলো ক্লাসের মেথডও লেখা হলো এবার এটা ব্যবহার করতে হলে অন্য একটা ক্লাস থেকে কল করা যাবে। যেমন মেইন মেথড থেকে কল করতে হলে এভাবে করা যাবে:
#import <Foundation/Foundation.h>
#import "MyClassName.h"
int main(int argc, const char * argv[]){
@autoreleasepool{
MyClassName *myClassName = [[MyClassName alloc] init];
[myClassName myMethod];
[myClassName setName:@"Touhid"];
}
}
যেহেতু মেইন মেথড অটো কল হয় তাই এখানেই উদাহরন দেখানো হলো। প্রথমে আছে ইম্পোর্ট সেকশন। Foundation ফ্রেমওয়ার্ক আর তৈরি করা কাস্টম ক্লাস import করা হয়েছে। কোন ফ্রেমওয়ার্ক ইম্পোর্ট করতে হলে < > দেয়া হয় আর ডিফল্টভাবে ইম্পোর্ট করতে “ ” ব্যবহার করতে হয়।
এরপর মেইনমেথডে অটোরিলিজপুলের ভিতর প্রথমে ক্লাসকে ইনিশিয়ালাইজ করা হলো তারপর সেই ক্লাসের অবজেক্ট থেকে মেথড কল করা হলো। আবার সেই অবজেক্ট থেকে তার প্রোপার্টির সেট মেথড ব্যবহার করা হলো। এখানে প্রোপার্টির জন্য সেটার/গেটার দেয়া লাগে না অটো হয়ে যায়।
Methods:
মেথড ডিফাইন করতে হয় হেডার (.h) ফাইলে।
উদা:
-(void) myMethod: (int) myNumber;
এখানে প্রথমে রয়েছে – সাইন। – দিলে তা হবে ইন্সটেন্স মেথড আর + দিলে হবে ক্লাস মেথড। মানে হলো – দিলে ক্লাসের ইন্সটেন্স(অবজেক্ট) তৈরি করে তারপর এই মেথডে এক্সেস করতে হবে আর + থাকলে ক্লাসের নাম দিয়ে সরাসরি এক্সেস করা যাবে। বিষয়টা জাভার static এর সাথে মিল আছে।
এরপর রয়েছে (void) যা হলো মেথডের রিটার্ন টাইপ। এই মেথড যা রিটার্ন করবে তা লিখতে হবে এই অংশে। এখানে void মানে কিছুই রিটার্ন করবে না।
এরপরের অংশটুকু myMethod হলো মেথডের নাম।
: কোলনের পরে রয়েছে প্যারামিটার টাইপ (int) এবং প্যারামিটারের নাম myNumber
প্যারামিটার না থাকলে মেথড হতো এরকম:
উদা:
-(void) myMethod;
আমাদের যদি অবজেক্ট রিটার্ন করতে হয় কিংবা প্যারামিটারে দিতে হয় তখন টাইপের সাথে বাড়তি একটা এস্টারিক চিহ্ন লাগবে।
উদা:
-(NSString *) myMethod: (NSString *) myName;
NSString হলো অবজেক্ট টাইপ তাই এরপর * এস্টারিক দিতে হবে।
এতক্ষন দেখলাম একটা প্যারামিটারের উদাহরন। যদি দুইটা প্যারামিটার থাকে তবে মেথড হবে এরকম:
উদা:
-(int) addNumber: (int) a toNumber: (int) b;
এখানে a আর b দুইটা প্যারামিটার যাদের টাইপ হলো int, addNumber হলো মেথডের নাম আর toNumber হলো মেথডের নামের আরেকটা অংশ। প্যারামিটার দুইটা থাকলে দুইটা ভাগে মেথডের নাম লিখতে হবে। এই মেথডের ভাল ইন্ডেন্টেশন এভাবে করলে পড়তে সুবিধা হবে:
-(int) addNumber: (int) a
toNumber: (int) b;
হেডার ও মেথড ফাইলের স্কীনশট:
ছবি: বামের হেডার ও ডানে মেথড ফাইলএতক্ষন ইন্টারফেসের কাজ করলাম হেডার(.h) ফাইলে। এবার ইমপ্লিমেন্টেশনের জন্য মেথড (.m) ফাইলে কাজ করতে হবে।
যে মেথড গুলো হেডার ফাইলের ইন্টারফেসে ডিফাইন করা হলো সেগুলিকে এবার মেথড ফাইলে লিখতে হবে শেষের সেমিকোলন বাদ দিয়ে {} দিতে হবে। এই কোড ব্লকস {} এর মধ্যে মেথডের প্রয়োজনীয় কোডগুলি লেখা যাবে প্যারামিটার ব্যবহার করা যাবে এবং রিটার্ন করা যাবে অন্যান্য ল্যাঙ্গুয়েজের মতই।
মেথড তো তৈরি করলাম এবার ব্যবহার করতে হবে। এজন্য অন্য কোন ক্লাসে গিয়ে এই MyCalculation ক্লাসকে import করতে হবে।
স্ক্রীনশট:
যেহেতু মেইন মেথড অটোমেটিক কল হয় তাই এর ভেতরে গিয়ে প্রথমে অবজেক্ট তৈরি করা হলো এই লাইনের মাধ্যমে:
MyCalculation *myCalc = [[MyCalculation alloc] init];
এরপর [ ] ব্রাকেটের ভিতরে নিচের মত করে myCalc অবজেক্টের রেফারেন্স লিখে স্পেস দিয়ে মেথডের নাম লিখতে হবে (লেখার সময় xCode এই অবজেক্টের ভিতরে যে ইন্সটেন্স মেথডগুলি আছে তার সাজেশন্স দেখাবে)। মেথডের নামের পর কোলন দিয়ে প্যারামিটারের জন্য আর্গুমেন্ট দিতে হবে।
[myCalc myMehod:1];
NSString *name = [myCalc myNameMethod:@"Md. Touhidul Islam"];
NSLog(@"My name is: %@", name);
int sum = [myCalc addNumber:3 toNumber:4];
NSLog(@"Sum is: %d", sum);
myNameMethod এবং addNumber toNumber মেথড দুটি যেহেতু রিটার্ন করে তাই রিটার্ন করা ভ্যালু ভ্যারিয়েবলে রেখে তা লগে প্রিন্ট করা হয়েছে।
এবার প্রজেক্ট রান করালে ফলাফল দেখা যাবে।
Property:
প্রোপার্টি বা ডাটা বা ভেরিয়েবল ডিফাইন করার জন্য আগে হেডার ফাইলের কোড ব্লকস্ এর ভিতরে লিখে তারপর getter/setter মেথড লিখতে হতো নিচের মত করে:
এখানে ভেরিয়েবলের নামের আগে আন্ডারস্কোর _ ব্যবহার করাটা ivars বা ইন্সটেন্স ভেরিয়েবল ডিফাইন করার একটা কনভেনশন, না দিলেও চলে। গেটার/সেটার দিয়ে অন্য ক্লাস থেকে এই ভেরিয়েবলের মান পরিবর্তন ও এক্সেস করা যাবে।
একই কাজ আরো সহজে করা যায় @property ব্যবহার করে। এক্ষেত্রে অটোমেটিক সেটার/গেটার হয়ে যায়। কোডে শুধু নিচের মত করে ভেরিয়বল লিখতে হবে। অন্য ক্লাস থেকে এই ভেরিয়েবলের সেটার/গেটার মেথড পাওয়া যাবে এজন্য আর কোন কোড লিখতে হবে না।
হেডার ফাইলে প্রোপার্টি ডিফাইন করার পর মেথড ফাইলে গিয়ে ইমপ্লিমেন্টেশন করতে হবে। এজন্য আগে @synthesize ব্যবহার করা হতো । এখন এটা না করলেও চলে। যেহেতু হেডার ফাইল মেথড ফাইলে ইম্পোর্ট করা আছে তাই সেটাকে মেথড ফাইলে সরাসরি ব্যবহার করা যাবে।
যদি উপরের প্রোপার্টিকে synthesize করা হয় তবে এমন হবে:
xCode 4.4 থেকে এটা আর প্রয়োজন হয় না।
হেডার ফাইলে যখন অবজেক্টকে প্রোপার্টি হিসেবে ডিফাইন করা হয় তখন আরেকটি জিনিসের প্রয়োজন হয় – অবজেক্ট এর আগে strong, weak, nonatomic কী-ওয়ার্ড ব্যবহার করা।
উদা:
@property (strong) NSString *myName;
@property (weak) NSString *yourName;
@property (nonatomic) NSString *anotherName;
@property (strong, nonatomic) NSString *fullName;
strong কী-ওয়ার্ড মানে হলো অবজেক্টের strong রেফারেন্স। এটা ডিফল্ট তাই না দিলেও চলে। weak হলো weak রেফারেন্স আর nonatomic হলো থ্রেড সেফটির জন্য।
দুই কী-ওয়ার্ড একসাথে ব্যবহারের জন্য মাঝখানে কমা ব্যবহার করা হয়। আইওএস ডেভলপের সময় strong এবং nonatomic ব্যবহার করা ভাল।
আরেকটা আছে readonly, এটা ব্যবহার করলে প্রোপার্টিতে ভ্যালু সেট করা যাবে না শুধু রিড করা যাবে অর্থাৎ গেটার মেথড জেনারেট হবে কিন্তু সেটার মেথড জেনারেট হবে না।
হেডার ফাইলে যে প্রোপার্টিগুলো আছে সেগুলো অন্য ক্লাস থেকে এক্সেস করা যায় হেডার ফাইল ইম্পোর্ট করার মাধ্যমে। যদি কোন প্রোপার্টিকে অন্য ক্লাস থেকে এক্সেস দিতে না চাই তাহলে সেই প্রোপার্টিকে হেডার ফাইলে না লিখে মেথড ফাইলে লিখতে হবে এভাবে:
Initializers:
একটা কোড দেখি আগে:
এখানে হেডার ফাইলে একটা প্রোপার্টি একটা মেথড নেয়া হয়েছে।
মেথড ফাইলে লেখা হয়েছে দুইটি ইনিশিয়ালাইজার মেথড।
মেইন মেথড ফাইলে এসে হেডার ফাইল ইম্পোর্ট করার পর দুইটা অবজেক্ট তৈরি করে গেটার মেথড দিয়ে ভেরিয়েবল/প্রোপার্টি এক্সেস করা হয়েছে।
জাভাতে কন্সট্রাক্টর যেরকমভাবে কোন অবজেক্টকে ইনিশিয়ালাইজ করতে ব্যবহৃত হয় অবজেক্টিভ সি তে অবজেক্ট ইনিশিয়ালইজ করতে init মেথড ব্যবহার করা হয়। এটা শুরু হয় – সাইন দিয়ে, রিটার্ন টাইপ হলো instancetype । জাভাতে যেমন this ব্যবহার করা হয় তেমনি এখানে আছে self, এটা যে ক্লাসে লেখা হবে সেই ক্লাসকে বুঝায়। super কী-ওয়ার্ড ব্যবহার করা হয় সুপার/প্যারেন্ট/বেস ক্লাসকে বুঝাতে। init কে হেডার ফাইলের ইন্টারফেসে লিখতে হয় না কারণ এটা সুপার ক্লাস NSObject এ ডিফাইন করা আছে। কিন্তু initWith… এরকম ইনিশিয়ালাইজার ব্যবহার করলে সেটা হেডার ফাইলে লিখতে হবে। এখানে initWithName লিখা হয়েছে। কোন অবজেক্ট সাধারণত NSObject কে ইনহেরিট করে। অর্থাৎ NSObject হলো সুপার ক্লাস। কোন ইনন্সটেন্স ভেরিয়েবলকে ক্লাসের ভিতরে ব্যবহার করতে হলে আগে _ (আন্ডারস্কোর) ব্যবহার করতে হবে। জাভাতে যেরকম this.someThing এরকমই _someThing.
কন্সট্রাক্টর যেমন একাধিক হতে পারে সেরকম ভাবে ইনিশিয়ালাইজার মেথড একাধিক হতে পারে। যেমন: initWithString, initWithInteger, initWithName এভাবে। initWithSomething এভাবে লেখাটা অবজেক্টিভ সি এর কনভেনশন।
আরেকটা বিষয় এখানে বলে দেই, অবজেক্টের (NSObject) dealloc নামে একটা মেথড আছে। আমরা যখন কোন কাস্টম ক্লাস বানাই এবং ব্যবহার করি তখন এই dealloc মেথড অটোমেটিক কল হয়ে অবজেক্টকে রিলিজ করে দিয়ে মেমোরি খালি করে দেয়। এটা ম্যানুয়েলি সেট করতে চাইলে মেথড ফাইলে এভাবে লিখে দিলেই হবে। কিন্তু সাধারণত এটা লিখার প্রয়োজন হয় না।
উদা:
-(void) dealloc{
NSLog(@"This part will call automatically");
}