برنامه نویسی Kotlin — مقدمه‌ای بر برنامه‌نویسی اندروید با زبان کاتلین

۴۶۰ بازدید
آخرین به‌روزرسانی: ۲۵ اردیبهشت ۱۴۰۲
زمان مطالعه: ۱۰ دقیقه
برنامه نویسی Kotlin — مقدمه‌ای بر برنامه‌نویسی اندروید با زبان کاتلین

در هنگام ساخت اپلیکیشنهای بومی (Native Applications) برای سیستم‌عامل اندروید (Android)، معمولاً برای اعمال عملیات و تعاریف دلخواه، از زبان برنامه‌نویسی جاوا (Java) استفاده می‌شود. در حالی که، زبان جاوا بسیار دشوار است و مشکلات مربوط به خود را دارد.

هنگامی که شما یک اپلیکیشن جاوا را اجرا می‌کنید، آن اپلیکیشن به مجموعه‌ای از فرمان‌ها، به نام بایت‌کد (Bytecode) کامپایل (Compile) شده و در یک ماشین مجازی اجرا می‌شود. در طی چند سال اخیر، زبان‌های برنامه‌نویسی جدیدی برای اجرا در ماشین مجازی جاوا (Java Virtual Machine - JVM) معرفی شده‌اند. در حالی که، ظاهر اپلیکیشن‌های ساخته‌شده توسط این زبان‌های جدید برای ماشین مجازی یکسان است، هدف اصلی از معرفی این زبان‌ها، ارائه ویژگی‌های مفید در کدنویسی راحت‌تر برای توسعه‌دهندگان و برطرف کردن مشکلات جاوا است.

شرکت توسعه نرم‌افزاری (JetBrains)، سازنده استودیوی توسعه اندروید (IntelliJ IDEA)، زبان برنامه‌نویسی کاتلین (Kotlin) را معرفی کرده است. کاتلین، یک زبان برنامه‌نویسی ایستا است که در JVM اجرا می‌شود و قابلیت کامپایل شدن به سورس‌کد جاوا اسکریپت (JavaScript Source Code) را نیز دارد. این زبان، چندین ویژگی جذاب را در خود جای داده است. در این مقاله، مطالب زیر را در مورد کاتلین خواهید آموخت:

  • نحوه تنظیم محیط کاتلین
  • نحوه به کارگیری هم‌زمان با جاوا و کاتلین در یک پروژه
  • دلایل جذابیت زبان برنامه‌نویسی جدید کاتلین

در این مقاله فرض می‌شود که شما تجربه‌ای در زمینه توسعه اندروید دارید. اگر تازه وارد دنیای برنامه‌نویسی اندروید شده‌اید؛ سؤالات زیادی در مورد شروع پروژه دارید؛ یا هیچ آشنایی با اندروید استودیو (Android Studio) ندارید، بهتر است در ابتدا با مقدمات برنامه‌نویسی اندروید آشنا شوید.

چرا از زبان کاتلین برای اندروید استفاده کنیم؟

اندروید، دنیای اپلیکیشن‌ها را تصاحب کرده است و به همین دلیل، توسعه‌دهندگان هیچ راه دیگری برای توسعه اپلیکیشن جاوا نداشته‌اند. با اینکه استفاده از جاوا بسیار گسترده است، این زبان دارای یک سری مشکلات تاریخی است. جاوا 8، برخی از مشکلات این زبان را حل کرد و جاوا 10 نیز ایرادات بیشتری را تصحیح کرد.

به منظور بهره بردن از مزایای اصلاحات صورت گرفته برای این دو نسخه از جاوا، باید حداقل کیت توسعه نرم‌افزاری (minimum SDK) را بر روی اندروید 24 نصب کرده تا فقط بتوانید از جاوا 8 استفاده کنید. این کار، برای توسعه‌دهندگان انتخابی نیست و تقریباً هیچ‌کسی جاوا 10 را مد نظر قرار نمی‌دهد.

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

  1. مختصر و در عین حال جامع بودن. این ویژگی باعث کاهش نوشتن کدهای تکراری برای شما می‌شود.
  2. رسا بودن. این ویژگی، خوانایی و قابل فهم بودن کدهای شما را بیشتر می‌کند.
  3. ایمن بودن. این ویژگی باعث اجتناب از تمامی کلاس‌های خطا مانند خطای رایج «Null Pointer» می‌شود.
  4. چندمنظوره بودن. این ویژگی، امکان ساخت اپلیکیشن‌های سمت سرور، اپلیکیشن‌های اندرویدی یا اجرای کد سمت کاربر در مرورگر را فراهم می‌کند.
  5. سازگار بودن. این ویژگی، قابلیت به کارگیری از کتابخانه‌ها و فریم‌ورک‌های موجود در ماشین مجازی جاوا به همراه 100 درصد سازگاری با زبان جاوا را فراهم می‌کند.
  6. به‌روز بودن. مهم‌تر از همه‌ی این ویژگی‌ها، کاتلین یک زبان جدید است و همین موضوع، یادگیری آن را هیجان‌انگیز می‌کند.

شروع کار با کاتلین

شما می‌توانید فایل پروژه شروع کار را از «لینک پروژه» دریافت کنید. در ابتدا، باید این فایل را از حالت فشرده خارج کرده و آن را در اندروید استودیو باز کنید. در این پروژه، شما قرار است به منظور یادگیری کاتلین، با یک اپلیکیشن ساده در زمینه جستجوی کتاب، مشاهده جلد کتاب و به اشتراک‌گذاری کتاب با دوستان کار کنید. این اپلیکیشن دارای سه فایل سورس کد است:

  • MainActivity.java: این فایل، یک فعالیت (Activity) است که برای جستجو و نشان دادن فهرست کتاب‌ها، صفحه را به نمایش درمی‌آورد.
  • DeatailActivity.java: این فایل، یک فعالیت (Activity) است که با توجه به ID واردشده کتاب، جلد آن را به نمایش درمی‌آورد.
  • JSONAdapter.java: این فایل، یک کلاس سفارشی (BaseAdapter) است که یک شیء JSON را به یک فهرست نتایج تبدیل می‌کند.

پروژه را ایجاد کرده و آن را اجرا کنید تا ببینید که با چه محیطی قرار است کار کنید.

اندروید استودیو، به صورت پیش‌فرض هیچ آگاهی از نحوه کار با کاتلین ندارد. به همین دلیل، در قدم اول باید افزونه کاتلین را در اندروید استودیو نصب کرده و پیکربندی (Configure) آن را در پروژه خود انجام دهید.

نصب افزونه کاتلین

به بخش (Android Studio) در منوی نواری بالای صفحه رفته و (Preference) را انتخاب کنید.

در سمت چپ پنجره بازشده، گزینه «Plugins» را انتخاب کرده و مطابق شکل زیر، بر روی «Install JetBrains plugin» کلیک کنید.

در قسمت جستجو، عبارت «Kotlin» را وارد کرده و سپس از انتخاب افزونه کاتلین، بر روی «Install» کلیک کنید.

هنگامی که دانلود و نصب افزونه پایان یافت، باید محیط ویرایشگر کد «IDE» را مجدداً راه‌اندازی (Restart) کنید.

پیکربندی کاتلین در پروژه

با انجام مراحل بالا، IDE برای کار با کاتلین آماده می‌شود اما پروژه شما هنوز برای این کار آماده نیست.

از این‌رو، باید پیکربندی ساخت پروژه را تغییر داد. برای این کار، به مسیر روبرو بروید: ToolsKotlinConfigure Kotlin in Project

در پنجره بازشده «Choose Configurator»، گزینه «Android with Gradle» را انتخاب کنید.

در پنجره بعدی «Configure Kotlin in Project»، بر نسخه مورد نیاز افزونه خود را انتخاب کرده و بر روی «OK» کلیک کنید.

این کار، تغییراتی را بر روی فایل‌های «build.grade» شما اعمال می‌کند. در ادامه، کدهای مربوط به ساخت فایل‌های bulid.gradle آورده شده است.

