خبرنامه
 
پست الکترونیکی خود را وارد نمایید
شماره خبر : 886
تاریخ انتشار :
آموزش برنامه نویسی اپل با xcode : بررسی کنترلر Tab Bar

آموزش برنامه نویسی اپل با xcode : بررسی کنترلر Tab Bar

در حالی که کنترلرهای کاوشی(navigation controllers) به کاربران این امکان را می دهند تا بین محتویات سلسله مراتبی یا به طور کلی داده های بزرگ به واسطه مدیریت یک گروه از view controllerها کاوش کنند، از آن طرف کنترلرهای tab bar، یک آرایه از view controllerهایی را مدیریت می کنند که الزماً ارتباطی به یکدیگر ندارند. در این مقاله قصد داریم به طور عمیق تری به نحوه کارکرد کنترلرهای tab bar با ایجاد یک برنامه چندزبانه ای از صفر بپردازیم. با ما همراه باشید.
مقدمه :
کلاس UITabBarController یکی از زیرکلاس های دیگر کلاس UIViewController می باشد. به طور کلی با وجود اینکه کنترلرهای کاوشی، یک مجموعه از view controllerهای مرتبط را تحت مدیریت خود قرار می دهند اما کنترلرهای tab bar، یک آرایه از view controllerهایی را مدیریت می کنند که هیچ ارتباط مشخص و آشکاری با دیگری ندارند.
برنامه های Clock و Music تحت سیستم عامل iOS دو نمونه مهم از به کار گیری و استفاده از کنترلرهای tab bar هستند. درست به مانند هر زیرکلاس دیگر UIViewController، یک کنترلر tab bar در واقع یک نمونه UIView را مدیریت می کند.

نمای ظاهری یک کنترلر tab bar از دو زیرنما تشکیل شده است :



بخش tab bar در ناحیه پایین view و بخش دیگر نیز viewی یکی از view controllerها که کنترلر tab bar آنرا مدیریت می کند.

پیش از شروع کار :
هنگام کار با کنترلرهای tab bar چند نکته هست که باید پیش از شروع کار، آنها را بدانید. حتی با این وجود که نمونه هایی از UITabBar تنها قادر به نمایش 5 زبانه هستند، اما کلاس UITabBarController قادر به مدیریت view controllerهای بیشتری است. هر زمان که یک کنترلر tab bar بیشتر از 5 view controller را مدیریت می کند، آخرین زبانه tab bar تحت عنوان More تنظیم می شود.

view controllerهای اضافی را می توان از طریق این زبانه مورد دسترسی قرار داد و حتی ممکن است بتوانید مکان زبانه ها را در tab bar تنظیم کنید.

اگرچه کنترلرهای tab bar یک نما یا همان view را مدیریت می کنند، لیکن برنامه شما قرار نیست تا به صورت مستقیم با نمای کنترلر tab bar ارتباط برقرار کند.
اگر شما به نتیجه برسید که یک کنترلر tab bar، انتخاب درستی برای یک برنامه به شمار می رود، لازم است تا کنترلر tab bar به عنوان یک view controller ریشه از پنجره برنامه در نظر گرفته شود. به عبارت دیگر، نمای ریشه از یک پنجره برنامه همیشه نمای کنترلر tab bar می باشد.
یک کنترلر tab bar نباید هرگز به عنوان یک فرزند از view controller دیگر نصب شود. این حالت یکی از مهمترین تفاوت های کلیدی موجود با کنترلرهای کاوشی یا همان navigation controllerها است.
Tabbed Library :
در این برنامه ما دوباره برنامه Library را که پیش از این در مقالی قبلی ایجاد کردیم را مورد بررسی قرار می دهیم. با انجام این کار می توانیم از چندین کلاس دوباره استفاده کرده و سرعت روند کار را افزایش دهیم. به اضافه اینکه، این اقدامات به شما اثبات خواهد کرد که کنترلرهای کاوشی و کنترلرهای tab bar کاملاً از هم متفاوت بوده و در وضعیت ها و نقاط مختلفی مورد استفاده قرار می گیرند.
برنامه ای که در این بخش خواهیم ساخت تحت اسم Tabbed Library نامگذاری شده و کلاس پایه آن نیز کلاس UITabBarController خواهد بود. به هنگام ساخت برنامه Tabbed Library، شما متوجه خواهید شد که استفاده از یک کنترلر tab bar، برنامه را تحت یک الگوی کاربری خیلی خاصی قرار می دهد که سبب کاهش انعطاف پذیری آن خواهد شد. کنترلرهای tab bar به طور باورنکردنی‌ای کاربردی هستند اما به هر حال شما باید قبول کنید که آنها محدودیت هایی را تحت رابط کاربری برنامه تان ایجاد می کنند.
نرم افزار Xcode را باز کرده و از مسیر (File > New > Project...)، پروژه جدیدی را ایجاد کرده و الگوی Empty Application را از لیست موجود انتخاب کنید.

