Name of the blog

Short description of the blog

newer

آموزش کار با view controller ها

در این مبحث همچنان بر روی scene و UI مربوطه ی آن در برنامه ی ثبت و مشاهده ی اطلاعات غذا،FoodTracker، کار خواهید کرد. ترتیب المان های جاری UI را تغییر داده و با استفاده از image picker یک عکس به رابط کاربری برنامه ی خود اضافه خواهید نمود.

در پایان برنامه ظاهری مشابه زیر خواهد داشت:

clip_image002

آنچه خواهید آموخت

1.      با چرخه ی حیات view controller و مفهوم آن آشنا شده، بدانید توابع بازفراخوان/callback های آن، viewDidLoad، viewWillAppear و viewDidAppear چه زمانی صدا خورده و اجرا می شوند. 

2.      بتوانید بین view controller ها داده رد و بدل نمایید.

3.      یک view controller را از صفحه حذف یا پنهان کنید.

4.      با الحاق کردن آبجکت های gesture recognizer به view، قابلیت تعامل با کاربر و واکنش نشان دادن به رخداد/event ها را به آن اعطا نمایید.

5.      بر اساس سلسله مراتب و زنجیره ی ارث بری (class hierarchy) UIView/UIControl، رفتار یک آبجکت را پیش بینی کنید.

6.      با استفاده از ابزار asset catalog، محتوا و منابعی همچون عکس را به پروژه اضافه نمایید.

آشنایی با life cycle/چرخه ی حیات View Controller و مفهوم آن

در حال حاضر، برنامه ی FoodTracker از تنها یک scene یا صفحه ی محتوا برخوردار است که UI آن توسط فقط یک view controller مدیریت می شود. با ساخت اپلیکیشن های پیچیده تر، نا گزیر با scene های بیشتری سر و کار داشته و علاوه بر آن می بایست بارگذاری و حذف view ها از حافظه را همین که بر روی صفحه نمایش داده و سپس از آن حذف می شوند، اداره نمایید.  

آبجکتی که از روی کلاس UIViewController (و کلاس های فرزند آن) ساخته می شود، تعدادی متد پیش فرض دارد که توسط آن ها view hierarchy (نمای سلسله مراتبی از آبجکت ها/view های یک scene همچون دکمه، لیبل) خود را مدیریت می کند. زمانی که یک view controller تغییر وضعیت می دهد (برای مثال در صفحه نمایش داده می شود و سپس از آن حذف می گردد)، IOS خود این متدها را در زمان مناسب فراخوانی می کند. 

کلاس فرزندی که از UIViewController ایجاد می کنید، مانند کلاس ViewController که در برنامه ی جاری با آن کار می کنید، تمامی متدهای کلاس والد (UIViewController) را به ارث برده و در این حین به شما امکان می دهد تا کد خود را جهت پیاده سازی عملیات و رفتار دلخواه به بدنه ی این متدها اضافه نمایید. به منظور تنظیم و آماده سازی view ها جهت نمایش در صفحه یا حذف آن ها در زمان مناسب (یا گام مربوطه در فرایند مزبور)، آگاهی از ترتیب و زمان دقیق فراخوانی متدهای نام برده ضروری است. البته این عملیات کمی پیچیده بوده و در مباحث آینده به پیاده سازی آن خواهید پرداخت.

clip_image004

متدهای کلاس UIViewController به ترتیب شرح داده شده در زیر صدا خورده و اجرا می شوند:

·         viewDidLoad() – زمانی فراخوانی می شود که content view (view ای که در بالای سلسله مراتب قرار گرفته و چندین view دیگر را دربرمی گیرد) کلاس view controller ایجاد شده و از storyboard بارگذاری می شود. این متد ویژه ی تنظیم اولیه تعبیه شده است. لازم به ذکر است که view ها، گاهی به دلیل عدم وجود منابع کافی، از برنامه حذف می شوند و از اینرو هیچ تضمینی وجود ندارد که متد مذکور تنها یکبار فراخوانده شود (ممکن است به دلیل منابع محدود و حذف view ها از صفحه، لازم باشد چندین بار فراخوانی شود).

·         viewWillAppear() ویژه ی عملیاتی طراحی شده که می خواهید حتما پیش از به نمایش گذاشتن  view برای کاربر، انجام شوند. از آنجایی که امکان دارد قابلیت رویت یک view به دلیل وجود دیگر view ها، بین دو حالت تغییر کند (نمایش داده شده/پنهان شود) یا کلا تحت الشعاع قرار گیرد، این متد همیشه بلافاصله قبل از نمایان شدن content view بر روی صفحه صدا زده می شود.

·         viewDidAppear() – عملیاتی که می خواهید بلافاصله پس از نمایان شدن view بر روی صفحه، انجام شوند از جمله واکشی داده ها و به اجرا گذاشتن یک انیمیشن و غیره ... در بدنه ی این متد تعریف می شوند. از آنجایی که امکان دارد قابلیت رویت یک view به دلیل وجود دیگر view ها، بین دو حالت تغییر کند (نمایش داده شده/پنهان شود) یا کلا تحت الشعاع قرار گیرد، این متد همیشه بلافاصله پس از نمایان شدن content view بر روی صفحه صدا زده می شود. 

همان طور که در نمودار فوق مشاهده می کنید، تعدادی متد مکمل نیز جهت teardown یا حذف view از صفحه وجود دارد.

برخی از متدهای ذکر شده را جهت بارگذاری و نمایش داده های view در زمان مناسب، در برنامه ی FoodTracker مورد استفاده قرار خواهید داد. در واقع، اگر بخاطر داشته باشید، داخل بدنه ی یکی از این متدها (تابع viewDidLoad() از کلاس ViewController) کدنویسی کردید:

override func viewDidLoad() {

super.viewDidLoad()

// Handle the text field’s user input through delegate callbacks.

nameTextField.delegate = self

}

این سبک طراحی برنامه که در آن view controller ها به عنوان پل های ارتباطی (pipeline) بین view ها و data model ایفای نقش کرده و زمینه ی تعامل بین آن ها را فراهم  می نمایند، در اصطلاح معماری MVC ( الگو توسعه ی مدل-نما-کنترلگر) خوانده می شود. در این الگوی توسعه، model وظیفه ی کار با داده ها (ارتباط با پایگاه داده/هر منبع داده ای همچون آرایه و واکشی اطلاعات از آنها، ذخیره ی موقت یا تبدیل آن ها به یک شی و همچنین بررسی صحت داده ها) را بر عهده دارد، بخش view ظاهر برنامه/UI را در صفحه به نمایش گذاشته، محتوای قابل مشاهده برای کاربر را ارائه می دهد و در نهایت لایه ی controller اداره ی view ها، مدیریت تعامل با کاربر را عهده دار بوده و در حقیقت واسطی میان model و view محسوب می شود. با واکنش نشان دادن به اعمال یا ورودی کاربر، پر کردن view ها با داده از data model، بخش controller به مثابه ی یک درگاه یا پل ارتباطی بین لایه ی model و view ایفای نقش می کند. در حال حاضر تمامی برنامه های کارامد و پربازده ی IOS مبتنی بر این الگوی توسعه طراحی می شوند و برنامه ی FoodTracker نیز از این امر مستثنی نیست.    

در بخش بعدی UI ساده برنامه را گسترش داده و قالب یا طرح نهایی (layout) آن را مشخص می کنید.

افزودن یک عکس به UI برنامه

مرحله بعدی که آخرین گام در تکمیل ظاهر برنامه ی Foodtracker است، تعریف مکانیزمی جهت نمایش یک عکس، ویژه ی غذای مورد نظر در UI می باشد. برای این منظور از یک image view (کلاس UIImageView) بهره می گیرد. Image view یک المان UI است که تصویری را برای کاربر بر روی صفحه به نمایش می گذارد. 

به منظور افزودن image view به scene فعلی مراحل زیر را گام به گام دنبال نمایید:

1.      فایل storyboard خود، Main.storyboard را از project navigator انتخاب کرده و باز نمایید.

2.      Object library را از utility area باز نمایید (یا این مراحل را دنبال نمایید: View > Utilities > Show Object Library).

 

clip_image006

3.      داخل فیلد جستجوی Object library، عبارت image view را وارد نمایید تا Xcode به سرعت آبجکت Image View را یافته و در اختیار شما قرار دهد.

4.      آبجکت نام برده را از Object library کشیده و در سطح scene جاری، زیر کنترل دکمه جایگذاری کنید.

clip_image008

5.      پس از کلیک بر روی المان image view و انتخاب آن، کادر Size inspector را در utility area باز کنید. اگر بخاطر داشته باشید، Size inspector با کلیک بر روی دکمه ی پنجم از سمت چپ در inspector selector bar، به نمایش در می آید. این کادر به شما اجازه ی تنظیم اندازه و مکان قرار گیری آبجکت مورد نظر در storyboard را می دهد.

clip_image010

6.      از فیلد Intrinsic Size در پایین کادر، گزینه ی Placeholder را انتخاب نمایید.

7.      داخل فیلدهای Width و Height، مقدار 320 را وارد کنید. کلید Return را فشار دهید.

به دلیل اینکه در image view حاضر عکسی برای نمایش وجود ندارد، از intrinsic content size آن (حداقل فضای لازم برای نمایش کامل و بی نقص محتوای view) اطلاع کافی نداریم. بنابراین فیلد Intrinsic Size را بر روی گزینه ی placeholder تنظیم می کنیم تا بعده ها بتوانیم اندازه ی صحیح و constraint های مناسب را در interface builder مشخص کنیم.    

clip_image012

8.      در زیر canvas (پس زمینه ی storyboard)، گوشه ی سمت راست محیط، منوی Pin را با کلیک بر روی سومین دکمه از سمت چپ باز نمایید.

clip_image014

9.      در کادر جاری، چک باکس Aspect Ratio را تیک دار نمایید. هم اکنون منوی Pin باید مشابه زیر باشد:


clip_image016

10.   در منوی Pin، بر روی دکمه ی Add 1 Constraint کلیک نمایید.

clip_image018

Image view در حال حاضر دارای aspect ratio/نسبت پهنا به ارتفاع 1:1 می باشد. بنابراین یک مربع را برای کاربر به نمایش می گذارد.

11.   پس از کلیک بر روی المان image view و انتخاب آن، کادر Attribute inspector را باز کنید.

اگر بخاطر داشته باشید، کادر Attribute inspector با کلیک بر روی دکمه ی چهارم از سمت چپ در inspector selector bar باز می شود. در این کادر شما می توانید property های یک آبجکت را در storyboard خود ویرایش کنید.

12.   در کادر Attribute inspector، فیلدی که Interaction نام دارد را پیدا کرده و سپس چک باکس User Interaction Enabled را تیک دار نمایید. این امکان به کاربران اجازه می دهد تا با المان image view تعامل داشته باشند.

اپلیکیشن شما اکنون باید ظاهری مشابه زیر داشته باشد:

clip_image020

به نمایش گذاشتن یک عکس مکان نگهدار در image view

شما باید به طریقی به کاربر اعلان کنید که اجازه دارد با المان image view تعامل داشته و از آن یک عکس را انتخاب و مشاهده نماید. برای نیل به این هدف، یک عکس به عنوان مکان نگهدار در این المان به نمایش می گذارید که کاربر با مشاهده ی آن متوجه می شود که می تواند با آن تعامل داشته و تصویری را برای مشاهده انتخاب کند.

clip_image022

می توانید این تصویر را در پوشه ی  Images/ از پروژه ی حاضر (پس از دانلود آن) انتخاب کنید یا عکس دلخواه خود را انتخاب نمایید.

به منظور افزودن یک عکس به پروژه ی خود مراحل زیر را دنبال نمایید:

1.      در project navigator، با کلیک بر روی فایل Assets.xcassets، ابزار asset catalog را باز کنید. asset catalog بستری است که در آن asset های پروژه (محتوای برنامه ی خود همچون عکس ها، فایل های تصویری و متنی) را ذخیره و سازمان دهی می کنید.

2.      در پایین محیط کاری Xcode، گوشه ی سمت چپ بر روی دکمه ی (+) کلیک کرده و سپس گزینه ی New Image Set را از منوی pop-up انتخاب نمایید.      

clip_image024

3.      بر روی اسم image set دوبار کلیک کرده و آن را به defaultPhoto تغییر دهید.

4.      عکس دلخواه را از حافظه ی کامپیوتر خود انتخاب کنید.

5.      حال عکس را کشیده و آن را در فضای خالی 2x در image set جایگذاری کنید.

clip_image026

 

2x ، وضوح تصویر نرم افزار شبیه ساز/simulator iPhone 6 در محیط Xcode است. از اینرو عکس مورد نظر باید با بهترین کیفیت به نمایش گذاشته شود.  

پس از افزودن عکس مکان نگهدار به پروژه، بایستی تنظیمات image view را انجام دهید تا این المان بتواند عکس مورد نظر را در UI برای کاربر به نمایش بگذارد.

جهت نمایش عکس مکان نگهدار در المان image view، مراحل زیر را گام به گام دنبال نمایید:

1.      فایل storyboard را باز کنید.

2.      در storyboard، المان image view را انتخاب نمایید.

3.      پس از کلیک بر روی المان مورد نظر، کادر Attributes inspector را از utility area باز کنید.

4.      در Attribute inspector، فیلدی که Image نام دارد را پیدا کرده و سپس گزینه ی defaultPhoto را از آن انتخاب نمایید.  

تست کنید: برنامه را در شبیه ساز اجرا کنید. می بینید که عکس مکان نگهدار در المان image view به نمایش در می آید.  

clip_image027

 

 

متصل کردن المان image view به کد مربوطه در فایل ViewController.swift

در این بخش بایستی با کدنویسی قابلیتی به المان image view اضافه کنید که به شما اجازه می دهد محتوای آن را در زمان اجرای برنامه (runtime)، تغییر دهید. شما باید بتوانید تصویر را از داخل کد (با کدنویسی) تغییر دهید. برای این منظور ابتدا لازم است المان image view را به کد مربوطه در فایل ViewController.swift متصل کنید.   

جهت متصل کردن المان image view به کد مرتبط در فایل ViewController.swift، مراحل زیر را گام به گام دنبال نمایید:

1.      بر روی دکمه ی Assistant در نوار ابزار Xcode، بالای محیط گوشه ی سمت راست کلیک نموده و ویرایشگر کمکی (assistant editor) را باز کنید.  

clip_image029

2.      در صورت نیاز به فضای کاری بیشتر، با کلیک بر روی دکمه های navigator toggle و utility toggle در نوار ابزار Xcode، می توانید project navigator و utility area را ببندید. 

clip_image031

در صورت تمایل، می توانید کادر outline view را نیز ببندید.

3.      در storyboard، المان image view را انتخاب نمایید. 

4.      حال المان نام برده را از سطح scene جاری کشیده و در ناحیه ی ویرایش کد (سمت راست محیط، داخل فایل ViewController.swift) در زیر outlet جاری (متغیر mealNameLabel) جایگذاری نمایید. 

clip_image033

5.      در پنجره ی محاوره ای که به نمایش در می آید، واژه ی photoImageView را وارد فیلد Name نمایید. لازم نیست سایر تنظیمات را دستکاری کنید. پنجره ی محاوره ای هم اکنون می بایست به صورت زیر باشد:

clip_image035

6.      حال بر روی دکمه ی Connect کلیک نمایید.

Xcode یک اشاره گر در قالب متغیری با نام photoImageView به المان مزبور در فایل ViewController.swift ایجاد می کند. سپس storyboard را جهت برقراری اتصال بین کد و المان مربوطه در UI تنظیم می نماید.

@IBOutlet weak var photoImageView: UIImageView!

حال می توانید از کد به المان image view در UI دسترسی داشته و محتوای آن را تغییر دهید. اما اینجا یک سوال جالب مطرح می شود! از کجا بفهمیم چه زمانی باید عکس یا محتوای المان مزبور را تغییر دهیم؟ شما می بایست روشی تعریف کنید که کاربران از طریق آن بتوانند تمایل خود مبنی بر تغییر محتوای image view را به نحوی بیان کنند، برای مثال با کلیک (قرار دادن انگشت) بر روی image view.  

پس از آن یک action method تعریف می کنید که به مجرد رخداد tap (کلیک کاربر بر روی المان)، صدا خورده شده و محتوای المان را تغییر می دهد.

گفتنی است که بین view و control یک تفاوت جزئی وجود دارد. همان طور که می دانید control ها نسخه های ویژه از view ها هستند که به شیوه ای خاص به ورودی یا اعمال کاربر واکنش نشان می دهند. در واقع view صرفا محتوای ساده ای را برای کاربر به نمایش می گذارد، در حالی که یک control امکان ویرایش محتوا (به نحوی خاص) را نیز در اختیار کاربر قرار می دهد.

control (کلاس UIControl) در حقیقت از کلاس UIView ارث بری می کند (یک کلاس فرزند از UIView است). از نمونه های view می توان به label و image view اشاره کرده و از control ها می توان از text field و button نام برد که اگر بخاطر داشته باشید قبلا با تمامی آن ها در UI برنامه ی خود کار کرده اید. 

تعریف یک Gesture Recognizer (اعطای قابلیت های یک control به view)

همان طور که در بالا گفته شد، المان image view از نوع control نیست، بنابراین واکنشی که در پاسخ به ورودی کاربر نشان می دهد با یک control –همچون دکمه – یکسان نیست (در اصل طوری طراحی نشده که به عمل کاربر مانند یک کنترل واکنش نشان دهد). به عنوان مثال، نمی توانید به راحتی و بدون هیچ گونه واسطی یک action method تعریف کرده، آن را به image view متصل کنید که به مجرد کلیک کاربر بر روی المان مذکور مستقیما فراخوانی/اجرا می شود (اگر بر روی المان در interface builder کلیک کرده و آن را به ناحیه ی ویرایش کد بکشید، می بینید که داخل کادر محاوره ای امکان انتخاب گزینه ی Action از فیلد connection وجود ندارد).  

خوشبختانه، به راحتی می توانید قابلیت های یک control را به view مورد نظر اعطا کنید. برای این منظور کافی است از gesture recognizer استفاده نمایید. gesture recognizer ها آبجکت هایی هستند که با الصاق آن ها به view، به آن ها این امکان داده می شود تا درست مانند یک control به action یا فعل کاربر واکنش نشان دهند.

Gesture recognizer ها حالات مختلف لمس را شناسایی کرده و هر یک را به فعل خاصی تفسیر می کنند. در واقع زمانی که کاربر نمایشگر را با حالت خاصی لمس می کند، IOS آن را مورد بررسی و تحلیل قرار می دهد. سپس آن حالت خاص لمس را معادل یکی از حالات تعریف شده برای سیستم عامل مورد نظر همچون pinch، swipe یا rotation در نظر می گیرد. در پی آن، متناسب با حالت لمس تفسیر شده، (پس از فراخوانی متد متصل به آن gesture recognizer) عملیات معینی نظیر کوچک/بزرگ کردن صفحه یا چرخاندن تصویر را ترتیب می دهد.

جهت اعطا کردن قابلیت های یک control به view (واکنش نشان دادن به عمل کاربر)، کافی است یک آبجکت gesture recognizer به آن view متصل کنید. سپس یک action method تعریف کنید که به مجرد اینکه gesture recognizer حالت لمس کاربر را شناسایی و تفسیر کرد، آن متد فراخوانی شود.

 در این بخش با الصاق یک gesture recognizer به المان image view، قابلیت تعامل با کاربر را به این المان اعطا می کنیم.

ابتدا یک tap gesture recognizer (از کلاس UITapGestureRecognizer) به المان image view الحاق کنید. با این کارِ شما، زمانی که کاربر با انگشت خود به سطح نمایشگر ضربه می زند، gesture recognizer آن را شناسایی کرده و پس از تفسیر آن (و فراخوانیaction method  مربوطه) زمینه ی تعامل کاربر با المان مزبور را فراهم می آورد.

جهت افزودن یک tap gesture recognizer به المان image view در storyboard، مراحل زیر را گام به گام دنبال نمایید:  

1.      در مرحله ی اول، Object library را باز کنید. (روش سریع برای باز کردن آن: View > Utilities > Show Object Library.)

2.      داخل فیلد جستجوی Object library، واژه ی tap gesture را وارد کنید تا محیط Xcode آبجکت مد نظر را یافته و به سرعت در اختیار شما قرار دهد. 

3.      آبجکت Tap Gesture Recognizer را از Object library کشیده و آن را بر روی المان image view در scene کنونی جایگذاری نمایید.

Attach a tap gesture recognizer (UITapGestureRecognizer) to the image view, which will recognize when a user has tapped the image view. You can do this easily in your storyboard.

clip_image037

می بینید که آیکون Tap Gesture Recognizer در scene dock نمایان می شود (نواری در بالای scene که اطلاعاتی را درباره ی آن به نمایش می گذارد).

clip_image039

متصل کردن gesture recognizer به کد مربوطه در فایل ViewController.swift

اکنون زمان آن فرا رسیده که gesture recognizer را به action method در کد متصل کنید.

به منظور متصل کردن gesture recognizer به کد مربوطه در فایل ViewController.swift، مراحل زیر را دنبال نمایید:

1.      بر روی آیکون gesture recognizer در scene dock کلیک کنید، آن را به ناحیه ی ویرایش کد در سمت راست scene جاری کشیده و در زیر خط // MARK: (خط توضیحات مربوط به action ها در فایل ViewController.swift) جایگذاری نمایید:

clip_image041

2.      در کادر محاوره ای که نمایان می شود، گزینه ی Action را از فیلد Connection انتخاب کنید.

3.      در فیلد Name، واژه ی selectImageFromPhotoLibrary را به عنوان اسم متد وارد کنید.

4.      از فیلد Type، گزینه ی UITapGestureRecognizer را انتخاب نمایید. پس از تنظیمات ذکر شده، کادر محاوره ای می بایست به صورت زیر باشد:

clip_image043

5.      حال بر روی دکمه ی Connect کلیک نمایید.

Xcode خود کد مورد نیاز جهت (ایجاد و تنظیم) action method را به فایل ViewController.swift اضافه می کند.

@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {

}

 

 

افزودن یک image picker به پروژه جهت تعامل با کاربر و فراهم آوردن امکان انتخاب عکس

زمانی که کاربر بر روی المان image view در نمایشگر دستگاه ضربه می زند، طبیعتا باید بتواند یک عکس از مجموعه عکس های آماده در حافظه ی دستگاه انتخاب کند یا عکس دلخواه خود را بگیرد. خوشبختانه، کلاس UIImagePickerController تمامی این رفتارها را به صورت درون ساخته در اختیار دارد.

image picker controller رابط کاربری مورد نیاز جهت گرفتن عکس جدید یا انتخاب از میان عکس های ذخیره شده در حافظه ی دستگاه و استفاده از آن ها در برنامه ی جاری را مدیریت می کند. همان طور که به هنگام کار با المان text field به یک delegate احتیاج دارید، برای کار با image picker نیز، ناگزیر به یک delegate image picker controller نیاز دارید. protocol (الگوی پیاده سازی) ویژه ی این delegate عبارت است از UIImagePickerControllerDelegate. همچنین، آبجکتی که به عنوان delegate آبجکت image picker منصوب می کنید (آبجکتی که با همکاری و هماهنگی آن )، مانند نمونه ی قبلی، ViewController است.  

اما پیش از هر چیزی، ViewController می بایست protocol نام برده (UIImagePickerControllerDelegate) را پیاده سازی کند. از آنجایی که ViewController وظیفه ی ارائه ی image picker controller را نیز بر عهده دارد، ناگزیر می بایست پروتکل UINavigationControllerDelegate را هم پیاده سازی کند. این protocol برخی از مسئولیت های پیمایش (navigation) را به view controller واگذار می کند.     

به منظور افزودن protocol های نام برده به ViewController، مراحل زیر را دنبال نمایید:

1.      با کلیک بر روی دکمه ی Standard در سمت چپ نوار ابزار Xcode، ویرایشگر اصلی محیط (standard editor) را باز کنید.

clip_image045

حال project navigator و utility area را با کلیک بر روی دکمه های مربوطه ی آن ها (اشاره شده در تصویر فوق) باز نمایید.

2.      از کادر project navigator، فایل ViewController.swift را انتخاب نمایید.

3.      داخل فایل ViewController.swift، خط حامل تعریف کلاس را پیدا کنید:

class ViewController: UIViewController, UITextFieldDelegate {

4.      بعد از UITextFieldDelegate، یک ویرگول اضافه کرده و سپس UINavigationControllerDelegate را درج کنید.

class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate {

5.      اکنون پس از UIImagePickerControllerDelegate، یک ویرگول اضافه کرده و سپس UINavigationControllerDelegate را تایپ کنید. با این کار کلاس ViewController را ملزم به پیاده سازی متدهای تعریف شده در این دو protocol می کنید:

class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

پس از اضافه کردن این دو protocol به خط تعریف کلاس، می توانید به تکمیل پیاده سازی متد selectImageFromPhotoLibrary(_:) بپردازید.

جهت پیاده سازی متد selectImageFromPhotoLibrary(_:)، مراحل زیر را دنبال کنید:

1.      در فایل ViewController.swift، متد selectImageFromPhotoLibrary(_:) را پیدا کنید. بایستی ظاهری مشابه زیر داشته باشد:

@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {

}

در بدنه ی متد، بین ({}) کد زیر را اضافه کنید:

// Hide the keyboard.

nameTextField.resignFirstResponder()

این کد سبب می شود اگر کاربر حین نمایان بودن صفحه کلید در نمایشگر، بر روی المان image view کلیک کرد، صفحه کلید به طور کامل از صفحه حذف شود.

2.      حال کد زیر را جهت ایجاد یک image picker controller، به بدنه ی متد اضافه نمایید:

// UIImagePickerController is a view controller that lets a user pick media from their photo library.

let imagePickerController = UIImagePickerController()

3.      سپس کد زیر را به بدنه ی متد اضافه کنید:

// Only allow photos to be picked, not taken.

imagePickerController.sourceType = .PhotoLibrary

این خط کد، محلی که image picker controller فایل های تصویری خود را از آن وارد المان می کند را مشخص می نماید. پارامتر .PhotoLibrary به image picker اعلان می کند که باید عکس های خود را فقط از مجموعه تصاویر محیط شبیه ساز (simulator camera roll) وارد کند. می دانیم که imagePickerController.sourceType از جنس UIImagePickerControllerSourceType است که نوع داده ای آن enumeration می باشد. بنابراین می توانید بجای اینکه مقدار را به طور کامل UIImagePickerControllerSourceType.PhotoLibrary تایپ کنید، آن را به صورت مختصر .PhotoLibrary مورد اشاره قرار دهید. یادآور می شویم که هرگاه نوع مقدار enumeration از قبل مشخص است، می توانید از صورت مختصر آن استفاده نمایید.    

4.      با افزودن کد زیر، کلاس حاضر (ViewController) را به عنوان delegate کنترلرimage picker  انتخاب نمایید:

// Make sure ViewController is notified when the user picks an image.

imagePickerController.delegate = self

5.      حال این کد را در زیر کد فوق، به بدنه ی متد اضافه کنید:

presentViewController(imagePickerController, animated: true, completion: nil)

presentViewController(_:animated:completion:) یک متد است که در سطح کلاس ViewController فراخوانی می شود. اگرچه این متد صریحا به آبجکت self الحاق نشده، اما از شرایط جاری مشخص است که بر روی آن فراخوانی می شود. متد مذکور به کلاس ViewController اعلان می کند که باید view controller را نمایش دهد.

ارسال مقدار true به پارامتر animated، سبب می شود image picker controller به صورت پویا (با انیمیشن) ارائه شود.پارامتر completion به یک completion handler اشاره دارد. Completion handler یک تابع closure است که با اتمام اجرای متد جاری، صدا زده می شود. از آنجایی که پس از اجرای کامل متد، نیاز به انجام عملیات دیگری نیست، مقدار nil را به این پارامتر پاس می دهیم.

در حال حاضر بدنه ی متدselectImageFromPhotoLibrary(_:) بایستی مشابه نمونه ی زیر باشد:

@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {

// Hide the keyboard.

nameTextField.resignFirstResponder()

// UIImagePickerController is a view controller that lets a user pick media from their photo library.

let imagePickerController = UIImagePickerController()

// Only allow photos to be picked, not taken.

imagePickerController.sourceType = .PhotoLibrary

// Make sure ViewController is notified when the user picks an image.

imagePickerController.delegate = self

presentViewController(imagePickerController, animated: true, completion: nil)

}

پس از اینکه image picker controller به نمایش گذاشته شد، رفتارش (عملیاتی که قادر به اجرای آن ها است) به آبجکت delegate محول می شود.

برای این که به کاربران این امکان را بدهید تا پس از کلیک بر روی المان، یک عکس را انتخاب کنند، لازم است دو متد زیر از پروتکل UIImagePickerControllerDelegate را پیاده سازی نمایید:   

func imagePickerControllerDidCancel(picker: UIImagePickerController)

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])

متد اول، imagePickerControllerDidCancel(_:)، زمانی صدا خورده می شود که کاربر بر روی دکمه ی Cancel از image picker کلیک می کند. این متد در واقع به شما اجازه می دهد تا UIImagePickerController را از صفحه حذف/محو کنید (و در صورت تمایل، کدی اضافه کنید که عملیات cleanup و پاک سازی داده های غیرضروری از حافظه را انجام می دهد).

جهت پیاده سازی متد imagePickerControllerDidCancel(_:)، مراحل زیر را به ترتیب دنبال نمایید:

1.      داخل فایل ViewController.swift، درست در بالای // MARK: Actions ، خط زیر را درج نمایید:

1.       // MARK: UIImagePickerControllerDelegate

این کد صرفا یک comment است که شما یا هر شخص دیگری که کد برنامه ی شما را می خواند را در پیمایش در پروژه و فهم کاربرد بخش های مختلف آن یاری می کند. این comment اعلان می کند که این بخش از کد مربوط به پیاده سازی متدهای image picker می باشد.

2.      حال در زیر comment، متد زیر را وارد نمایید:

func imagePickerControllerDidCancel(picker: UIImagePickerController) {

}

3.      داخل بدنه ی متد دستور زیر را تایپ کنید:

// Dismiss the picker if the user canceled.

dismissViewControllerAnimated(true, completion: nil)

این کد، فرایند حذف شدن image picker controller از نمایشگر را پویانمایی می کند (با انیمیشن آن را نظر کاربر پنهان می کند).

بدنه ی متد imagePickerControllerDidCancel(_:) هم اکنون بایستی مشابه نمونه ی زیر باشد:

func imagePickerControllerDidCancel(picker: UIImagePickerController) {

// Dismiss the picker if the user canceled.

dismissViewControllerAnimated(true, completion: nil)

}

دومین متدی که باید از پروتکل UIImagePickerControllerDelegate پیاده سازی کنید، imagePickerController(_:didFinishPickingMediaWithInfo:) می باشد. این متد زمانی فرخوانی می شود که کاربر عکس دلخواه خود را انتخاب می نماید.

با اجرا شدن متد نام برده، این فرصت در اختیار شما قرار می گیرد تا بر روی عکس یا عکس هایی که کاربر انتخاب کرده، عملیات مورد نظر را انجام دهید. در مثال جاری، شما عکس مورد انتخاب کاربر را گرفته و در UI به نمایش می گذارید.  

جهت پیاده سازی متد imagePickerController(_:didFinishPickingMediaWithInfo:)، مراحل زیر را به ترتیب دنبال نمایید:

1.      در زیر متد imagePickerControllerDidCancel(_:)، این کد را درج نمایید:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

}

2.      در بدنه ی متد، کد زیر را وارد نمایید:

// The info dictionary contains multiple representations of the image, and this uses the original.

let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage

info در کد فوق، یک dictionary است که علاوه بر عکس اولیه و انتخاب شده در image picker، نسخه ی ویرایش شده ی آن را نیز دربر می گیرد. در اینجا از نسخه ی ساده و ویرایش نشده ی عکس برای غذای مورد نظر استفاده می کنیم. کد حاضر نیز همین عکس (نسخه ی ویرایش نشده) را داخل ثابت selectedImage ذخیره می کند.

3.      این کد را به بدنه ی متد اضافه کنید تا عکس مورد نظر در متغیر photoImageView (یک outlet که قبلا به فایل اضافه کردید) قرار داده شده و برای کاربر به نمایش درآید.

// Set photoImageView to display the selected image.

photoImageView.image = selectedImage

4.      حال با افزودن کد زیر به متد، image picker را از حالت نمایش خارج کنید:

// Dismiss the picker.

dismissViewControllerAnimated(true, completion: nil)

در حال حاضر بدنه ی متد imagePickerController(_:didFinishPickingMediaWithInfo) شما بایستی مشابه زیر باشد: 

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

// The info dictionary contains multiple representations of the image, and this uses the original.

let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage

// Set photoImageView to display the selected image.

photoImageView.image = selectedImage

// Dismiss the picker.

dismissViewControllerAnimated(true, completion: nil)

}

تست کنید: برنامه را اجرا کنید. بایستی پس از کلیک بر روی image view، یک image picker به نمایش درآمده و به شما اجازه ی انتخاب عکس دلخواه را بدهد. برای اینکه برنامه FoodTracker بتواند به بخش Photos دسترسی داشته و به کاربر اجازه ی انتخاب عکس را بدهد، باید بر روی دکمه ی OK در کادر محاوره ای کلیک نمایید. پس از آن، با توجه به کدی که برای برنامه نوشته شده، باید بتوانید با کلیک بر روی Cancel، انتخابگر عکس (image picker) را ببندید یا Camera Roll را باز کرده، عکس دلخواه را از آن انتخاب نمایید و متعاقبا در image view به نمایش بگذارید.

clip_image047

اگر به عکس های موجود در محیط شبیه ساز (Simulator) نگاه کنید، متوجه می شوید که عکسی در رابطه با غذا در آن وجود ندارد. می توانید عکس های مد نظر خود را مستقیما وارد محیط شبیه ساز نموده و در image view نمایش دهید یا پس از دانلود پروژه ی این آموزش، به پوشه ی Images/ مراجعه نموده و از عکس نمونه ی داخل این فولدر استفاده کنید.  

جهت افزودن عکس جدید به شبیه ساز، مراحل زیر را دنبال نمایید:

1.      ابتدا برنامه را در محیط شبیه ساز اجرا کنید.

2.      عکس دلخواه را انتخاب نمایید.

3.      عکس مورد نظر را با اشاره گر موس کشیده و در محیط شبیه ساز جایگذاری کنید.

connect to ui

متصل کردن UI (ظاهر یا رابط کاربری برنامه) به کد (رفتارها و عملیاتی که برنامه انجام می دهد)

در این مبحث، شما UI ساده ی اپلیکیشن FoodTracker (یا ثبت و رصد اطلاعات غذا) را به کد برنامه متصل می نمایید. با استفاده از این کد امکان انجام عملیات خاصی بر روی UI را برای کاربر برنامه ی خود فراهم می کنید.

در پایان برنامه ظاهری مشابه زیر خواهد داشت:

 

 

clip_image002[6]

آنچه خواهید آموخت

·         رابطه ی بین یک scene در storyboard و view controller زیرین آن را درک کرده و توضیح دهید.

·         با استفاده از outlet و action بین المان های UI در سطح storyboard و کد برنامه (source code) ارتباط برقرار کنید.

·         ورودی کاربر از یک کادر متن یا text field را خوانده، پردازش کنید و سپس خروجی آن را در UI اپلیکیشن به نمایش بگذارید.

·         یک کلاس را بر اساس protocol خاص پیاده سازی کنید (property ها و متدهای تعیین شده توسط آن protocol را در کلاس پیاده سازی کنید).

·         با الگوی توسعه ی delegation آشنا شوید.

·         در طراحی معماری اپلیکیشن از الگوی توسعه ی target-action پیروی نمایید (الگوی توسعه ی target-action را در معماری اپلیکیشن پیاده سازی کنید).

متصل کردن UI به کد برنامه (Source Code)

المان هایی که در storyboard مشاهده می کنید، در واقع هر یک به بخشی از source code وصل است. شما باید این رابطه ی بین storyboard با کد برنامه را به خوبی درک کنید.  

در Storyboard، یک scene نشانگر صفحه ای از صفحات متعدد برنامه است که بخشی از محتوای برنامه و عموما یک view controller را شامل می شود. view controller ها رفتار (متدهای) اپلیکیشن شما را پیاده سازی می کنند.    

view controller تنها یکview  content و view های زیرمجموعه ی آن را اداره می کند (content view = view دربرگیرنده ی تمامی view ها یا آبجکت های یک scene همچون button، text field و label).

View controller ها: 1. تعاملات/گردش اطلاعات بین data model برنامه (بخشی که داده های اپلیکیشن را کپسوله سازی می کند) و view ها را (بخش هایی که داده های برنامه را برای کاربر به نمایش می گذارد) مدیریت می کند 2. چرخه ی حیات content view های برنامه (view ای که در بالای سلسله مراتب قرار گرفته و نقش ظرف را برای view های فرزند خود همچون button، label ایفا می کند) را از ابتدا تا انتها مدیریت می نماید 3. تغییرات در جهت نمایش برنامه را به هنگام چرخش دستگاه اداره می کند 4. قابلیت پیمایش در برنامه را تعریف کرده  5. و در پایان رفتاری که به ورودی کاربر واکنش نشان می دهد را پیاده سازی می نماید.

تمامی آّبجکت های view controller در IOS، از جنس کلاس UIViewController یا یکی از کلاس های فرزند آن هستند.

رفتار view controller ها را بایستی در کد با ایجاد و پیاده سازی subclass های اختصاصی از view controller (کلاس های فرزند view controller با پیاده سازی اختصاصی خود)، تعریف نمایید. سپس می توانید یک اتصال بین کلاس های مذکور و scene ها در storyboard ایجاد کرده و در نهایت برنامه ای داشته باشید که رفتار تعریف شده در کد (کلاس های view controller) را همراه با UI مورد نظر در storyboard، ارائه می دهد. 

Xcode قبلا چنین کلاسی را با نام ViewController.swift ایجاد کرده و آن را به scene جاری که هم اکنون در storyboard با آن کار می کنید، متصل کرده است. در آینده، همین که scene های بیشتری را به برنامه اضافه می کنید، این اتصال بین scene و view controller را خود از طریق Identity inspector برقرار می نمایید.

Identity inspector این امکان را به شما می دهد تا آن دسته از property های یک آبجکت را که با identity آن مرتبط هستند، مانند اینکه به کدام کلاس تعلق دارد، ویرایش نمایید.

clip_image004[6]

در زمان اجرای برنامه (runtime)، storyboard نمونه ای از کلاس ViewController می سازد (همان subclass اختصاصی view controller). صفحه ای از برنامه را که در storyboard می بینید، رابط کاربری و ظاهر خود را از scene جاری گرفته، و رفتارهایش، عملیاتی که می تواند انجام دهد، را از کدهای فایل ViewController.swift دریافت می کند.

اگرچه scene مورد نظر به کدهای فایل ViewController.swift متصل است، اما این اتصال به تنهایی برای داشتن تعامل بین بخش های مختلف برنامه کافی نیست. برای تعریف تعامل در برنامه ی خود، کد view controller بایستی بتواند با view های موجود در storyboard (آبجکت های text field، label) تبادل اطلاعات داشته باشد. این کار را با ایجاد connection های بیشتر – که outlet و action خوانده می شوند – بین view ها در storyboard و فایل های view controller انجام می دهید.

تعریف Outlet برای المان های UI

Outlet روشی تعریف می کند که می توان به وسیله ی آن به آبجکت های رابط کاربری – آبجکت هایی نظیر label، button که به storyboard اضافه شده – از کد فایل های source code اشاره کرد (دسترسی داشت).

برای ایجاد outlet، کافی است از آبجکت مورد نظر در storyboard، به فایلview controller ، control-drag کنید. بدین معنی که با کلیک بر روی آن آبجکت، نگه داشتن کلید control و کشیدن آن به فایل view controller، یک اشاره گر از آن آبجکت در فایل view controller ایجاد نمایید.

این عملیات یک (متغیر) property برای آبجکت مورد نظر در فایل view controller ایجاد می کند و به شما اجازه می دهد در زمان اجرا از کد به آن آبجکت دسترسی داشته و آن را دستکاری کنید.   

با توجه به آنچه گفته شد، جهت دسترسی یا اشاره به label و text field در لایه ی رابط کاربری، باید برای آن ها در کد outlet تعریف نمایید. 

به منظور وصل کردن المان text field به کد فایل ViewController.swift:

1.      فایل Main.storyboard را باز کنید.

2.      Assistant editor را با کلیک بر روی دکمه ی Assistant، واقع در نوار ابزار Xcode، بالای محیط گوشه ی سمت راست، باز نمایید.

clip_image006[6]

3.      اگر به فضای کاری بیشتری نیاز دارید، می توانید project navigator و utility area را با کلیک بر روی دکمه های مربوطه در نوار ابزار Xcode پنهان نمایید (جمع کنید).

clip_image008[6]

در صورت لزوم می توانید outline view را نیز جمع کنید.

4.      در editor selector bar، در بالای assistant editor، این مسیر را طی کنید: Preview -> Automatic -> viewController.swift.

clip_image010[6]

محتویات فایل ViewController.swift در ویرایشگر سمت راست محیط به نمایش در می آید.

1.      در فایل ViewController.swift، خطی که کلیدواژه ی class را دارد، پیدا کنید:

class ViewController: UIViewController {

2.      در زیر کد ذکر شده، عبارت ذیل را درج کنید:

// MARK: Properties

با این کار در واقع یک comment (کد درج توضیحات) به source code خود اضافه می کنید. همان طور که قبلا گفته شد، comment یک تکه متن در فایل source code است که به هنگام کامپایل به عنوان بخشی از دستورات برنامه ترجمه و اجرا نمی شود، اما اطلاعات کاربردی در خصوص بخش های مختلف کد ارائه می دهد.

Comment ای که با کاراکترهای // MARK: آغاز می شود، یک نوع خاص comment است که بیشتر به منظور سازمان دهی کد و کمک در فهم کاربرد آن بخش مورد استفاده قرار می گیرد.

به عنوان نمونه، تکه کدی که شما به عنوان comment به فایل نام برده اضافه کردید، اعلان می کند که در آن بخش property های آبجکت لیست می شوند.  

1.      در storyboard، المان text field را انتخاب کنید.

2.      بر روی المان مذکور در canvas کلیک کرده، کلید control را نگه دارید، سپس آن را کشیده و در زیر بخش comment در assistant editor جایگذاری نمایید.

clip_image012[6]

3.      یک پنجره ی محاوره ای به نمایش در می آید. در فیلد Name، واژه ی nameTextField را وارد کنید.  

لازم نیست دیگر تنظیمات را تغییر دهید.

 

clip_image014[6]

4.      حال بر روی دکمه ی Connect کلیک نمایید. Xcode کد لازم را به فایل ViewController.swift، جهت ذخیره ی اشاره گری (pointer) به text field اضافه کرده و storyboard را برای برقراری اتصال مورد نیاز بین المان UI و کد تنظیم می کند. به عبارت واضح تر، Xcode یک اشاره گر (در قالب متغیر یا property) به المان UI مورد نظر، در فایل ViewController.swift اضافه کرده و سپس storyboard را جهت برقراری ارتباط بین المان مورد نظر در لایه ی رابط کاربری با کد مربوطه ی آن در فایل مزبور تنظیم می کند.  

@IBOutlet weak var nameTextField: UITextField!

مدت زمانی را به فهم این خط کد اختصاص دهید.

خصیصه (attribute) IBOutlet این امکان را برای شما فراهم می کند تا در محیط Xcode از interface builder به متغیر (property) nameTextField وصل شوید (پیشوند IB نیز به همین امکان اشاره دارد). کلیدواژه ی weak بیانگر قابلیت nil بودن متغیر در طول عمر آن می باشد (بدین معنی که property مذکور می تواند در برهه ای از زمان هیچ مقداری نداشته باشد). در بقیه ی (تعریف) کد صرفا یک متغیر از نوع (کلاس) UITextField، به نام nameTextField ایجاد می شود.  

به علامت تعجب "!" در انتهای تعریف outlet دقت کنید. اگر بخاطر داشته باشید، برخی از property ها در فایل AppDelegate.swift این علامت را در انتهای خود دارند. علامت مزبور نشانگر این است که متغیر یا property مورد نظر از نوع implicitly unwrapped optional است. implicitly unwrapped optional، یک متغیر از جنس optional است که پس از مقداردهی اولیه همیشه حاوی مقدار خواهد بود (optional متغیری که می تواند مقداری داشته/نداشته باشد).

حال label را مانند المان قبلی (text field) به کد مربوطه ی آن در فایل ViewController.swift متصل کنید.  

برای وصل کردن المان label به کد مربوطه در فایل ViewController.swift:

1.      Label را در storyboard انتخاب نمایید.

2.      بر روی المان مذکور در canvas کلیک کرده و کلید Control را نگه دارید، سپس آن را کشیده و در assistant editor، زیر متغیر nameTextField جایگذاری کنید. 

clip_image016[6]

3.      در کادر محاوره ای که نمایان می شود، در فیلد Name، واژه ی mealNameLabel را به عنوان اسم المان وارد نمایید. لازم نیست تنظیمات دیگری انجام دهید.

clip_image018[6]

4.      بر روی Connect کلیک نمایید.

Xcode یک اشاره گر (pointer) در قالب متغیر  به المان Label در فایل ViewController.swift اضافه کرده، سپس storyboard را جهت برقراری ارتباط بین المان UI مورد نظر و کد مربوطه ی آن در فایل مذکور، تنظیم می کند. این outlet به استثنای دو ویژگی نوع و اسم، کاملا مشابه المان قبلی است (outlet جاری از نوع کلاس UILabel است که با نوع آبجکت در storyboard کاملا همخوانی دارد).  

1. @IBOutlet weak var mealNameLabel: UILabel!

حالا که روشی برای اشاره و دسترسی به المان های UI از داخل کد (در فایل ViewController.swift) دارید، باید یک رخداد که توسط کاربر فعال می شود و زمینه ی تعامل میان این دو المان را فراهم می کند، تعریف نمایید. برای تعریف این رخداد در IOS از action بهره می گیریم. 

 

تعریف یک رخداد با استفاده از Action

اپلیکیشن های IOS رخداد محور هستند (بر اساس الگوی برنامه نویسی رخداد محور/event-driven طراحی می شوند). بدین معنی که روند اجرای (flow) برنامه توسط event ها: رخدادهای سیستم و action های کاربر (کلیک موس یا فشردن کلیدهای کیبورد یا دکمه ای بر روی صفحه) تعیین می گردد.

 کاربر با UI برنامه تعامل برقرار کرده ، برای مثال یک دکمه را کلیک می کند، در پی این عمل/action کاربر رخداد خاصی اتفاق می افتد. این رخدادها خود سبب اجرای منطق برنامه و تغییر در داده های آن می شود. سپس واکنش برنامه به عمل کاربر و اثر آن، در UI برنامه منعکس می شود.

همان طور که می دانید در برنامه های رویداد محور، کنترل اجرای بخش هایی از برنامه به دست کاربر است. بدین معنی که زمانی که کاربر با UI برنامه تعامل می کند، بخش های مختلف از کد برنامه در پاسخ به عمل کاربر اجرا می شود. حال از آنجایی که کاربر، نه شما، کنترل اینکه چه زمانی بخش هایی از کد برنامه اجرا شوند را در دست دارد، شما به عنوان برنامه نویس بایستی مشخص کنید کاربر دقیقا اجازه ی انجام چه عملیاتی را دارد و در پاسخ به آن اعمال دقیقا چه واکنشی بایستی نشان داده شود (چه اتفاقی رخ دهد).

Action (یا action method) یک تکه کد است که به event یا رخدادی در برنامه وصل بوده و با اتفاق افتادن آن event فراخوانی و اجرا می شود. به عبارتی دیگر زمانی که آن event رخ می دهد، متعاقبا کد یا دستور مرتبط با آن اجرا می گردد.

می توانید با تعریف action، عملیات دلخواه را پیاده سازی کنید. حال این عملیات می تواند دستکاری داده های مشخص، بروز رسانی بخشی از UI و یا هر عملیات دیگری باشد. در واقع شما با استفاده از action جریان یا روند اجرای برنامه را در پاسخ به رخدادهای فعال شده توسط کاربر و سیستم تعیین می کنید.     

تعریف action و outlet به یک نحو صورت می گیرد: کافی است بر روی آبجکت مورد نظر کلیک کرده، کلید control را نگه دارید. سپس آن را کشیده و داخل فایل view controller جایگذاری نمایید. به دنبال آن یک متد در فایل view controller تعریف می شود که به مجرد تعامل کاربر با آبجکت متصل (به آن متد)، فراخوانده و اجرا می گردد.

 

کار را با ایجاد یک action ساده آغاز نمایید: زمانی که کاربر در UI برنامه، دکمه ی Set Default Label Text را فشار می دهد، شما باید label را طوری تنظیم کرده باشید که (به مجرد فشرده شدن دکمه) مقدار پیش فرض Default Text را نمایش دهد. (در بخش بعدی label را طوری تنظیم می کنیم که مقدار وارد شده در text field را عینا نمایش دهد.)

جهت ایجاد یک action برای بازگردانی مقدار label به Default Text در فایل ViewController.swift، مراحل زیر را گام به گام دنبال نمایید:

1.      در فایل ViewController.swift، به قبل از آخرین "}"، عبارت زیر را اضافه نمایید:

// MARK: Actions

comment فوق نشانگر این است که action های کد در این بخش قرار می گیرند.

2.      بر روی دکمه ی Set Default Label Text کلیک کرده، کلید control را نگه دارید. سپس المان مزبور را کشیده و داخل فایل ViewController.swift، در زیر comment درج شده (// MARK: Actions)، جایگذاری کنید.

clip_image020[6]

3.      در کادر محاوره ای که پدیدار می شود، در فیلد Connection گزینه ی Action را انتخاب نمایید.

4.      در فیلد Type، گزینه ی UIButton را انتخاب نمایید.

حتما متوجه شدید که مقدار فیلد Type به صورت پیش فرض بر روی AnyObject تنظیم می شود. در زبان Swift، AnyObject یک نوع است و برای توصیف آبجکتی که می تواند به هر کلاسی تعلق داشته باشد، بکار می رود. تنظیم نوع این action method بر روی مقدار UIButton، بیانگر این است که تنها آبجکت های از جنس کلاس UIButton می توانند به این متد یا action وصل شوند. کادر محاوره ای پس از وارد کردن مقادیر مورد نیاز در آن به صورت زیر خواهد بود:

clip_image022[6]

5.      اکنون بر روی دکمه ی Connect کلیک نمایید.

محیط Xcode خود تعریف و کد لازم برای action method را اضافه می کند.

@IBAction func setDefaultLabelText(sender: UIButton) {

}

در این کد، پارامتر sender به آبجکتی که action را صدا زده و اجرای آن را سبب می شود – در این سناریو همان آبجکت button – اشاره دارد. خصیصه (attribute) IBAction نشانگر این است که متد مورد نظر یک action بوده که می توان از storyboard در interface builder به آن وصل شد. بقیه ی کد صرفا یک متد متعارف به نام setDefaultLabelText(_:) را تعریف می کند.

در حال حاضر، تعریف متد هیچ پیاده سازی در بدنه ی خود ندارد. در زیر کدی به بدنه ی متد اضافه می کنیم که مقدار label را به یک مقدار پیش فرض برمی گرداند.

به منظور پیاده سازی action یا متدی که مقدار label را در فایل ViewController به Default Text برمی گرداند، مراحل زیر را طی نمایید:

1.      در فایل ViewController.swift، تعریف متد setDefaultLabelText را پیدا کنید. 

2.      داخل بدنه ی متد (بین {})، این خط کد را اضافه نمایید:

mealNameLabel.text = "Default Text"

همان طور که حدس می زنید، این کد مقدار text (که یکی از property های label است) را برابر Default Text قرار می دهد. اگر به کد دقت کنید، متوجه می شوید که نوع Default Text را صریحا مشخص نکردیم و نیازی هم به این کار نیست. چراکه زبان Swift قابلیتی به نام type inference (استنتاج نوع) دارد و با استفاده از آن می تواند درست حدس بزند که مقداری از نوع رشته را به آبجکتی از جنس کلاس NSString تخصیص می دهید.

هم اکنون کد action method شما باید به صورت زیر باشد:

@IBAction func setDefaultLabelText(sender: UIButton) {

mealNameLabel.text = "Default Text"

}

تست کنید: تغییراتی که تاکنون به کد اعمال کرده اید را با شبیه ساز (Simulator) تست نمایید. زمانی که بر روی دکمه ی Set Default Label Text کلیک می کنید، مقدار label بایستی از Meal Name (مقداری که در storyboard تنظیم کردید) به Default Text (مقداری که در بدنه ی متد یا action تعریف کردید) تغییر کند.

clip_image024[6]

رفتاری که با این مثال پیاده سازی کردید، مصداق و نمونه ای از پیاده سازی الگوی توسعه ی target-action در طراحی برنامه های IOS است. target-action یک الگوی توسعه یا design pattern است که در آن آبجکت مورد نظر، با اتفاق افتادن یا فعال شدن رخدادی معین، message یا پیغامی را به آبجکت دیگری ارسال می کند. در این سناریو، event کلیک کاربر بر روی دکمه ی Set Default Label Text است، action همان متد setDefaultLabelText است، target همان ViewController، جایی که متد در آن تعریف شده است و در پایان sender (ارسال کننده ی پیغام) دکمه ی Set Default Label Text است.

Message در واقع یک action method است که در source code تعریف شده و target –دریافت کننده ی پیغام – آن آبجکتی است که قادر به اجرای action یا عملیات تعریف شده توسط متد می باشد. آبجکتی که پیغام را ارسال می کند معمولا یک کنترل همچون button، slider یا switch است که در پاسخ به عمل کاربر (لمس صفحه ی نمایش، کشیدن یا تغییر مقدار) رخدادی را فعال می کند (به ورودی کاربر واکنش نشان داده و رخدادی را اجرا می کند).

همان طور که گفته شد این الگو به وفور در برنامه نویسی IOS پیاده سازی شده و شما نمونه های بیشتری از آن را در مباحث بعدی این سری آموزشی مشاهده خواهید کرد.   

پردازش ورودی کاربر (برابر قرار دادن مقدار label با مقدار وارد شده توسط کاربر در text field)

در حال حاضر، برنامه طوری تنظیم است که با کلیک بر روی دکمه، مقدار label را بر روی Default Text قرار می دهد. اکنون می خواهیم رفتاری برای برنامه تعریف کنیم که با کلیک بر روی دکمه ی آن، مقدار label را برابر مقدار وارد شده توسط کاربر در text field قرار دهد. 

در این بخش جهت ساده نگه داشتن برنامه، برای اعلان زمان بروز رسانی مقدار label، متکی به action کاربر که همان کلیک بر روی دکمه ی Return صفحه کلید است، خواهید بود.

برای پردازش و کار با ورودی کاربر از آبجکت text field، به یک delegate از آبجکت مزبور نیاز دارید. Delegate یک آبجکت است که به نمایندگی از یا با همکاری آبجکت دیگری کاری را انجام می دهد. آبجکتی که کاری را به آبجکت دیگر محول می کند (به آن اشاره می کند) یا با هماهنگی آن آبجکت کاری را انجام می دهد در اینجا delegating object نامیده می شود. آن آبجکتی که کاری از جانب delegating object به آن سپرده می شود، delegate خوانده می شود.

Delegating object (در این مثالtext field )، یک اشاره گر (reference) از آبجکت دیگر (delegate) نزد خود نگه داشته و در زمان مناسب، delegating object نام برده یک پیغام به delegate ارسال می کند. حال این پیغام به delegate درباره ی رخدادی خبر می دهد که delegating object در صدد مدیریت آن بوده و یا به تازگی مدیریت کرده است. در پی آن، delegate با بروز رسانی ظاهر/وضعیت خود، آبجکت دیگر در برنامه یا بازگردانی مقداری که تعیین می کند یک رخداد در حال وقوع چگونه اداره شود، به این دست رخدادها واکنش نشان می دهد.  

delegate این text field، زمانی که مقدار کنترل مورد نظر (text field) در حال ویرایش است، با آن تعامل داشته و کاملا اطلاع دارد چه زمانی رخدادهای مهم اتفاق می افتد – مانند اینکه کاربر چه زمانی ویرایش متن را آغاز و کی آن را متوقف می کند. delegate می تواند با استفاده از این اطلاعات، داده ها را در زمان مناسب ذخیره/حذف کند، صفحه کلید را ببندد و غیره ... .   

هر آبجکتی می تواند به عنوان delegate آبجکتی دیگری ایفای نقش کند مادام اینکه از الگو یا protocol مناسب پیروی نماید. Protocol یا الگویی که delegate کنترل field text را تعریف می کند، UITextFieldDelegate نام دارد (protocol = صرفا یک الگو و معرفی یک سری متد و property است. اگر برای آبجکت یا کلاسی protocol اعلان کنید، آن کلاس یا آبجکت ملزم به پیاده سازی متدها و property های تعیین شده توسط آن protocol می شود). در این مثال، از آنجایی که ViewController اشاره گر به آبجکت text field را نگهداری می کند، view controller را delegate آن text field انتخاب می کنیم.

ابتدا بایستی ViewController را بر اساس protocol یا الگوی UITextFieldDelegate تنظیم و پیاده سازی کنید. برای استفاده از protocol خاص،