objc.io

ساخت وبلاگ

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

00:06 در این قسمت ، ما می خواهیم بر اساس نوع آینده ای که در یک قسمت قبلی اجرا کردیم ، بسازیم. به طور خاص ، ما از نوع آینده به عنوان پایه ای برای ایجاد یک اجرای واکنش پذیر ساده استفاده خواهیم کرد. در حالی که آینده یک انتزاع در اطراف یک تماس یک طرفه است ، سیگنال در یک کتابخانه واکنشی با گذشت زمان مقادیر می کند.

00:38 اگر تماس فقط یک نتیجه را ارائه می دهد ، به عنوان مثال ، از آینده ای در یک API ناهمزمان استفاده می کنید. بیشتر تماس های شبکه یا محاسبات گران قیمت. در مقابل ، اگر مجبورید چندین مقادیر را با گذشت زمان انجام دهید ، مانند یک دکمه که می تواند چندین بار بر روی آن ضربه بزند ، یا برای یک قسمت متنی که مقدار آن را با هر ورودی کاربر جدید تغییر می دهد ، از یک سیگنال استفاده کنید. در مورد سیگنال ، ما باید در مورد برخی از موضوعات اضافی ، مانند مدیریت حافظه (برای جلوگیری از چرخه مرجع) و مدیریت اشتراک (برای اجازه دادن به مشتری ها از دریافت مقادیر یک سیگنال خاص استفاده کنیم) فکر کنیم.

01:17 انگیزه نوشتن یک کتابخانه واکنش پذیر کوچک از ابتدا ، درک مفهوم برنامه نویسی واکنشی در سطح عمیق تر است. هدف ما نوشتن کد آماده تولید نیست ، بلکه بیشتر این است که سر خود را در اطراف صحنه در هنگام استفاده از یکی از کتابخانه های واکنشی موجود بپیچیم.

تبدیل آینده به سیگنال

01:53 ما از قسمت شماره 36 با نوع آینده شروع می کنیم:

01:55 به عنوان اولین قدم ، ما ذخیره نتیجه را حذف می کنیم ، زیرا این حداقل برای یک سیگنال معنی ندارد ، حداقل در این شکل. ما همچنین اولیه را حذف می کنیم ، نوع را از آینده به سیگنال تغییر نام دهید ، هم اکنون ارسال کنید و به اشتراک گذاری تغییر نام دهید. سرانجام ، ما در پایان روش ارسال ، تماس های تماس تلفنی را پاک نمی کنیم ، زیرا اکنون می خواهیم بتوانیم مقادیر مختلفی را ارسال کنیم. این کد را کاملاً ساده می کند:

03:31 اکنون می توانیم سیگنال را امتحان کنیم:

04:30 اجرای سیگنال اکنون بسیار ساده است ، اما همچنین بسیار محدود است. پس از ساختن این نوع بیشتر ، باید پیچیدگی های بیشتری را به آن اضافه کنیم.

جدا کردن API ارسال/مشترک شدن

04:49 اولین پیشرفتی که ما می کنیم جدا کردن API سیگنال در یک قسمت ارسال کننده و یک قسمت دریافت کننده است. این یک الگوی بسیار متداول در کتابخانه های واکنشی است ، زیرا به شما امکان می دهد کنترل کنید چه کسی می تواند مقادیر جدیدی را به سیگنال در مقابل کسی که فقط مجاز به عضویت در آن هستند ، ارسال کند.

05:22 برای این کار ما یک روش استاتیک ، لوله ، به سیگنال اضافه می کنیم ، که این دو چیز را برمی گرداند: تابعی که می توانیم مقادیر جدیدی را ارسال کنیم و خود سیگنال که فقط خواندنی است. شما می توانید نام این روش را کاملاً به معنای واقعی کلمه در نظر بگیرید: Tuple برگشتی را می توان به عنوان یک لوله فیزیکی با دو انتها تصور کرد. در یک انتها می توانید مقادیر جدیدی را وارد کنید (که به آن "سینک" نیز گفته می شود) ، و در انتهای دیگر می توانید آنچه را که بیرون می آید مشاهده کنید:

06:43 با روش لوله در محل ، ما توانستیم دوباره ارسال خصوصی کنیم. امکان ارسال مقادیر جدید اکنون فقط از طریق روش لوله در معرض دید قرار می گیرد.

07:06 برای امتحان کردن این تغییرات ، ما فقط باید کد تست خود را کمی تغییر دهیم:

اضافه کردن سیگنال به یک قسمت متن

07:30 بیایید همه این کد را در یک زمینه واقع بینانه تر قرار دهیم. برای این منظور ، ما قصد داریم یک کنترلر نمایش را در زمین بازی خود جعلی کنیم و در ViewDidload در سیگنال یک قسمت متن مشترک شویم:

09:05 برای کار کردن این کد ، باید روش سیگنال را به صورت برنامه افزودنی به NSTextField اضافه کنیم. در این روش ، ما می توانیم از جداسازی ارسال/مشترک که در بالا ایجاد کرده ایم استفاده کنیم - قسمت متن قادر به ارسال مقادیر جدید به سیگنال است ، در حالی که هر کد دیگری فقط می تواند مشاهده کند:

10:23 در این رویکرد ، ما نمی خواهیم قسمت متن به سیگنال مراجعه کند ، بلکه سیگنال باید قسمت متن را ارجاع دهد (از طریق ناظر ارزش کلید). این مزیت آن را دارد که انعطاف پذیرتر است ، زیرا ما باید قسمت متن را زیر طبقه بندی کنیم یا از اشیاء مرتبط استفاده کنیم تا مرجع سیگنال را در خود قسمت متن ذخیره کنیم.

12:09 کلاس KeyValueObserver یک بسته بندی ساده در اطراف KVO است که هر بار که ویژگی مشاهده شده تغییر می کند ، یک عملکرد را فراخوانی می کند. همچنین طول عمر مشاهده را مدیریت می کند: هنگامی که نمونه ناظر با ارزش کلیدی از بین برود ، مشاهده قسمت متن را متوقف می کند. تا زمانی که ناظر ارزش کلیدی زنده باشد ، شیء مشاهده شده نیز در اطراف آن تضمین می شود ، زیرا نمونه ناظر یک مرجع قوی به شیء مشاهده شده است.

12:39 از آنجا که ما هنوز به عنوان نمونه KeyValueObserver ادامه نداده ایم ، بلافاصله دچار دیوانگی می شود و مشاهده متوقف می شود. ساده ترین راه برای رفع این مسئله فقط ذخیره ناظر در خاصیت سیگنال است. فعلاً این اشیاء خاصیت را می نامیم:

15:16 اکنون ناظر تا زمانی که سیگنال زنده باشد زنده خواهد بود. از آنجا که سیگنال در یک ویژگی از کنترلر View ذخیره می شود ، مقادیر جدید تا زمانی که کنترل کننده View در اطراف باشد ارسال می شود.

برخورد با چرخه های مرجع

15:33 متأسفانه ، ما به طور تصادفی یک چرخه مرجع را معرفی کردیم ، که باعث می شود سیگنال هرگز مورد بحث قرار گیرد.

15:46 چرخه مرجع گاهی اوقات اشکال زدایی دشوار است ، زیرا بسیاری از اشیاء می توانند در ایجاد چرخه نقش داشته باشند. یک تکنیک بسیار ساده برای کمک به تشخیص این چرخه ها ، اضافه کردن یک بیانیه چاپ به یک deinit کلاس است. به عنوان مثال ، ما می توانیم این کار را با کلاس کنترل کننده نمایش خود امتحان کنیم:

هنگامی که متغیر VC را روی NIL تنظیم کردیم ، کنترلر مشاهده می شود و "حذف VC" در کنسول چاپ می شود.

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

اشکال زدایی حافظه Xcode

16:57 یکی از ابزارهای بسیار مفید برای تشخیص بیشتر مشکل ، اشکال زدایی حافظه Xcode است. از آنجا که این در یک زمین بازی کار نمی کند ، ما فقط کد خود را در یک پروژه خط فرمان کپی و چسبانده و به کار خود ادامه خواهیم داد.

17:21 اکنون بعد از تنظیم متغیر VC روی NIL و اجرای پروژه ، یک نقطه شکست را تعیین کردیم. هنگامی که اشکال زدایی در این خط متوقف شد ، می توانیم اشکال زدایی حافظه را باز کنیم:

The reference cycle in Xcode

17:40 در نوار کناری همه اشیاء زنده را می بینیم ، به عنوان مثالنمونه سیگنال که دیگر نباید در آن باشد. در سمت راست ، ما تمام اشیاء درگیر در چرخه مرجع را که سیگنال را زنده نگه می دارد ، می بینیم: سیگنال به ناظر ارزش کلیدی از طریق خاصیت اشیاء خود اشاره می کند ، و ناظر ارزش کلیدی از طریق چند واسطه دیگر به سیگنال اشاره می کندمراحل