حال نام پروژه را Tabbed Library نهاده و برای بخش های organization name و company identifier نامی دلخواه برگزیده و سپس مقدار کادر بازشوی جلوی فیلد Devices را تحت مقدار iPhone تنظیم کنید. در پایان نیز مکانی را برای ذخیره پروژه انتخاب کرده و روی گزینه Create کلیک کنید.

با وجود اینکه خود Xcode شامل یک الگوی Tabbed Application به صورت آماده می باشد اما ترجیح می دهیم تا برای درک بیشتر قسمت های مختلف برنامه و نحوه ارتباط آنها با یکدیگر از یک الگوی empty application استفاده کنیم.
در ادامه متوجه خواهید شد که کنترلرهای tab bar به آن پیچیدگی که تصویر می کنید نیستند. با ما همراه باشید.
شروع فرایند کار از صفر :
زمانی که فرایند ساخت برنامه Tabbed Library به پایان رسید، کنترلر tab bar متعلق به برنامه، 6 view controller را مدیریت خواهد کرد. به جای ایجاد هر کلاس  view controller از صفر ما قصد داریم کمی زرنگی کرده و از کلاس های view controllerای استفاده کنیم که در مقاله قبلی آنها را ایجاد کرده ایم.
به اضافه اینکه، ما چندین نمونه از یک کلاس view controller را ایجاد کرده تا در زمان صرفه جویی بیشتری داشته باشیم. به طور کلی هدف این مقاله این نیست که مجموعه ای از کلاس های view controller را ایجاد کند. در حال حاضر شما باید کاملاً بدانید که آن چگونه کار می کند.
ابتدا از لینک source code from the previous article، فایل های مقاله قبلی را که ایجاد کرده ایم را دانلود کرده و تحت نرم افزار Xcode به عنوان یک پروژه جدید باز کنید. حال کلاس های TSPAuthorsViewController، TSPBooksViewController و TSPBookCoverViewController را پیدا کرده و آنها را با درگ کردن به پروژه جدید خود اضافه کنید. مطمئن شوید که عمل کپی فایل ها به درون پروژه جدید با فعال بودن گزینه Copy items into destination group's folder (if needed) همراه بوده و همچنین فراموش نکنید که این فایل ها را به پروژه Tabbed Library اضافه کنید.

علاوه بر این سه کلاس، ما همچنین لازم است تا پوشه منابع یا همان resources را که شامل فایل های تصاویر و فایل Books.plist هست را به درون پروژه خود منتقل کنیم.
برای این منظور پوشه ای با نام Resources را به درون پروژه درگ کرده و از همان تنظیماتی استفاده کنید که ما به هنگام کپی فایل های کلاس استفاده کردیم.
حال وقت آن رسیده است تا یک نمونه از کنترلر tab bar متعلق به برنامه را ایجاد کرده و آن را با اولین view controllerش آماده استفاده قرار دهیم.
اضافه کردن یک کنترلر Tab Bar :
فرایند اضافه کردن یک کنترلر Tab Bar بسیار ساده است. برای این منظور کافی است، storyboard اصلی پروژه یعنی Main.storyboard را باز کنید. البته چون ما از الگوی  Empty Application استفاده کردیم، نرم افزار Xcode هیچ storyboardای به ما تحویل نمی دهد.
اضافه کردن یک Stroryboard :
برای این منظور از منوی file، مسیر New > File را طی کرده و از فهرست موجود در سمت چپ که با عنوان  iOS User Interface مشخص شده، گزینه Storyboard را برگزینید.

نوع Device Family را تحت مقدار iPhone تنظیم کرده و نام storyboard را main قرار دهید. البته در این موقعیت هیچ نیازی به اضافه کردن پسوند .storyboard نبوده و خود نرم افزار Xcode آن را برای شما اضافه خواهد کرد.

ما همچنین لازم است به Xcode اعلام کنیم که از Main.storyboard به عنوان رابط اصلی برنامه ما استفاده کند. برای این منظور پروژه را از بخش Project Navigator انتخاب کرده و از لیست گزینه های موجود Tabbed Library  را انتخاب و در نهایت مقدار Main Interface را تحت Main یا Main.storyboard تنظیم کنید.

 

قبل از شروع کار با storyboard، لازم است تا پیاده سازی فعلی از application:didFinishLaunchingWithOptions: را در کلاس TSPAppDelegate را به روزرسانی کنیم. برای این منظور TSPAppDelegate.m را باز کرده و ساختار آن را همانطور که در دستورات زیر می بینید به روز کنید.


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    return YES;
}

 

البته شما می توانید برنامه های iOS مدنظر خود را بدون storyboardها ایجاد کنید، اما در این صورت شما  به طور صریح، پنجره برنامه خود را که در واقع چیزی است که شما در ساختار application:didFinishLaunchingWithOptions: دیدید باید معرفی و تنظیم کنید. به طور کلی زمانی که شما با storyboardها کار می کنید، شما به سادگی مقدار YES را برگردانده و خود storyboard باقی کارها را انجام می دهد.



اضافه کردن یک کنترلر Tab Bar :
Main.storyboard را باز کرده و یک نمونه  UITabBarController را از بخش Object Library به سمت راست محیط آن درگ کنید. به صورت پیشفرض، کنترلر tab bar با دو view controller همراه است.  در ادامه به شما خواهیم گفت که چگونه view controllerهای اضافی را به کنترلر tab bar به صورت دستی اضافه کنید.  اکنون  view controllers را انتخاب کرده و آنها را از storyboard حذف کنید. البته اینجا منظور، کنترلر tab bar نیست.

اگر برنامه را در شبیه ساز iOS اجرا کنید، شما باید یک tab bar در بخش پایین  و همچنین با یک پس زمینه سیاه روبرو شوید. البته این حالت شاید چندان مهم به نظر رسد اما به هر حال نشان می دهد که یک کنترلر tab bar چگونه کار می کند. یک کنترلر tab bar، آرایه ای از view controllerها را مشابه به همان گونه ای که یک کنترلر کاوشگر مجموعه ای از view controller را سازمان دهی می کند، مدیریت می کند.
چیزی که ما در حال حاضر باید انجام دهیم اضافه کردن چند view controller به storyboard و در نهایت اضافه کردن آنها به مشخصه viewControllers متعلق به کنترلر tab bar است. حال اجازه دهید ببنیم چه کارهایی را برای این منظور باید انجام دهیم. با ما همراه باشید.
اضافه کردن View Controllerها :
ابتدا یک نمونه UITableViewController را از بخش Object Library به فضای کاری درگ کرده و کلاس آن را در بخش Identity Inspector تحت مقدار TSPAuthorsViewController تنظیم کنید. حال نمای جدولی view controller را انتخاب کرده و در رابط Attributes Inspector تعداد Prototype Cells را تحت مقدار 0، همانطور که آموزش قبلی گفته شده ذخیره کنید.

به منظور اضافه کردن view controller متعلق به نویسندگان به آرایه view controller های متعلق به کنترلر tab bar، در حالی که کلید Control روی صفحه کلید را نگه داشته اید، از بخش کنترلر tab bar یکی را به بخش view controller متعلق به نویسندگان درگ کنید. حال تحت فهرست Relationship Segue و از منویی که نمایان می شود بخش view controllers را برگزینید.

 

یک کنترلر tab bar با تنها یک زبانه کارایی چندانی برای برنامه ما ندارد، حال اجازه دهید تا یک view controller دیگر به این مجموعه اضافه کنیم. برای این منظور یک نمونه دیگر UITableViewController را از بخش Object Library درگ کرده و مقادیر کلاس و تعداد Prototype Cells را به ترتیب تحت TSPBooksViewController و 0 تنظیم کنید. حال همانطور که ما برای authors view controller اقدام کردیم یک relationship segue نیز ایجاد کنید.

اکنون یک نمونه UIViewController را به فضای کاری اضافه کرده و کلاس آنرا نیز تحت مقدار TSPBookCoverViewController در بخش Identity Inspector تنظیم کنید. حال همانطور که در بخش قبل دیدید یک نمونه از UIImageView را به view controller اضافه کرده و آن را به  خروجی bookCoverView متعلق به view controller متصل کنید.
همانگونه که ما برای کنترلرهای table view عمل کردیم حال یک relationship segue با کنترلر tab bar ایجاد کنید.
شما تنها زمانی می توانید segueها را ایجاد کنید که فضای کاری در حالت zoomed out قرار نگرفته باشد که البته این مورد می تواند گاهی اوقات با توجه به نوع کار شما آزاردهنده باشد. به هر حال شما می توانید اتصالاتی مانند segueها را از سمت چپ و در بخش navigator ایجاد کنید. این حالت اغلب بسیار راحت تر و دم دستی تر است.

حال برنامه را build کرده و اجرا کنید. در حال حاضر tab bar دارای سه زبانه است. تپ کردن یک زبانه، view controller متعلق به آن زبانه را نشان می دهد.
اگر دقت کرده باشید در این برنامه books view controller به ما یک نمای خالی جدولی را نشان می دهد. خب العان این حالت یک مشکل بوده که باید نسبت به رفع آن اقدام کنیم. با ما همراه باشید.
حل مشکلات موجود تحت Authors view Controller :
زمانی که شما روی نام نویسنده تحت authors view controller تپ می کنید، برنامه از کار باز می ایستد. اولین کاری که شما به هنگام مواجهه با این خطا باید بکنید این است که رابط کنسول نرم افزار Xcode را مورد بررسی قرار دهید. مثلا خطای حاصله برای من عبارت زیر را تحت کنسول نشان می دهد :


2014-03-27 12:42:07.964 Tabbed Library[1943:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<TSPAuthorsViewController: 0x8ca22e0>) has no segue with identifier 'BooksViewController''

فهمیدن و درک پیغامی که نرم افزار Xcode به هنگام بروز خطا در رابط کنسول خود نمایش می دهد سخت نیست. ما به view controller دستور می دهیم که یک segue را با شناسه BooksViewController اعمال کند، اما چون segue موجود نیست نتیجه حاصله این است که برنامه با خطا مواجه می شود.
رفع این خطا با گنجاندن authors view controller در یک navigation controller، ایجاد یک segue برای یک نمونه از کلاس TSPBooksViewController و نام گذاری segue تحت نام BooksViewController بسیار آسان خواهد بود.
با توجه به اینکه ما پیشتر در مقاله قبلی مراحل را گفته ایم به همین جهت انجام این کار را به عهده خود شما می گذاریم.
مسئله مهمتری که در این مثال باید بیشتر مورد توجه و درک واقع شود این است که در واقع سه view controlleای که به کنترلر tab bar پیوند خورده اند، اصلا با یکدیگر هیچ تعامل و ارتباطی ندارند. سیاست و تدبیری که بین هر کدام از کنترلرهای tab bar و کاوشگر نهفته، کاملا متفاوت هست. یک کنترل کاوشگر یک آرایه از view controllerها را تحت عنوان navigation stack نگهداری می کند. view controllerها در داخل navigation stack یک رابطه غیرآشکار با دیگری دارند به طوری که گویی آنها بخشی از همان navigation stack هستند.
همچنین یک کنترلر tab bar، یک آرایه از view controllerها را تحت مدیریت خود قرار می دهد اما view controllerها هیچ اطلاعاتی راجع به یکدیگر ندارند. یعنی اینکه آنها نمی توانند با یکدیگر از طریق کنترلر tab bar ارتباط برقرار کنند. در مقاله قبلی زمانی که روی یک نویسنده تپ می شد ما داده ها را از یک authors view controller به books view controller انتقال می دادیم. اما باید بدانید که این الگو در یک کنترلر tab bar قابل استفاده نیست. البته ما می توانیم راه حلی را به کارگیریم تا به کاربر زمانی که یک نویسنده در authors view  controller تپ شد، books view controller را نشان دهد. اما مهم است که شما بدانید که این حالت هدف یک کنترلر tab bar نیست.
برنامه های Music و Clock تحت سیستم عامل iOS، مثال های خوبی هستند که نشان می دهند چگونه یک کنترلر tab bar باید مورد استفاده قرار بگیرد. view controllerهایی که یک کنترلر tab bar در برنامه Music تحت مدیریت خود قرار می دهد هیچ ارتباطی با دیگری، صرف نظر از این که آنها اصوات را نشان می دهند ندارند.
قبل از ادامه کار، مطمئن شوید که به طور کامل با کنترلرهای tab bar و navigation آشنا شده و درک درستی از نحوه کار با آنها پیدا کرده اید. چرا که در ادامه این سری مقالات از آنها به وفور استفاده خواهیم کرد. با ما همراه باشید.
اضافه کردن یک کنترلر Tab View دیگر :
حال در این بخش می خواهیم چهارمین view controller را به کنترلر tab barای که وظیفه نمایش هر کتاب در Books.plist را دارد اضافه کنیم. برای این منظور ابتدا یک زیر کلاس جدید با نام UITableViewController ایجاد کرده و نام آن را TSPAllBooksViewController قرار دهید.

این view controller تمامی کتاب ها را از Books.plist استخراج کرده و آنها را به صورت الفبایی در یک table view نمایش می دهد.
 اکنون TSPAllBooksViewController.m را باز کرده و یک مشخصه جدید با نام books و از نوع NSArray را به class extension در بالا اضافه کنید :


#import "TSPAllBooksViewController.h"
 
@interface TSPAllBooksViewController ()
 
@property NSArray *books;
 
@end

 

در متد viewDidLoad متعلق به view controller، ما متد extractBooks که یک متد کمکی است را فراخوانی می کنیم. به صورت کلی سعی من بر این است که viewDidLoad را به مختصرترین حالت ممکن از نظر میزان کد، با گنجاندن وظایف در متدهای راهنمایی هچون extractBooks تبدیل بکنم.
این تدبیر سیب کوتاه شدن کد و به طبع ساده تر شدن درک و افزایش پایداری آن خواهد شد. به دستورات زیر خوب دقت کنید :


- (void)viewDidLoad {
    [super viewDidLoad];
 
    // Set Title
    self.title = @"Books";
 
    // Extract Books
    self.books = [self extractBooks];
}

حال اجازه دهید تا الگوی پیاده سازی extractBooks را مورد بررسی قرار دهیم. با ما همراه باشید.
ما کارمون را با ایجاد یک آرایه‌ای از ثابت ها آغاز می کنیم. در واقع ساخت این آرایه برای جایی است که قصد داریم کتاب های را برای هر نویسنده در لیست مشخصه اضافه کنیم. اگر مقاله پیشین را خوب مطالعه کرده باشید، دو خط بعد باید برایتان آشنا باشد. ما از باندل برنامه مسیر فایل Books.plist را درخواست کرده و از این آدرس به منظور بارگذاری محتویات Books.plist به درون یک آرایه با نام authors استفاده می کنیم. سپس ما با استفاده از یک حلقه، آرایه نویسندگان را کاوش کرده و کتاب های هر نویسنده را به آرایه‌ای از ثابت ها که پیش از این ایجاد کردیم اضافه می کنیم. به منظور مرتب سازی آرایه کتاب ها، ما یک sort descriptor همراه با یک کلید از Title می سازیم. بعد از اینکه ما کتاب ها را بر حسب Title مرتب کردیم، یک آرایه جدید تحت عنوان result با مرتب کردن آرایه ثابتها با استفاده از sort descriptor ایجاد می شود. در نهایت نیز ما لیست مرتب شده از کتاب ها را برمیگردانیم.



- (NSArray *)extractBooks {
    // Buffer
    NSMutableArray *buffer = [[NSMutableArray alloc] init];
 
    // Load Authors
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Books" ofType:@"plist"];
    NSArray *authors = [NSArray arrayWithContentsOfFile:filePath];
 
    for (int i = 0; i < [authors count]; i++) {
        NSDictionary *author = [authors objectAtIndex:i];
 
        // Add Books to Buffer
        [buffer addObjectsFromArray:[author objectForKey:@"Books"]];
    }
 
    // Sort Books Alphabetically
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"Title" ascending:YES];
    NSArray *result = [buffer sortedArrayUsingDescriptors:@[sortDescriptor]];
 
    return result;
}


Sort descriptorها و نمونه هایی از NSSortDescriptor به منظور مرتب سازی مجموعه ای از اشیاء مانند آرایه ها مورد استفاده قرار گرفته اند. که البته این فرایند با معین کردن مشخصه ای صورت می گیرد که لازم است به منظور مقایسه دو شی از مجموعه مورد استفاده قرار بگیرد. به هر حال اگر این فرایند برای شما کاملاً روشن و واضح نیست، می توانید بدون هیچ نگرانی‌ای از این بخش از پیاده سازی extractBooks صرف نظر کنید چرا که این بخش در حوضه این مقاله آموزشی اهمیت چندانی ندارد.
پیاده سازی متد پروتکلی UITableViewDataSource بسیار مشابه به چیزی است که شما در این سری مقالات با آن روبر شدید. حال در ادامه قصد داریم تا پیاده سازی هر یک از متدها را مورد بررسی قرار دهیم. با ما همراه باشید.


- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.books count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Dequeue Reusable Cell
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    // Fetch Book
    NSDictionary *book = [self.books objectAtIndex:[indexPath row]];
    
    // Configure Cell
    [cell.textLabel setText:[book objectForKey:@"Title"]];
    
    return cell;
}

همانطور که در پیشتر در مورد table viewها مشاهده کردید، ما لازم است تا شناسه قابل استفاده مجدد سلول یا  cell reuse identifier را اعلان کرده و همچنین برای این شناسه یک کلاس را ثبت کنیم :

 


@implementation TSPAllBooksViewController
 
static NSString *CellIdentifier = @"Cell Identifier";
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Set Title
    self.title = @"Books";
    
    // Extract Books
    self.books = [self extractBooks];
    
    // Register Class for Cell Reuse
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
}

 

با کلاس جدید و آماده برای استفاده view controller به بخش storyboard مراجعه کرده و یک نمونه UITableViewController را از بخش Object Library درگ کرده و کلاس آن را نیز تحت TSPAllBooksViewController تنظیم کنید. سپس در حالی که table view در حالت انتخاب قرار گرفته است، تعداد Prototype Cells را در بخش Attributes Inspector تحت مقدار 0 تنظیم کنید. پیش از اینکه برنامه را در شبیه ساز iOS اجرا کنید،  یک relationship segue بین دو کنترلر tab bar و table view که پیش از این اضافه کردیم ایجاد کنید.

حال پروژه را build کرده و اجرا کنید تا نتیجه زحمات سخت خود را ملاحظه کنید. اگر کمی ریزبین باشید، شاید دقت کرده باشید که عنوان زبانه چهارم تنها زمانی پدیدار می شود که این زبان مورد انتخاب قرار گیرد. به نظر شما علت این امر چیست؟ برای فهمیدن علت این امر ادامه این مقاله را از دست ندهید. با ما همراه باشید.

علت این مشکل یک امر بسیار ساده و واضح است. به طور کلی یک نما(View) تا زمانی که به طور صددر صد مورد نیاز نباشد به درون حافظه بارگذاری نمی شود. این حالت معمولا بدان معناست که تنها زمانی یک نما وارد حافظه می شود که قرار است به کاربر نشان داده شود.
زمانی که برنامه Tabbed Library اجرا می شود، اولین زبان به صورت پیشفرض تحت انتخاب قرار می گیرد. تا مادامی که چهارمین زبانه به واسطه کاربر یا از طریق برنامه نویسی مورد انتخاب قرار نگرفته باشد، نیازی به بارگذاری نمای چهارمین View Controller وجود ندارد. پس نتیجه حاصله این است که متد viewDidLoad تا زمانی که چهارمین کنترل انتخاب نشود مورد فراخوانی قرار نمی گیرد. که در اصل یعنی اینکه عنوان زبانه چهارم تا زمانی که مورد انتخاب قرار نگیرد تنظیم نخواهد شد.
راه حل برای این مسئله ساده است. یک روش خوب برای این مسئله این است که مثلا هنگامی که view controller  مورد ارزشیابی یا همان بارگذاری قرار گرفت، عنوان آن را از طریق کدنویسی تنظیم شود. اگر ما عنوان را در متد init کلاس تنظیم کنیم،  می توانیم مطمئن باشیم که عنوان view controller در موقع مناسب تنظیم می شود.
حال TSPAllBooksViewController.m را باز کرده و یک متد با نام initWithCoder: را همانطور که در پایین می بینید به آن اضافه کنید.
این متد به وسیله سیستم عامل مورد فراخوانی قرار گرفته تا یک نمونه از کلاس را ایجاد کند. به دستورات زیر دقت کنید :


- (id)initWithStyle:(UITableViewStyle)style {
    self = [super initWithStyle:style];
    
    if (self) {
        // Set Title
        self.title = @"Books";
    }
    
    return self;
}


حال زمان خوبی است تا روند دستوری یک متد متداول init را مورد بررسی قرار دهیم. یک متد ارزشیابی معمولاً با یک فراخوانی به متد init متعلق به کلاس پدر کار خود را شروع می کند. البته در اینجا آن متد initWithCoder: است. اگر به یاد داشته باشید زمانی که ما پیشتر در این سری متد viewDidLoad را شرح دادیم گفتیم که چرا این متد از اهمیت بسیاری برخوردار است. نتیجه [super initWithCoder:aDecoder] تحت self که در واقع نمونه ای از کلاسی است که ما در حال کار بر روی آن هستیم تنظیم شده است.
در مرحله بعد، ما بررسی می کنیم که در اصل self یک nil نیست. اگر self تحت nil تنظیم نشده باشد، وقت آن رسیده تا توجه بیشتری به نمونه کلاس یعنی self داشته باشیم. یک متد ارزشگذار، همیشه باید یا نمونه کلاس را برگرداند یا اگر اشکالی پیش آمد، nil را به عنوان خروجی منتقل کند.


در دستور شرطی ifی که در متد initWithCoder: قرار گرفته است ما مشخصه title متعلق به view controller را تنظیم می کنیم تا مشکلی که چند لحظه پیش در مورد آن صحبت کردیم حل شود.
از نقطه نظر تئوری، مراحل زیادی را باید برای حل یک مسئله جزیی طی می کردیم. اما به هر حال توضیحات بالا یک شروع و مقدمه خوب برای دیگر بخش مهم کنترلرهای tab bar و آیتم های آن به شمار می رود. در این لحظه زبانه های کنترلر tab bar تنها عنوان هر یک از view controllerها را نمایش داده و یا در مورد view controller دوم و سوم، یک عنوان پیشفرض با مقدار item نمایش داده خواهد شد.
در اغلب برنامه ها، زبانه ها همچنین یک آیکون کوچک که به تابع یا نوع کارکرد view controller اشاره می کند در زیر زبانه نمایش می دهند. حال اجازه دهید تا ببینیم این روش چگونه کار می کند با ما همراه باشید.
آیتم های Tab Bar :
اگر به یاد داشته باشید من در مقاله قبلی گفتم که هر view controller تحت یک navigation stack، یک ارجاع به کنترل کاوشگری که stack را مدیریت می کند نگه می دارد. حالا همین حالت برای view controllerهایی که تحت یک کنترلر tab bar مدیریت می شوند صدق می کند. یعنی اینکه یک view controllerای که تحت مدیریت یک کنترلر tab bar باشد یک ارجاع یا همان refrence به کنترل tab bar تحت مشخصه tabBarController خود نگه می دارد.
علاوه بر این خصوصیات، یک view controller همچنین یک مشخصه tabbaritem دارد که در واقع یک نمونه منحصر به فرد از کلاس UITabBarItem به شمار می رود.
این مشخصه زمانی که view controller، فرزند یک کنترلر tab bar باشد مورد استفاده قرار می گیرد. هر یک از آیتم های  کنترلر tab bar از یک عنوان، یک تصویر و یک تگ یا همان برچسب برخوردار هستند. در اینجا تگ، تنها یک عدد بوده که می تواند به منظور شناسایی یک آیتم در کنترلر tab bar مورد استفاده قرار بگیرد. به صورت پیشفرض عنوان آیتم های کنترلر tab bar از مشخصه title متعلق به view controller گرفته می شود. در واقع به همین علت است که اولین و آخرین زبانه در برنامه Tabbed Library، عنوان view controller نظیر خود را ایجاد می کنند.
حال فایل TSPAuthorsViewController.m را باز کرده و متدی با نام initWithCoder: را همانطور که در دستورات زیر می بینید به آن اضافه کنید :


- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    
    if (self) {
        // Set Title
        self.title = @"Authors";
        
        // Set Tab Bar Item
        self.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Authors" image:[UIImage imageNamed:@"icon-authors"] tag:0];
    }
    
    return self;
}

اکنون ما یک آیتم tab bar ایجاد کرده و آنرا تحت مشخصه tabbaritem متعلق به view controller تنظیم می کنیم. مقدار دهنده(ارزش دهنده یا همان initilizer) متعلق به کلاس UITabBarItem یک عنوان از نوع NSSring، یک تصویر از نوع UIImage و یک برچسب از نوع NSInteger را می پذیرد. قبل از build و اجرای پروژه خود، فایل های سرس موجود برای این بخش را دانلود کرده و دو فایل icon-authors.png و icon-authors@2x.png را تحت پروژه خود بارگذاری کنید.
همانطور که احتمالاً به خاطر می آورید، فایلی با پسوند @2x دستگاه هایی را مد نظر قرار می دهد که از صفحه نمایش رتینا پشتیبانی می کنند در حالی که فایل های بدون پسوند @2x دستگاه هایی را تحت پشتیبانی خود قرار می دهند که از صفحه نمایش غیر رتینا برخوردار هستند.
دقت داشته باشید که به هنگام استفاده از متد کلاس imageNamed: تحت UIImage لازم نیست تا پسوند فایل تصویری را ذکر کنید. به طور کلی، لازم نیست تا مشخص کنید چه نوع از فایل(منظور رتینا یا غیر آن) باید مورد استفاده قرار بگیرد. چرا که بر اساس نام فایل و سخت افزار دستگاه، خود سیستم عامل به صورت هوشمند و خودکار تصمیم می گیرد که از چه نسخه ای استفاده کند.
همانطور که ما در کلاس TSPAllBooksViewController عمل کردیم، من همچنین تنظیم title برای متد initWithCoder: را منتقل کردم. حال برنامه را به یکباره اجرا کنید تا نتایج را ملاحظه نمایید.
ما می توانیم همان سیاست را در مورد کلاس TSPAllBooksViewController به کار ببریم. برای این منظور فایل MTAllBooksViewController.m را باز کرده و متد initWithCoder: را همانطور که در دستورات زیر مشخص است؛ تغییر دهید :


- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    
    if (self) {
        // Set Title
        self.title = @"Books";
        
        // Set Tab Bar Item
        self.tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem:UITabBarSystemItemContacts tag:1];
        
        // Set Badge Value
        [self.tabBarItem setBadgeValue:@"12"];
    }
    
    return self;
}

علاوه بر تنظیم عنوان view controller، ما همچنین مشخصه tabBarItem را نیز تنظیم می کنیم. به هر حال، این بار ما از initWithTabBarSystemItem:tag: به منظور پیکربندی آیتم tab bar استفاده می کنیم. شما اگر تمایل به استفاده از یک آیتم tab bar سیستمی داشته باشید می توانید از این متد بهره ببرید. اولین آرگومان از این متد یعنی UITabBarSystemItem هم عنوان و هم تصویر آیتم tab bar را مشخص می کند.
همچنین این امکان وجود دارد تا به یک آیتم tab bar یک مقدار نشانی همانطور که در پیاده سازی متد initWithCoder: در بالا مشخص است بدهید. این مقدار نشانی یا badge value انتظار می رود تا یک نمونه NSString باشد.
زمانی که با کنترلرهای tab bar کار می کنید، دقت داشته باشید که در واقع آن یک view controller ریشه از هر زبانه ای است که تعیین می کند چگونه آیتم tab bar از زبانه های متناظر به نظر برسند.
به عنوان مثال، اگر یک کنترلر tab bar، یک کنترلر کاوشگر را با تعدادی از view controllerها مدیریت کند، در واقع آن آیتمی از view controller ریشه متعلق به navigation controller است که توسط tab bar متعلق به کنترلر tab bar مورد استفاده قرار می گیرد. کلاس UITabbarItem از چند متد اضافی دیگر به منظور سفارشی سازی بیشتر ظاهر و نوع ساختار بیرونی هر آیتم tab bar برخوردار است.
پیش از پایان این مقاله، من تمایل دارم تا به شما نشان دهم چگونه یک tab bar زمانی که کنترلر tab bar بیشتر از 5 view controller را مدیریت می کند به نظر می رسد. همانطور که قبلاً گفتم، تنها 5 زبانه در آن واحد قابل نمایش است، اما باید بدانید که کنترلر tab bar به طور کلی بیشتر از پنج view controller فرزند را نیز پشتیبانی می کند.
حال main storyboard را باز کرده و دو نمونه دیگر از UITableViewController را اضافه کنید. اکنون یک relationship segue برای هر table view controller ایجاد کرده و برنامه را تحت شبیه ساز iOS اجرا کنید تا نتیجه نهایی کار را ببینید.
view controllerهای دیگری که ما اضافه کردیم خیلی کاربردی و مفید نیستند اما به هر حال آنها نشان می دهند که چگونه یک کنترلر tab bar بیشتر از 5 view controller فرزند را مدیریت می کند.
کنترلرهای tab bar امکان دسترسی به پنجمین و ششمین view controller تحت کنترلر tab bar را به شما اعطاء می کنند. ناگفته نماند همچنین به کاربران این قابلیت اعطا شده تا بتوانند مکان و موقعیت view controllerها در tab bar بنا به تمایل خود تغییر دهند.
نتیجه گیری :
مهم است که بدانید کلاس های UITabBarController و UINavigationController هر یک الگوی رابط کاربری متفاوتی را ارائه می کنند. این مقاله همچنین نشان می دهد که مسلط شدن بر کنترلرهای tab bar و استفاده کامل از امکانات آنها بعد از اینکه اجزاء پیش نیاز آنها را درک کردید چندان سخت نیست. به هر حال اگر تا اینجا اطلاعات گفته شده نتوانسته شما را به طور کامل با نحوه کارکرد این نوع کنترلر آشنا کند پیشنهاد می کنم از منابع دیگر نیز بهره برده تا در ادامه کار با مشکل برنخورید.. در مقاله بعدی نگاهی به نگهداری داده ها یا data persistence و همچنین گزینه هایی را که به عنوان یک برنامه نویس در اختیار دارید خواهیم انداخت. پس تا آن موقع با ما همراه باشید. در پایان امیدوارم از این مقاله بهره لازم را برده باشید.

مترجم:هادی نجار

منبع:code.tutsplus.com

تعداد بازدید : 908

نظرات
ناشناس
خیلی ممنون.آموزشتون جزو تخصصی ترین آموزش های اپلی ای بود که من خوندم.فقط امیدوارم ادامه دار باشه.
ناشناس
سلام کتاب و جزوه ای میشناسید در زمینه برنامه نویسی اپل که به ما معرفی کنید؟
ارسال نظر

سوال امنیتی : مجموع دو عدد 2 و 5 =