draw(_:) / drawRect, UIView sınıfının (Swift'te) ve Objective-C'deki karşılığının (drawRect:) bir yöntemidir ve Core Graphics kullanarak görünüm içeriğinin render edilmesinden sorumludur. Sistem, görünüm ekranda ilk kez göründüğünde ve setNeedsDisplay() çağrısından sonra bu yöntemi otomatik olarak çağırır. Apple Belgeleri'ne (2025) göre draw(_:), geliştiricinin özel çizim için geçerli ekranın grafik bağlamına erişebildiği tek yöntemdir. draw(_:)'ı geçersiz kılmak, bileşenin görünümü üzerinde tam kontrol sağlar — basit geometrik şekillerden karmaşık animasyonlu grafiklere kadar.
Önemli Noktalar
draw(_:), UIKit'in görünüm içeriğini render etmek için çağırdığı bir UIView örnek yöntemidir. Bu yöntemin içinde, geliştirici CGContext grafik bağlamına erişir ve çizgiler, dolgular, metin ve görüntüler çizmek için Core Graphics API'sini kullanır. Objective-C'de drawRect: aynı işlevi ancak farklı sözdizimiyle yerine getirir: tek parametre, yeniden çizilecek alanı belirten bir CGRect'tir.
Apple Engineering'e (2024) göre draw(_:), CPU tabanlı Bitmap Graphics Context renderi aracılığıyla çalışır ve maksimum esneklik sağlar ancak CALayer'a kıyasla daha fazla kaynak gerektirir. draw(_:) kullanma kararı, grafiğin karmaşıklığına ve performans gereksinimlerine göre verilir.
Swift'te yöntem override func draw(_ rect: CGRect) olarak bildirilir, burada rect yeniden çizilmesi gereken dikdörtgendir. Objective-C'de imza - (void)drawRect:(CGRect)rect şeklindedir. setNeedsDisplay(_:) aracılığıyla kısmi yeniden çizim sırasında rect parametresi görünümün bounds'undan daha küçük olabilir.
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rect);
}
Sistem, kesin olarak tanımlanmış senaryolarda otomatik olarak draw(_:)'ı çağırır. Bu tetikleyicileri anlamak, gereksiz yeniden çizimleri önlemeye ve görünüm performansını optimize etmeye yardımcı olur. Aşağıda yöntemin otomatik çağrılmasının tüm durumları listelenmiştir.
Apple belgeleri uyarır: draw(_:)'ı asla doğrudan çağırmayın. Sistem çizimi ne zaman yapacağına kendisi karar verir ve doğrudan çağrı dahili önbellekleme mekanizmasını bozar. Yeniden çizim istemek için her zaman setNeedsDisplay() veya setNeedsDisplay(_:) kullanın.
Swift'te draw(_:)'ı geçersiz kılmak, grafik bağlamını almak ve ardından Core Graphics çağrılarıyla başlar. Çizimin mantıksal blokları için ayrı yöntemler oluşturulması önerilir — bu, kod okunabilirliğini ve test edilebilirliğini artırır.
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
// Line parameters
context.setStrokeColor(UIColor.darkGray.cgColor)
context.setLineWidth(2.0)
// Drawing a triangle
context.move(to: CGPoint(x: rect.midX, y: rect.minY + 10))
context.addLine(to: CGPoint(x: rect.maxX - 10, y: rect.maxY - 10))
context.addLine(to: CGPoint(x: rect.minX + 10, y: rect.maxY - 10))
context.closePath()
context.strokePath()
}
Bu örnekte draw(_:), 2 piksel kalınlığında koyu gri bir çerçeveye sahip bir üçgen çizer. Yöntemin başında super.draw(rect) çağrısı, üst çizim mantığını korumak için Apple tarafından önerilir, ancak UIView'in varsayılan draw(_:) uygulaması boştur.
draw(_:)'ın her çağrısı, aynı girdi verileriyle aynı sonucu üretmelidir. Bu, sistemin sonucu önbelleğe almasına ve görünüm içeriği değişmediyse draw(_:)'ı tekrar çağırmamasına olanak tanır. draw(_:) içinde rastgele değerler, sistem saati veya ağ istekleri kullanmayın.
drawRect: tarihsel olarak iOS 2.0'da Objective-C ile ortaya çıkan yöntemin ilk sürümüdür. Swift'te yöntem, dış parametre _ kullanılarak draw(_:) olarak yeniden adlandırılmıştır. İşlevsel olarak yöntemler aynıdır: her ikisi de yeniden çizilecek alanın CGRect'ini alır ve grafik bağlamına erişmek için UIGraphicsGetCurrentContext() kullanır.
| Özellik | draw(_:) (Swift) | drawRect: (Objective-C) |
|---|---|---|
| İmza | override func draw(_ rect: CGRect) | - (void)drawRect:(CGRect)rect |
| super çağrısı | super.draw(rect) | [super drawRect:rect] |
| Bağlam | UIGraphicsGetCurrentContext() | UIGraphicsGetCurrentContext() |
| rect parametresi | rect: CGRect | CGRect rect |
| Performans | Aynı | Aynı |
Bir projeyi Objective-C'den Swift'e taşırken yöntemi yeniden adlandırmak ilk görevlerden biridir. Xcode otomatik bir dönüştürücü sağlar, ancak drawRect: manuel olarak draw(_:)'a güncellenmelidir. Apple'a (2024) göre Swift sürümü draw(_:) yeni projeler için tercih edilir.
draw(_:) CPU'da çalışır ve optimal olmayan bir uygulama, kare düşüşlerine ve düşük performansa neden olabilir. Apple, çizimi hızlandırmak için birkaç kanıtlanmış yaklaşım önerir.
Her Core Graphics işleminin (move(to:), addLine(to:), strokePath) ek yükü vardır. İşlemleri gruplandırın ve karmaşık şekiller için CGPath kullanın — yol bir kez oluşturulur ve her draw(_:) çağrısında yeniden kullanılır.
UIBezierPath, şekiller oluşturmak için basit bir API sağlayan CGPath üzerinde bir Objective-C sarmalayıcısıdır. UIBezierPath'i önceden oluşturun (örneğin başlatıcıda) ve draw(_:) içinde yalnızca fill() veya stroke() çağırın.
private let starPath: UIBezierPath = {
let path = UIBezierPath()
// Building a star shape
path.move(to: CGPoint(x: 50, y: 0))
for i in 1...5 {
let angle = CGFloat(i) * 4 * CGFloat.pi / 5
path.addLine(to: CGPoint(x: 50 + 40 * cos(angle),
y: 50 + 40 * sin(angle)))
}
path.close()
return path
}()
override func draw(_ rect: CGRect) {
UIColor.systemYellow.setFill()
starPath.fill()
}
Geliştiriciler draw(_:)'ı geçersiz kılarken sıklıkla aynı hataları yaparlar. Bu kalıpları bilmek, hatalardan ve performans düşüşünden kaçınmaya yardımcı olur. En yaygın sorunlara ve çözümlerine bakalım.
Bu kuralları izleyerek, herhangi bir iOS projesinde kararlı ve hızlı özel görünüm çizimi sağlarsınız. Gerçek yürütme süresini ve darboğazları görmek için Instruments (Core Animation) aracılığıyla draw(_:)'ı profilleyin.
Sıkça Sorulan Sorular
Hayır, draw(_:)'ın doğrudan çağrılması Apple belgeleri tarafından yasaklanmıştır. Sistem çizim döngüsünü kendisi yönetir. Yeniden çizim istemek için setNeedsDisplay() kullanın; bu, görünümü en yakın render döngüsünde güncellenmesi gereken olarak doğru şekilde işaretler.
İşlevsel olarak bu yöntemler aynıdır. drawRect: Objective-C'de kullanılır, draw(_:) Swift'te. Her ikisi de yeniden çizilecek alanın CGRect'ini alır ve UIGraphicsGetCurrentContext() aracılığıyla aynı Core Graphics bağlamını kullanır.
Apple render'ı optimize eder: Bir UIView'de geçersiz kılınmış draw(_:) yoksa, sistem onun için bitmap bağlamı oluşturmaz. Bu bellek tasarrufu sağlar. Geçersiz kılma varsa ancak yöntem çağrılmıyorsa — görünümün çerçevesinin sıfır olmadığını ve görünümün görünür olduğunu kontrol edin.
Yalnızca gerekli olduğunda: ilk render, setNeedsDisplay() sonrası, contentMode = .redraw ile bounds değiştiğinde. Statik durumda draw(_:) tekrar çağrılmaz, CPU ve pil kaynaklarından tasarruf sağlar.
Apple, geçersiz kılınan yöntemin başında super.draw(rect) çağrısını önerir. Mevcut UIView uygulaması boş olsa da, super çağrısı gelecekteki UIKit sürümleriyle uyumluluğu garanti eder ve iyi bir uygulamadır.
Ö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