build.gradle برای پروژه «omg-android-starter»

buildscript {
  ext.kotlin_version = '1.0.3' // 1
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.1.3'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // 2

    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
  }
}

allprojects {
  repositories {
    jcenter()
  }
}

build.gradle برای ماژول «OMG Android»

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' // 3

android {
    compileSdkVersion 23
    buildToolsVersion "24.0.2"

    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 23
    }
  sourceSets {
    main.java.srcDirs += 'src/main/kotlin' // 4
  }
}

dependencies {
  compile 'com.android.support:appcompat-v7:23.2.0'
  compile 'com.loopj.android:android-async-http:1.4.4'
  compile 'com.squareup.picasso:picasso:2.1.1'
  compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" // 5
}
repositories {
  mavenCentral()
}

بیایید عملکرد کدهای بالا را قدم‌به‌قدم بررسی کنیم:

  1. در ابتدا، نسخه کاتلین پیکربندی‌شده در پروژه را اعلام می‌کند.
  2. یک «classpath dependency artifact» یا محصول وابستگی کلاس classpath که شامل افزونه «Kotlin Gradle» و نسخه اعلام‌شده است را مشخص می‌کند.
  3. کاربرد افزونه «Kotlin Android» را به وسیله دستور «apply plugin» مشخص می‌کند.
  4. تعیین می‌کند که فایل‌های سورس موجود در آدرس «src/main/kotlin»، کامپایل خواهند شد. در واقع، gradle فایل‌های سورس کاتلین موجود در آدرس src/main/java را کامپایل می‌کند اما بهتر است که فایل‌های کاتلین در مسیر کاتلین قرار داشته باشند.
  5. در انتها، کتابخانه استاندارد کاتلین را به عنوان یک وابستگی زمانی کامپایل (compile time dependency) به پروژه اضافه کرده است.

حال برای ساخت پروژه، بر روی «Sync Now» کلیک کنید. پروژه را بسازید و آن را اجرا کنید.

از نظر ظاهری هیچ‌چیز تغییری نکرده است اما با انجام این مراحل، شما امکان پشتیبانی از کاتلین در پروژه‌ی اندرویدی خود را به وجود آورده‌اید.

نحوه به کارگیری هم‌زمان با جاوا و کاتلین در یک پروژه

یکی از ویژگی‌های شگفت‌انگیز کاتلین، توانایی آن در امکان کار کردن هم‌زمان با جاوا بر روی یک پروژه است. کدهای جاوا از کاتلین قابل فراخوانی هستند و بالعکس. یعنی شما قادر خواهید بود که کلاس «DetailActivity» را به کاتلین برگردانید. بر روی بسته «com.example.omgandroid» در پنل پروژه (نوار سمت چپ) کلیک کنید.

بسته مذکور را انتخاب کرده و به مسیر «FileNewKotlin File/Class» بروید تا یک کلاس جدید کاتلین ایجاد شود. توجه داشته باشید که بدون انتخاب بسته مذکور، شما قادر به دیدن گزینه «Kotlin File/Class» نخواهید بود.

در پنجره بازشده «New Kotlin File/Class»، گزینه «Class» را در بخش «Kind» انتخاب کرده و نام «DetailActivityKotlin» را برای کلاس خود انتخاب کنید. در انتها، بر روی دکمه «OK» کلیک کنید.

ظاهر کلاس جدید شما باید مانند کد زیر باشد:

    
    package com.example.omgandroid

    class DetailActivityKotlin {
    }

در ادامه یک سری نکته قابل ذکر آورده شده است:

  1. ممکن است متوجه شده باشید که در کد بالا، کلاس‌های کاتلین با استفاده از کلیدواژه «class» تعریف می‌شوند (مشابه جاوا).
  2. تعیین‌کننده پیش‌فرض وضعیت مشاهده در کاتلین، «public» است.
  3. کلاس‌ها و متدها در کاتلین، به صورت پیش‌فرض نهایی (final) هستند و امکان تغییر آن‌ها پس از تعریف وجود ندارد. اگر قصد دارید کلاسی را توسعه دهید، باید از کلیدواژه «open» استفاده کنید.

از آنجایی که کاتلین قابلیت سازگاری با جاوا را داراست، شما می‌توانید از فریم‌ورک‌ها (Framework) و کتابخانه‌های موجود در جاوا برای فایل‌های کد کاتلین استفاده کنید. در مرحله اول، شما باید دستورات زیر را در قسمت بالای فایل وارد کنید:

  import android.app.Activity
  import android.os.Bundle

سپس، کلاس را به یک زیرکلاس «Activity» تبدیل کنید.

class Main2Activity : Activity() {

}

توجه داشته باشید که انجام این کار در کاتلین کمی با جاوا متفاوت است. در کاتلین، شما تابع «()NameOfParentClass» را به تعریف زیرکلاس اضافه می‌کنید. حال متد «()onCreate» متعلق به Activity را بازفراخوانی کنید. کد شما چیزی شبیه به کد زیر خواهد شد:

import android.app.Activity
import android.os.Bundle

class DetailActivityKotlin: Activity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  }
}

توجه: شما می‌توانید برای عملکرد ایجاد کد در اندروید استودیو به منظور ساخت متد onCreate، از کلیدهای ترکیبی «Control + O» استفاده کنید. بعد از فشردن این کلیدهای ترکیبی، پنجره‌ای حاوی تمام متدهای قابل بازفراخوانی برای کلاس مدنظر شما باز خواهد شد.

«MainActivity.java» را باز کرده و مرجع «DetailActivity» را در «()onItemClick» با «DetailActivityKotlin» جایگزین کنید. به این ترتیب، خط ایجاد شیء «Intent» شما باید از شکل زیر:

Intent detailIntent = new Intent(this, DetailActivity.class);

به شکل زیر تغییر کند:

Intent detailIntent = new Intent(this, DetailActivityKotlin.class);

مانند کار با Activity در جاوا، شما باید Activity خود در کاتلین را درون یک فایل «AndroidMainfest.xml» تعریف کنید. کد زیر را در قسمت پایین تعریف DetailActivity اضافه کنید:

   <activity
        android:name=".DetailActivityKotlin"
        android:label="@string/activity_details_kotlin"
        android:parentActivityName=".MainActivity">
      <meta-data
          android:name="android.support.PARENT_ACTIVITY"
          android:value=".MainActivity"/>
    </activity>

فایل خود را ساخته و آن را اجرا کنید. از درون فهرست، یک کتاب را انتخاب کرده تا بتوانید صفحه خالی با عنوان «Kotlin Book Details» را مشاهده کنید.

کاتلین بسیار جذاب است

قبل از اینکه وارد ویژگی‌های بیشتر کاتلین شوید، به فایل «DetailActivityKotlin.kt» برگردید و محتوای آن را با کد زیر جایگزین کنید:

 
package com.example.omgandroid

import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.widget.ImageView
import android.widget.ShareActionProvider
import com.squareup.picasso.Picasso

class DetailActivityKotlin: Activity() {

  private val IMAGE_URL_BASE = "http://covers.openlibrary.org/b/id/"
  internal var mImageURL = ""
  internal var mShareActionProvider: ShareActionProvider? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_detail)

    actionBar?.setDisplayHomeAsUpEnabled(true)

    val imageView = findViewById(R.id.img_cover) as ImageView

    val coverId = this.intent.extras.getString("coverID")

    val len = coverId?.length ?: 0

    if (len > 0) {
      mImageURL = IMAGE_URL_BASE + coverId + "-L.jpg"
      Picasso.with(this).load(mImageURL).placeholder(R.drawable.img_books_loading).into(imageView)
    }
  }

  private fun setShareIntent() {

    val shareIntent = Intent(Intent.ACTION_SEND)
    shareIntent.type = "text/plain"
    shareIntent.putExtra(Intent.EXTRA_SUBJECT, "Book Recommendation!")
    shareIntent.putExtra(Intent.EXTRA_TEXT, mImageURL)

    mShareActionProvider?.setShareIntent(shareIntent)
  }

  override fun onCreateOptionsMenu(menu: Menu): Boolean {

    menuInflater.inflate(R.menu.main, menu)

    val shareItem = menu.findItem(R.id.menu_item_share)

    mShareActionProvider = shareItem!!.actionProvider as ShareActionProvider

    setShareIntent()

    return true
  }
}

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

 

ویژگی Null-Safe

یکی از نکات آزاردهنده در بیشتر زبان‌های برنامه‌نویسی (مانند جاوا)، دسترسی یک عضو به یک مرجع نال (Null Reference) است. هنگامی که شما یک متغیر شیء تعریف کرده اما مقداری به آن اختصاص نداده باشید، اخطار مرجع تهی رخ می‌دهد.

زمانی که برنامه اجرا می‌شود و سعی دارد به آن متغیر دسترسی پیدا کند، برنامه نمی‌داند که باید در کجای حافظه به دنبال آن باشد (چراکه آن متغیر اصلاً وجود ندارد). این مسئله، اغلب باعث توقف ناگهانی و کرش کردن برنامه شما می‌شود. در این حالت، اخطاری مانند «NullPointerException» ظاهر می‌شود.

یکی از بهترین ویژگی‌های کاتلین این است که سیستم نوع (Type System) در آن، به دنبال حذف NullPointerException است (هدفی که با عنوان Void-Safety شناخته می‌شود). در کاتلین، تنها دلایل ممکن برای NullPointerException، موارد زیر هستند:

  • ایجاد شدن آن توسط کدهای خارجی جاوا
  • فراخوانی NullPointerException توسط برنامه‌نویس
  • استفاده از عملگر «!!» (در ادامه به طور مختصر به آن پرداخته می‌شود)
  • وجود ناسازگاری در داده‌ها با توجه به مقداردهی اولیه

انواع Nullable و Non-Null

کاتلین دارای انواع Nullable (نال‌پذیر) و Non-Null (غیر نال) است. اگر شما متغیری را به عنوان Nullable تعریف نکنید، نمی‌توانید به آن مقدار نال یا تهی اختصاص دهید. کامپایلر شما را وادار به رعایت این مسئله می‌کند تا از هرگونه کرش ناخواسته در برنامه جلوگیری شود. در کاتلین و برخلاف جاوا، تمام متغیرها باید در هنگام تعریف، مقداردهی اولیه شوند. برای تعریف یک متغیر به عنوان متغیر Nullable، یک «?» باید در هنگام تعریف به انتهای آن اضافه کنید؛ مانند مثال زیر:

internal var mShareActionProvider: ShareActionProvider? = null

ویژگی فراخوانی ایمن

در جاوا، برای دسترسی به یک خصوصیت یا متد در یک متغیر Nullable، باید در ابتدا بررسی نال بودن را انجام دهید. شما می‌توانید این مسئله را در کد زیر (مربوط به DetailActivity.java) مشاهده کنید:

if (mShareActionProvider != null) {
  mShareActionProvider.setShareIntent(shareIntent)
}

در کاتلین، می‌توانید عبارت بالا را با استفاده از عملگر فراخوانی ایمن (?) ساده کنید. به این صورت، خصوصیت و متد مدنظر شما، تنها زمانی فراخوانی می‌شود که متغیر Nullable، نال نباشد.

mShareActionProvider?.setShareIntent(shareIntent)

در کد بالا، «setShareIntent» زمانی فراخوانی می‌شود که خصوصیت «mShareActionProvider» نال نباشد.

عملگر "!!"

همان‌طور که بخش‌های قبلی به آن اشاره شد، یکی از دلایل ایجاد اخطار NullPointerException، این عملگر است. اگر یقین دارید که شیء شما نال نیست، می‌توانید برای «Dereference» کردن یا اشاره کردن به آن شیء، با خیال راحت از عملگر !! استفاده کنید.

شما می‌توانید مثال این نکته را در ()setShareIntent ببینید:

mShareActionProvider = shareItem!!.actionProvider as ShareActionProvider

