Layer — انتزاعی از محتوای گرافیکی است که نمایش بصری عناصر رابط را در برنامههای موبایل مدیریت میکند. برخلاف UIView، layer رویدادهای لمسی را پردازش نمیکند و در Auto Layout شرکت نمیکند — وظیفه آن منحصراً رندرینگ، انیمیشن و ترکیب پیکسلها است. طبق Apple QuartzCore Documentation, 2025، هر UIView در iOS یک CALayer مرتبط دارد که در واقع ترسیم و انیمیشن را مدیریت میکند. درک ساختار لایهها به توسعهدهنده امکان میدهد عملکرد رندرینگ را در سطح پیکسلهای جداگانه کنترل کند.
نکات اصلی
Layer — یک شیء سطح پایین از سیستم گرافیکی است که تصویر شطرنجی بخشی از صفحه را ذخیره میکند و ویژگیهای بصری آن: موقعیت، اندازه، چرخش، شفافیت، سایه و رنگ را مدیریت میکند. در iOS هر UIView دارای CALayer داخلی است که از طریق ویژگی layer قابل دسترسی است. توسعهدهنده میتواند مستقیماً با layer کار کند و UIView را برای تنظیم دقیق رندرینگ دور بزند.
معماری لایهها از الگوی Model-View-Controller پیروی میکند، جایی که CALayer نقش Model را دارد — وضعیت ویژگیهای بصری را ذخیره میکند. Core Animation Controller است که انیمیشن انتقال بین حالتها را مدیریت میکند. View (UIView) — یک پوشش اختیاری است که پردازش لمس و مشارکت در Auto Layout را اضافه میکند.
طبق Apple WWDC 2024، pipeline رندرینگ مدرن iOS از Metal برای ترکیب لایهها استفاده میکند. هر CALayer در یک بافر جداگانه ترسیم میشود، پس از آن Core Animation همه بافرها را با در نظر گرفتن شفافیت و حالتهای ترکیب در تصویر نهایی ادغام میکند.
در Android معادل لایهها View و Drawableهای پسزمینه هستند، اما کار مستقیم با لایههای گرافیکی از طریق Canvas و RenderNode در Android 10+ در دسترس است. درک مفهوم layer برای بهینهسازی رندرینگ در هر دو پلتفرم مهم است.
تفاوت اصلی در حوزه مسئولیت است. View مسئول ورودی کاربر (لمس، حرکات)، موقعیتیابی (Auto Layout, frame) و چرخه حیات است. Layer منحصراً مسئول نمایش بصری است: رندرینگ محتوا، انیمیشن ویژگیها و ترکیب با سایر لایهها.
این جداسازی امکان کش کردن نمایش شطرنجی لایه را مستقل از View فراهم میکند. اگر لایه تغییر نکند، Core Animation از فریم کش شده استفاده میکند و drawRect را فراخوانی نمیکند. برای عناصر ایستا این افزایش عملکرد قابل توجهی بدون تغییر کد ایجاد میکند.
iOS سلسلهمراتب غنی از کلاسهای مشتق شده از CALayer ارائه میدهد. هر زیرکلاس برای سناریوی خاصی بهینه شده است: نمایش متن، گرافیک برداری، گرادیانها یا تبدیلهای سه بعدی. انتخاب نوع صحیح لایه مستقیماً بر عملکرد رندرینگ تأثیر میگذارد.
در Android مفهوم لایهها از طریق RenderNode، ViewLayer و HardwareRenderer پیادهسازی شده است. از Android 5.0 (API 21) به بعد، هر View در لایه شتاب سختافزاری خود رندر میشود که امکان انجام انیمیشنها بدون فراخوانی onDraw را فراهم میکند.
انعطافپذیری اضافی در iOS توسط CAReplicatorLayer و CAEmitterLayer فراهم میشود. اولی برای ایجاد الگوهای تکراری و دومی برای سیستمهای ذرات استفاده میشود. هر دو منحصراً روی GPU کار میکنند که امکان ایجاد جلوههای بصری پیچیده بدون افت عملکرد را فراهم میکند.
سلسلهمراتب لایهها در iOS بر اساس اصل درخت ساخته میشود: هر CALayer میتواند شامل چندین sublayer فرزند باشد. همه تبدیلهای اعمال شده به لایه والد — مقیاس، چرخش، جابجایی — به طور خودکار به عناصر فرزند اعمال میشوند. این امر ثبات نمایش بصری را در طول انیمیشنها تضمین میکند.
ترکیب صحنه توسط Core Animation به ترتیب زیر انجام میشود: ابتدا پسزمینه (background) رندر میشود، سپس هر لایه فرزند به ترتیب افزودن از پایین به بالا. برای هر لایه Core Animation ویژگیهای شفافیت، ماسکها و حالتهای ترکیب را بررسی میکند، سپس ادغام (compositing) را در فریم نهایی انجام میدهد.
طبق Apple Documentation، ترکیب لایه با opaque = true و بدون کانال آلفا بدون گذرهای اضافی انجام میشود — GPU به سادگی پیکسلها را روی لایه قبلی کپی میکند. اگر لایه حاوی شفافیت باشد، GPU آلفا-بلندینگ انجام میدهد که نیازمند منابع محاسباتی اضافی است.
در Android ترکیب لایهها از طریق SurfaceFlinger انجام میشود — سرویس سیستمی که بافرها را از هر برنامه دریافت کرده و با در نظر گرفتن ترتیب z آنها را ادغام میکند. هر Window در Android یک Surface جداگانه است که میتواند شامل چندین لایه گرافیکی باشد.
CALayer.mask — ویژگیای که اعمال ماسکی با شکل دلخواه به لایه را امکانپذیر میکند. ماسک میتواند هر CALayer دیگری باشد — مثلاً CAShapeLayer با path دایرهای یا CAGradientLayer برای ایجاد انتقال نرم شفافیت. استفاده از ماسکها بار GPU را افزایش میدهد، زیرا نیازمند گذر رندرینگ اضافی برای محاسبه مقادیر آلفای هر پیکسل است.
برای برش ساده در مرزهای مستطیلی توصیه میشود از cornerRadius و masksToBounds استفاده کنید. برخلاف ماسکها از طریق ویژگی mask، cornerRadius در مرحله شطرنجیسازی به صورت سختافزاری پردازش میشود و نیازی به گذر اضافی ندارد.
shouldRasterize — ویژگی کلیدی CALayer برای بهینهسازی عملکرد. وقتی shouldRasterize روی true تنظیم شود، Core Animation لایه و همه sublayerهای آن را در یک بافر شطرنجی جداگانه (offscreen buffer) رندر میکند. در فریمهای بعدی به جای رندرینگ مجدد از تصویر شطرنجی کش شده استفاده میشود.
کش کردن برای لایههای ایستا یا به ندرت تغییرکننده مؤثر است: سایهها، گرادیانها، متن با گوشههای گرد. با این حال برای لایههای مکرراً بهروز شونده (انیمیشن، ویدئو، اسکرول) شطرنجیسازی ممکن است عملکرد را بدتر کند، زیرا هر فریم نیازمند بازتولید کش است.
طبق تحقیقات Objc.io، استفاده صحیح از shouldRasterize در iPad Pro زمان رندرینگ صفحه پیچیده را از 25 میلیثانیه به 8 میلیثانیه کاهش میدهد — بیش از سه برابر. شرط کلیدی: لایه نباید بیشتر از هر 3-5 فریم یک بار تغییر کند.
اولین نمونه پیکربندی ویژگیهای بصری پایه CALayer در Swift را نشان میدهد — گرد کردن گوشهها، سایه و حاشیه:
import UIKit
class StyledView: UIView {
override func awakeFromNib() {
super.awakeFromNib()
layer.cornerRadius = 12
layer.masksToBounds = false
layer.shadowColor = UIColor.darkGray.cgColor
layer.shadowOpacity = 0.3
layer.shadowOffset = CGSize(width: 0, height: 4)
layer.shadowRadius = 8
}
}
دومین نمونه — ایجاد انیمیشن لایه در Swift با استفاده از CABasicAnimation. ویژگی position بدون مشارکت UIView انیمیشن میشود:
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = NSValue(cgPoint: CGPoint(x: 0, y: 0))
animation.toValue = NSValue(cgPoint: CGPoint(x: 150, y: 300))
animation.duration = 1.0
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
targetLayer.add(animation, forKey: "moveAnimation")
سومین نمونه — کار با RenderNode در Kotlin روی Android. RenderNode — آنالوگ مستقیم CALayer است که امکان کار با لایههای گرافیکی در سطح Canvas را فراهم میکند:
import android.graphics.renderer.RenderNode
fun createLayer(): RenderNode {
val node = RenderNode("customLayer")
node.setPosition(0, 0, 300, 200)
node.setScaleX(1.5f)
node.setScaleY(1.5f)
val canvas = node.beginRecording()
canvas.drawColor(android.graphics.Color.BLUE)
node.endRecording()
return node
}
سوالات متداول
UIView — یک پوشش بر روی CALayer است که پردازش لمس و مشارکت در Auto Layout را اضافه میکند. Layer فقط به رندرینگ و انیمیشن میپردازد. کار مستقیم با CALayer امکانپذیر است، اما برای پردازش رویدادهای ورودی به UIView نیاز است.
shouldRasterize کش کردن لایه را در یک offscreen buffer جداگانه فعال میکند. برای عناصر ایستا یا به ندرت تغییرکننده با سایه یا ترکیب پیچیده استفاده کنید. برای لایههای مکرراً انیمیشن شده استفاده نکنید — بازتولید کش گرانتر از رندرینگ مستقیم خواهد بود.
ویژگی cornerRadius را برای گرد کردن گوشهها و masksToBounds = true را برای برش محتوا در مرزهای لایه تنظیم کنید. برای سایه masksToBounds باید false باشد، در غیر این صورت سایه بریده میشود — در این مورد از یک لایه جداگانه برای سایه استفاده کنید.
بله، RenderNode در Android 10+ عملکرد مشابهی ارائه میدهد: مدیریت موقعیت، مقیاس، چرخش و شفافیت در سطح لایه گرافیکی. Canvas و HardwareRenderer رندرینگ را از طریق GPU تضمین میکنند. با این حال از نظر معماری، Android View و لایه را به سختی iOS از هم جدا نمیکند.
سایه در CALayer از طریق shadowPath یا به طور خودکار بر اساس کانال آلفا محاسبه میشود. محاسبه خودکار نیازمند عبور از تمام پیکسلهای لایه است که هزینهبر است. یک shadowPath صریح — مستطیل یا UIBezierPath — مشخص کنید، این به GPU اجازه میدهد سایه را بدون بررسی محتوا محاسبه کند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید