Custom UIView, UIKit bileşeni UIView'in bir alt sınıfıdır ve geliştiricinin benzersiz görsel öğeler oluşturmak için yaşam döngüsü ve çizim yöntemlerini geçersiz kıldığı bir yapıdır. Standart UIView'ler (UIButton, UILabel, UIImageView) çoğu tipik senaryoyu kapsar, ancak standart olmayan grafikler, animasyon veya etkileşim gerektiğinde özel bir UIView oluşturmak esastır. Apple Documentation'a (2025) göre, özel UIView'ler, standart olmayan arayüz çözümlerine sahip App Store uygulamalarının %68'inde kullanılır. Bu yaklaşım, çizim, dokunma işleme ve görünüm içindeki öğelerin düzeni üzerinde tam kontrol sağlar.
Önemli Noktalar
Custom UIView, UIView'den miras alan, geliştiricinin özel görüntüleme ve etkileşim mantığı uygulamak için standart yöntemleri geçersiz kıldığı kullanıcı tanımlı bir sınıftır. UIKit birçok yerleşik bileşen içerir, ancak animasyonlu grafikler, özel anahtarlar, serbest el çizim tuvali, oyun öğeleri veya veri görselleştirme gibi tüm senaryoları kapsamaz ve özel uygulama gerektirir.
Apple, standart bileşenler gerekli işlevselliği sağlayamadığında veya aynı özel öğe uygulamanın birden çok yerinde kullanıldığında Custom UIView oluşturulmasını önerir. WWDC 2024'e göre, orta büyüklükteki bir projede özel görünümler tüm UIView'lerin ortalama %15-20'sini oluşturur.
Custom UIView, grafikler ve diyagramlar (Core Graphics ile çizgi ve şekil çizme), özel ilerleme göstergeleri, animasyonlu arka planlar, parmakla çizim öğeleri ve gerçek zamanlı veri görselleştirme oluşturmak için kullanılır. Bu durumların her birinde, geliştirici CGContext'e tam erişim elde eder ve herhangi bir geometriyi çizebilir.
Bir öğe standart UIKit bileşenlerinden (UIButton, UIImageView, UILabel) Auto Layout ve özellik yapılandırması kullanılarak birleştirilebiliyorsa, UIView alt sınıfı oluşturmak gereksizdir. Apple önce hazır görünümlerin kompozisyonunu denemeyi ve yalnızca işlevsellik yetersiz olduğunda özel çizime geçmeyi önerir.
Özel bir UIView oluşturmak, UIView'den miras alan bir sınıf bildirimi ve zorunlu başlatıcıların uygulanmasıyla başlar. Minimum uygulama, koddan oluşturmak için init(frame:) ve Storyboard veya XIB'den yüklemek için init(coder:) içerir.
import UIKit
class CircleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
private func setupView() {
backgroundColor = .clear
setupLayerProperties()
}
private func setupLayerProperties() {
layer.cornerRadius = bounds.width / 2
layer.masksToBounds = true
}
}
setupView() yönteminde ilk özellikler ayarlanır: şeffaf arka plan, katman ayarları. Görünüm Interface Builder'da görüntülenecekse, canlı önizleme için @IBDesignable ve @IBInspectable eklemeye değer.
Custom UIView, belirli bir sırayla çağrılan bir dizi yaşam döngüsü yöntemi aracılığıyla sistem tarafından yönetilir. Bu döngüyü anlamak, görünümün doğru şekilde ayarlanması ve çizilmesi için kritik öneme sahiptir.
| Yöntem | Ne Zaman Çağrılır | Amaç |
|---|---|---|
| init(frame:) | Koddan görünüm oluşturma | Özellikleri başlatma, alt görünüm ekleme |
| init(coder:) | Storyboard/XIB'den yükleme | Seri durumdan çıkarma ve ilk kurulum |
| layoutSubviews() | Çerçeve değiştiğinde | Alt öğelerin geometrisini yeniden hesaplama |
| draw(_:) | İlk görünümde veya setNeedsDisplay() sonrası | Core Graphics ile içerik çizme |
| didMoveToSuperview() | Hiyerarşiye eklendikten sonra | Son kurulum, animasyonları başlatma |
Tüm yöntemler sistem tarafından otomatik olarak çağrılır ve geliştiricinin bunları manuel olarak çağırması gerekmez. İstisna, sisteme draw(_:) yöntemini yeniden çağırması gerektiğini bildiren setNeedsDisplay()'dir.
draw(_:), Custom UIView'de özel çizim için anahtar yöntemdir. İçinde, geliştirici CGContext'e (grafik bağlamı) erişir ve Core Graphics kullanarak çizgiler, şekiller, metin ve resimler çizebilir.
Sistem, görünüm ekranda ilk kez göründüğünde draw(_:) yöntemini otomatik olarak çağırır. Sonraki bir çağrı, görünümü yeniden çizilmesi gereken olarak işaretleyen setNeedsDisplay() tarafından tetiklenir. Önemli: draw(_:) yöntemini doğrudan çağırmayın — bu önbelleğe alma mekanizmasını bozar ve performansı düşürür.
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
// Arka plan dolgusu
context.setFillColor(UIColor.systemBlue.cgColor)
context.fill(rect)
// Bir daire çizme
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(4.0)
let circleRect = rect.insetBy(dx: 20, dy: 20)
context.strokeEllipse(in: circleRect)
}
Bu örnekte, draw(_:) arka planı mavi renkle doldurur ve kenarlardan 20 piksel boşlukla beyaz bir daire çizer. draw(_:) yönteminin her çağrısı aynı sonucu üreten olmalıdır — aynı parametrelerle birden çok çağrı aynı sonucu vermelidir.
Apple, draw(_:) içindeki çalışmayı en aza indirmeyi önerir — UIBezierPath'i önceden oluşturun, resimleri önbelleğe alın ve ağır hesaplamalar yapmayın. Görünüm statikse, sürekli yeniden çizim yerine işlenmiş bir resimle UIImageView kullanmayı düşünün.
CALayer, UIView'in görsel içeriğini yöneten temel katmandır. Birçok özel çizim görevi, draw(_:) geçersiz kılınmadan CALayer özellikleri yapılandırılarak çözülebilir ve bu önemli ölçüde daha verimlidir.
Apple Engineering'e (2024) göre, CALayer düzeyindeki işlemler GPU'da çalışırken, draw(_:) CPU tabanlı Core Graphics işleme yoluyla çalışır. Animasyonlar ve yumuşak geçişler için CALayer ve CABasicAnimation kullanmak tercih edilir.
| Senaryo | Önerilen Yaklaşım | Performans |
|---|---|---|
| Yuvarlak köşeler | layer.cornerRadius | GPU, yüksek |
| Gölgeler ve gradyanlar | CAGradientLayer, shadowPath | GPU, yüksek |
| Rastgele şekiller | UIBezierPath ile CAShapeLayer | GPU, yüksek |
| Karmaşık grafikler | Core Graphics ile draw(_:) | CPU, orta |
| Özel biçimlendirmeli metin | CATextLayer veya draw(_:) | Hacme bağlı |
Animasyonlu vektör şekilleri çizmek için CAShapeLayer kullanın — donanım hızlandırmalıdır ve draw(_:) çağırmadan path, strokeStart ve strokeEnd animasyonunu destekler.
Custom UIView performansı, animasyonların akıcılığını ve genel kullanıcı deneyimini doğrudan etkiler. Temel sorunlar aşırı draw(_:) çağrılarından, alt görünümlerin optimal olmayan düzeninden ve önbelleğe alma eksikliğinden kaynaklanır.
setNeedsDisplay() çağrılarının her biri, görünümün tamamen yeniden çizilmesini tetikler. Değişiklikler yalnızca görünümün bir kısmını etkilediyse, belirli bir dikdörtgenle setNeedsDisplay(_:) kullanın. CALayer özellikleri (backgroundColor, cornerRadius, shadow) için yeniden çizim gerekmez — GPU düzeyinde güncellenirler.
Custom UIView içeriği nadiren değişiyorsa, UIGraphicsImageRenderer içinde bir kez işleyin ve UIImage olarak kaydedin. Bir sonraki yeniden çizimde, önbelleğe alınmış resmi görüntülemek için draw(at:) kullanın — bu, Core Graphics aracılığıyla yeniden işlemekten onlarca kat daha hızlıdır.
func renderToImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
return renderer.image { ctx in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
CALayer üzerindeki shouldRasterize özelliği, katmanın bitmap temsilinin önbelleğe alınmasını etkinleştirir. Saydamlık ve gölgelere sahip statik görünümler için etkinleştirin — bu, birleştirme yükünü azaltır. Animasyonlu görünümler için devre dışı bırakın: önbellek her değişiklikte sıfırlanır ve rasterleştirme yalnızca performansı düşürür.
Sıkça Sorulan Sorular
Hayır, draw(_:) yalnızca Core Graphics aracılığıyla özel çizim için gereklidir. Görünüm standart alt görünümlerden (UILabel, UIImageView) oluşuyorsa ve CALayer kullanıyorsa, draw(_:) geçersiz kılmak gerekli değildir — hatta performansı artıracaktır.
Tuval üzerine normal bir UIView yerleştirin, Identity Inspector'da Class alanında sınıfınızı belirtin. Sınıf @IBDesignable ile işaretlenmişse, değişiklikler Storyboard'da gerçek zamanlı olarak görüntülenecektir.
init(frame:) programatik olarak görünüm oluşturulurken çağrılır — konum ve boyut içeren bir CGRect iletirsiniz. init(coder:) Storyboard veya XIB'den seri durumdan çıkarılırken çağrılır. Doğru çalışma için her ikisi de uygulanmalıdır, aksi takdirde görünümünüz Interface Builder'dan yüklenirken çökecektir.
En yaygın neden, görünümün sıfır çerçeveye sahip olmasıdır (genişlik veya yükseklik sıfır). Sistem, sıfır boyutlu görünümler için draw(_:) çağırmaz. layoutSubviews() içinde çerçeveyi kontrol edin ve görünümün doğru kısıtlamalarla hiyerarşiye eklendiğinden emin olun.
GPU animasyonunu (position, opacity, transform) destekleyen özellikler için CALayer kullanın. draw(_:) öğesinin kısmi güncellemeleri için, değiştirilen alanın CGRect'i ile setNeedsDisplay(_:) kullanın — sistem tüm görünümü değil, yalnızca belirtilen bölgeyi yeniden çizer.
Özet
Anahtar teslim bir mobil uygulama geliştireceğiz
IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.
Ayrıca okuyun