در اینجا، اگر متغیر «shareItem»، نال نباشد، «actionProvider» بازگشت داده می‌شود. در غیر این صورت، اخطار NullPointerException نشان داده خواهد شد.

عملگر Elvis

ظاهر عملگر Elvis (:?)، مشابه عملگر سه‌تایی if در جاوا است اما کاربرد متفاوتی دارد. شما می‌توانید در ادامه، مثالی از این عملگر در هنگام اقدام برای به دست آوردن طول شناسه جلد (Cover ID) را مشاهده کنید:

val len = coverId?.length ?: 0

اگر عبارت سمت چپ عملگر Elvis غیر نال باشد، نتیجه عبارت بازگردانی می‌شود. در غیر این صورت، نتیجه عبارت سمت راست بازگردانی می‌شود. دقیقاً مانند عبارت «if-else»، عملگر Elvis تنها زمانی عبارت سمت راست را بررسی می‌کند که عبارت سمت چپ نال باشد.

استنتاج نوع داده

کاتلین از استنتاج نوع داده (Type Inference) نیز پشتیبانی می‌کند؛ یعنی کامپایلر می‌تواند پس تعریف و مقداردهی متغیر، نوع خود را از طریق مقداردهنده اولیه تعیین کند. برای مثال، نوع متغیرهای «IMAGE_URL_BASE» و «mImageURL» از روی مقداردهنده اولیه‌شان گرفته شده است.

private val IMAGE_URL_BASE = "http://covers.openlibrary.org/b/id/"
internal var mImageURL = ""

کامپایلر، نوع به‌دست‌آمده هر یک از متغیرها را دنبال کرده (در اینجا هر دو متغیر String هستند) و مقادیر اختصاصی بعدی به آن متغیرها را بر اساس نوع به‌دست‌آمده (در اینجا String) تعیین می‌کند.

جذاب‌ترین ویژگی کاتلین (تبدیل جاوا به کاتلین)

شاید بعد از خواند این مقاله، بخواهید کدهای جاوای خود را به کاتلین تبدیل کنید. نیازی به نگرانی نیست چراکه افزونه Kotlin، این کار را برایتان انجام می‌دهد. از آنجایی که کاتلین زبانی ساخته‌شده توسط توسعه‌دهندگان برای توسعه‌دهندگان بوده، طراحی آن در جهت تسهیل کار برنامه‌نویسی است. افزونه Kotlin، دارای ابزاری راحت برای تبدیل فایل سورس جاوا به کاتلین است.

بیایید برای امتحان کردن این ویژگی، فایل «DetailActivity.java» را به کاتلین تبدیل کنیم. کلاس DetailActivity.java را باز کرده و به مسیر زیر بروید:

«CodeConvert Java File to Kotlin File»

بر روی «OK» در صفحه «Convert Java to Kotlin» کلیک کنید. با این کار، فایل جاوای شما با یک فایل کاتلین جایگزین خواهد شد.

به همین سادگی، شما یک کلاس جاوا را به کلاس کاتلین تبدیل کردید.

سخن آخر

تبریک می‌گوییم. با خواندن این مقاله، شما مبانی زبان برنامه‌نویسی کاتلین و برخی از ویژگی‌های فوق‌العاده آن، کدنویسی دوباره یک فعالیت جاوا در کاتلین و تبدیل یک کد جاوا به کد کاتلین با استفاده از افزونه Kotlin را آموختید. شما می‌توانید فایل نهایی این آموزش را از طریق «لینک فایل نهایی» دریافت کنید. علاوه بر این، امکان امتحان کردن نمونه کدها و یادگیری بیشتر این زبان در کامپایلر آنلاین کاتلین فراهم شده است. مطالبی که در این مقاله ارائه شد، تنها یک بخش کوچک از ویژگی‌های جذاب و فوق‌العاده کاتلین است. امیدواریم از خواندن این مقاله «برنامه‌نویسی اندروید با زبان کاتلین» لذت برده باشید. با ارسال نظرات خود، ما را در بهبود کیفیت مطالب یاری کنید.

#

بر اساس رای ۶ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
raywenderlich
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *