به نام خدا

شاید توی کار با سویفت انواع متغییر ها رو دیده باشید منظورم از انواع به معنی نوع متغییر که دابل و استرینگ باشه نیست

کد زیر یک متغییر استرینگ که دارای setter و getter  هست رو نشون میده

var name : String? {
        set {
            validationNameAndSave(newValue)
        }
        get {
            return getSavedName()
        }
    }

فکر میکنم کار کد بالا روشن هست

وقت متغییر name رو برابر مقدار جدیدی قرار میدید در حقیقت متعییر مقدارداده نمیشه بلکه مقدارش برای یه تابع ارسال میشه و اونجا تابع میتونه دخیره کنه یا هرکار دیگه ای و هرموقع هم مقدار متغییر رو بخواید متغییر مقدارش رو از تابع getSavedName میگیره و به شما میده یعنی عملا این یه متغییر معمولی نیست یعنی ممکنه توی یه خط مقدار بهش بدید و خط بعدیش مقداری که ازش میخونید با مقداری که خط بالا بهش داده باشید فرق داشته باشه

 

تعریف کردن متغییر های فقط خواندنی  ReadOnly

هر موقع که شما set اون متغییر رو حذف کنید متغییر شما فقط خواندنی میشه و دیگه نمیتونید بهش مقدار بدید

البته سویفت برای راحتی کار به شما این امکان رو داده که دیگه کلمه کلیدیget روهم ننویسید به این شکل

 var name : String? {
        return getSavedName()
    }

 

خب فکر میکنم شده باشه که یه وقتایی میخوایم یه مقداری رو وقتی یه بار یه متغییر صدا زده میشه همون موقع مقدار داده بشه و دفعات بعد از همون استفاده کنه

بزارید یه مثال بزنم مثلا فرض کنید که توکنی که قرار هست توی هر رکوئست روی هدر درخواستتون ست شده باشه رو میخواید از توی UserDefult بخونید و دفعات بعد دیگه به userDefult دست نزنید

اگه قبلا کار کرده باشید قطعا حل این مسئله براتون به این شکله که یه جا اول برنامه متغییری رو مقدار میدید و دفعات بعد ازش استفاده میکنید ولی خب میخواید این توکن رو استاتیک بزارید تا توی همه کلاس ها قابل دسترس باشه بازم همون راه جواب میده اما ممکنه یه بار قرار باشه اون کد اول برنامه اجرا نشه به هردلیل و همه جای برنامه توکن ما نال میشه

بهترین کار اینه که هرکسی از هرجایی اولین بار صداش زد مقدار بگیره و دفعات بعد همون مقدار رو به ما برگردونه که این کار با تعریف یه تابع استاتیک که شرط نال بودن و نبودن توکن رو چک میکنه و اگه نال بود توش مقدار میریزه و برگرمیگردونه و اگرم مقدار داشت که مقدار رو برمیگیردونه قابل انجامه

اما کار راحت تر توی سویفت اینه که متغییرتون رو میتونید شبیه به همین تابع تعریف کنید یعنی بار اول بدنه تابع اجرا میشه و دفعات دیگه مقدارش فقط برگشته میشه 

حالا چجوری میتونیم اینجور توابعی رو تعریف کنیم؟

var token : String? = {
       //Do Any This
        return foo;
    }()

فقط یه محدودیتی داره اونم اینه که نمیتونید توش از متغییر های داخل کلاستون استفاده کنید مگر اینکه اونا رو استاتیک تعریف کنید.

متغیر های تنبل یا Lazy Variable:

ممکنه گاهی لازم بشه یه متغییر بنویسید که توش از self استفاده کنید (مثلا متغیری که توش یه closure رو نوشته باشید) اگه بخواید در چنین حالتی از self استفاده کنید نمیشه و باید از lazy استفاده کنید این کلمه کلیدی کاری میکنه که متغییر شما تا قبل از اینکه خودتون کال کنید اجرا نشه بخاطر همین فرصت برای مقدار دهی و صدا زدن init کلاس و متغییر های دیگه پیش میاد و بعد از اون وقتی شما متغیر تنبل خودتون رو کال کنید حتما self نیز وجود داره.

 

انگلیسیم ضعیفه ولی فکر کنم بشه فهمید منظورم چی بوده تا الان هرچی بلدم ایناست دیگه:

    var myVar = ""
//    this only is a getter (other word is a variable readonly)
//    did't run the block untill you call
    var mycode : String  {
        return "salam"
    }
//    First store the new value and then call didSet, you can access the previous value by calling 'oldvalue'
//    did't run the block untill you call
    var mycode1 : String = " salam" {
        didSet {
            oldValue //the previous value
            mycode1 //the new value of variable
            mycode
        }
    }
    
//  This is like two function : 1.getMyCode2(return -> string) 2.SetMyCode2(mycode2: string) and can't store any value
//  below variable always get "salam" and when you set mycode2="hello" run this line 'myVar = "hello"'
//    did't run the block untill you call
    var mycode2 : String {
        get{
            return "salam"
        }
        set {
            myVar = newValue
        }
    }
//    block of this variable run immediatly (bedofre calling 'init'), the block will be run and in next times, only return the final result of block
//    run the block before 'init' the class
    var myCode3 : String = {
        //Compute...
        //you can't call myVar here, because in this closure, the code run immediatly (and may 'self' is not completed yet)
        return "salam"
    }()
    
//    block run when you call 'myCode4', and after, everytime you call this, the same result returned
//    did't run the block untill you call
    lazy var myCode4 : String = {
        //Compute...
        //you <b>can<b> call myVar
        return myVar
    }()
    
//    closure run when you call 'myCode5()'
//    every time that you call this, the closure will be ran
//    this is called like exact a function
//    when you use 'self' in it, you create a strong refrence
//    closure are bypass value like class
    var myCode5: () -> String = {
        return "salam"
    }
    
//    defrence with above variable only is you can use 'self' in it
    lazy var myCode6: () -> String? = { [weak self] in
        return self?.myVar
    }