18:16 این تجسم می تواند در تشخیص مشکل بسیار مفید باشد. با این حال ، گاهی اوقات اشکال زدایی حافظه قادر به تولید نمودار مانند این نیست ، اما هنوز هم اشیاء زنده در نوار کناری را نشان می دهد.

طراحی چرخه های مرجع

19:04 یکی دیگر از رویکردهای مفید این است که منابع همه اشیاء را روی یک تکه کاغذ ترسیم کنید. ما این کار را بسیار انجام می دهیم تا درک کنیم که چگونه یک چرخه مرجع ایجاد کرده ایم. در مثال در دست ، نمودار به این شکل است:

Sketching out object references

19:10 در گوشه بالا سمت چپ ما کنترلر View را داریم که به شدت به قسمت متن و سیگنال رشته اشاره می کند (همانطور که توسط فلش ها نشان داده شده است). سیگنال String به بسته شدن با عبارت چاپ و همچنین ناظر ارزش کلیدی که برای مشاهده قسمت متن برای تغییرات استفاده می کند ، اشاره می کند. ناظر ارزش کلیدی به نوبه خود مرجع قوی به قسمت متن است.

19:40 این ممکن است در حال حاضر مانند یک چرخه مرجع به نظر برسد وقتی به قسمت سمت چپ نمودار نگاه می کنید (مشاهده کنترل کننده-سیگنال رشته-ناظر با ارزش کلید-زمینه متن-کنترل کننده مشاهده). با این حال ، همه منابع در همان جهت نشان نمی دهند ، بنابراین ما هنوز مشکلی نداریم.

19:55 ناظر با ارزش کلیدی همچنین به بسته شدن که هنگام تغییر خاصیت مشاهده شده فراخوانی می شود ، اشاره می کند. در مورد ما ، این تابعی است که مقادیر جدید را به داخل سینک تغذیه می کند. به نوبه خود ، سینک به شدت به سیگنال اشاره می کند ، زیرا سینک فقط روش ارسال سیگنال است. بنابراین در اینجا چرخه مرجع ما وجود دارد.

رفع چرخه مرجع

20:14 برای رفع چرخه ، ما باید در مورد اینکه کدام یک از منابع می تواند یک مرجع ضعیف باشد فکر کنیم. به عنوان مثال ، ما نمی توانیم از سیگنال به ناظر ضعیف باشیم ، زیرا ناظر دیگر به هیچ وجه به شدت ارجاع نمی شود. همین مسئله در مورد تعطیلی که توسط Observer ارجاع شده است نیز می شود. بنابراین ، ما می خواهیم با ایجاد مرجع از بسته شدن به سیگنال ، چرخه را بشکنیم:

The object graph with the reference cycle fixed

20:40 برای این کار ، ما باید اجرای روش لوله سیگنال را اصلاح کنیم. به جای بازگشت به سیگنال. send ، ما قصد داریم این را در بسته بندی که سیگنال ضعیف را ضبط می کند ، بپیچیم:

21:50 با این تغییر جزئی ، چرخه مرجع ثابت است ، که می توانیم از چاپ در کنسول "حذف سیگنال" و همچنین در اشکال زدایی حافظه مشاهده کنیم.

22:31 در این حالت ، چرخه مرجع در اثر اشتباه در اجرای سیگنال ایجاد شده است. با این حال ، مواردی نیز وجود دارد که مسئولیت مصرف کننده API این است که چرخه ایجاد نکند. به عنوان مثال ، اگر قرار بود در بسته شدن به خود به خود مراجعه کنیم ، به تماس مشترک در ViewDidload منتقل می شویم ، می توانستیم یک چرخه مرجع بین کنترل کننده مشاهده و سیگنال ایجاد کنیم. برای جلوگیری از این امر ، ما باید در لیست ضبط بسته شدن ، خود یا خود را ضعیف مشخص کنیم.

23:27 با استفاده از این مشکل ، ما دفعه بعد عملکرد کمی بیشتر به نوع سیگنال خود اضافه خواهیم کرد!

فارکس را از کجا شروع کنیم...
ما را در سایت فارکس را از کجا شروع کنیم دنبال می کنید

برچسب : نویسنده : لیما اصغرپورسازونی بازدید : <-PostHit-> تاريخ : جمعه 29 ارديبهشت 1402 ساعت: 13:46