iOS-da CGContext — bu nədir, metodlar və çəkmə kontekstini necə idarə etməli

Müəllif: IT Sectr Dərc olunub: 2026-07-21 Oxuma vaxtı: 9 dəq

CGContext — iOS və macOS-da 2D çəkmə əmrlərini yerinə yetirmək üçün Core Graphics-in əsas obyekti. O, qrafik konteksti təmsil edir və cari vəziyyəti saxlayır: dolğu rəngi, xətt qalınlığını, transformasiyanı, kəsmə sahəsini və şriftləri. Bütün çəkmə əməliyyatları — xətlər, dördbucaqlılar, mətn, şəkillər — CGContext vasitəsilə yerinƏ yetirilir. Apple Developer Documentation, 2026-ya görə, CGContext Apple ekosistemində bütün raster və vektor qrafikasının təməlidir.

Başlıca

  • CGContext — bütün 2D Core Graphics əmrlərinin yerinƏ yetirildiyi qrafik kontekst.
  • setStrokeColorsetFillColor kontekstdə xətlərin və dolğuların rəngini idarə edir.
  • addPathdrawPath ixtiyari CGPath konturlarını çəkməyə imkan verir.
  • clip(to:) müəyyən bir zona ilə məhdudlaşdırmaq üçün kəsmə sahəsini təyin edir.
  • saveGStaterestoreGState kontekst vəziyyətləri yığınını saxlayır və bərpa edir.

CGContext nədir?

CGContext — Core Graphics çərçivəsindən 2D render əmrlərini yerinƏ yetirmək üçün mühiti təmsil edən qeyri-şəffaf tip (opaque type). O, vəziyyətlər yığınını, cari rəng məkanını, koordinat transformasiyasını və kəsmə sahəsini idarə edir. CGContext bütün Quartz 2D çəkmə funksiyalarının qarşılıqlı əlaqədə olduğu yeganƏ obyektdir — bütün qrafik əməliyyatları onun vasitƏsilƏ keçir.

CGContext təyinatından asılı olaraq bir neçe növdƏ olur: yaddaşda raster şəkillƏrlƏ işləmək üçün bitmap context, PDF sənƏdləri yaratmaq üçün PDF context, ekranda göstərmək üçün window context (UIView tərƏfindən draw(_:) də təmin edilir). iOS proqramçıları ən çox draw(_:) metodu daxilindƏ UIGraphicsGetCurrentContext() vƏ ya oflayn render üçün UIGraphicsBeginImageContextWithOptions-dan əldə edilən kontekstlƏ işləyirlƏr.

Kontekst bütün parametrlƏri vəziyyətlər yığını vasitƏsilƏ tətbiq edir — proqramçı cari vəziyyəti saxlaya (saveGState), parametrləri dəyişə vƏ əvvəlki vəziyyəti bərpa edƏ bilər (restoreGState). Bu, mürəkkƏb səhnƏlƏri render edərkən kritik əhəmiyyət daşıyır, çünki müxtəlif elementlər müxtəlif rəng, xətt qalınlığı və transformasiya tələb edir. Apple WWDC 2023-Ə görə, vəziyyətlər yığınının düzgün istifadəsi kodun oxunaqlılığını artırır və vizual artefaktların qarşısını alır.

Vəziyyətin idarə edilməsi: saveGState və restoreGState

CGContextSaveGState kontekstin cari vəziyyətinin surətini yığına yerləşdirir. Bu vəziyyət bütün parametrləri əhatə edir: rənglər, xətt qalınlığı, transformasiya, kölgƏlər, kəsmə sahəsi, şriftlər. Parametrlər dəyişdirildikdƏn sonra CGContextRestoreGState çağırışı konteksti saxlanılmış vəziyyətə qaytararaq bütün aralıq dəyişiklikləri ləğv edir. Yığın iOS-da 32 vəziyyətə qədər saxlaya bilər.

Yığının praktik tətbiqi

Müxtəlif üslublu elementlər qrupunu çəkərkən (məsəlƏn, diaqramın çoxrəngli sektorları) vəziyyətlər yığını hər bir parametri əl ilƏ yadda saxlamaq və bərpa etmək zərurətini aradan qaldırır. saveGState/restoreGState olmadan proqramçı hər elementdən sonra rəngi, kölgƏni və transformasiyanı yenidƏ təyin etməli olardı. Yığının istifadəsi kodu qısaltır və bərpa xətalarını aradan qaldırır.

Saxlama və bərpa balansını qorumaq vacibdir — hər saveGState üçün bir restoreGState olmalıdır. Balansın pozulması vəziyyətlərin sızmasına və ya vaxtından ƏvvƏl bərpaya səbəb olur, bu da gözlənilməz göstərimƏ gətirib çıxarır. Xcode statik analizatoru CGContext yığın balansını yoxlamır, buna görƏ düzgünlük məsuliyyəti proqramçının üzərinə düşür. CütlƏri do/finally bloklarında qruplaşdırmaq tövsiyə olunur.

swift
override func draw(_ rect: CGRect) {
    guard let ctx = UIGraphicsGetCurrentContext() else { return }

    ctx.saveGState()
    ctx.setStrokeColor(UIColor.red.cgColor)
    ctx.setLineWidth(3)
    ctx.addRect(CGRect(x: 50, y: 50, width: 200, height: 100))
    ctx.strokePath()
    ctx.restoreGState()
}

Rənglər və dolğular

CGContextSetFillColorWithColor sonrakı əməliyyatlar üçün dolğu rəngini təyin edir. Rəng CGColorRef kimi ötürülür, tərkibindƏ rəng məkanı və rəng komponentləri haqqında məlumat saxlayır. CGContextSetStrokeColorWithColor kontur rəngi üçün eyni şəkildƏ işləyir. Apple tez-tez istifadə olunan CGColorRef-lərin keşlɘnmɘsini tövsiyə edir.

CGContext-də gradientlər

CGContextDrawLinearGradient iki nöqtə arasında müəyyən edilmiş rənglƏrlƏ xətti gradient çəkir. CGContextDrawRadialGradient bir dairƏdən digərinə keçən radial gradient yaradır. GradientlƏrlƏ işləmək üçün ƏvvƏl rənglər və dayanma nöqtələri massivini ehtiva edən CGGradientRef obyekti yaradılır. CGContext-də gradientlər həm RGB, həm də Grayscale rəng məkanlarını dəstəkləyir.

Sahəni gradientlƏ doldurmaq üçün ƏvvƏlcədən kəsmə sahəsinin təyin edilməsi tələb olunur. Clip olmadan gradient bütün konteksti doldurar, yalnız lazım olan formanı yox. Tipik naxş: kontekstə yol Əlavə etmək, sahəni məhdudlaşdırmaq üçün clip çağırmaq, sonra gradient çəkmək. Bu naxış düymƏlərdƏn fonlara qədər mürəkkƏb formaların gradient dolğusunu tələb edən bütün tətbiqlərdə istifadə olunur.

FunksiyaTəyinatRəng məkanı
setFillColorDolğu rəngini təyin edirIstənilən (CGColor vasitəsilə)
setStrokeColorKontur rəngini təyin edirIstənilən (CGColor vasitəsilə)
drawLinearGradientXətti gradient çəkirRGB və ya Grayscale
drawRadialGradientRadial gradient çəkirRGB və ya Grayscale

Konturların və xətlərin çəkilməsi

CGContextAddPath sonrakı render üçün ƏvvƏl yaradılmış CGPathRef-i kontekstə Əlavə edir. Yol Əlavə edildikdƏn sonra onu konturlamaq (strokePath), doldurmaq (fillPath) və ya hər iki əməliyyatı yerinƏ yetirmək olar. CGContextBeginPath Əvvəlki yolu təmizləyƏrək yeni bir yola başlayır. Kontekst hər an yalnız bir aktiv yolu dəstəkləyir.

Nöqtələr üzrə düz xətlər və əyrilər

CGContextMoveToPoint yolun cari nöqtəsini göstərilən koordinatlara köçürür. CGContextAddLineToPoint cari nöqtədən verilən nöqtəyə düz xətt çəkir. CGContextAddCurveToPoint kubik Bézier əyrisi Əlavə edir, CGContextAddQuadCurveToPoint — kvadratik. CGContextClosePath son və ilk nöqtə arasında düz xəttlə yolu bağlayır.

Bütün bu metodların yol obyektindƏ çağırıldığı UIBezierPath-dən fərqli olaraq, CGContext-də onlar birbaşa kontekstə çağırılır. Bu fərq yanaşma seçimindƏ vacibdir: UIBezierPath konturların təkrar istifadəsi üçün daha rahatdır, CGContext — minimal yüklƏ birdəfəlik render üçün. CGContext həmçinin CGContextSetLineDash vasitəsilə kəsik xətləri, CGContextSetLineCap vasitəsilə çevik ucları və CGContextSetLineJoin vasitəsilə birləşmələri dəstəkləyir.

swift
let ctx = UIGraphicsGetCurrentContext()!
ctx.beginPath()
ctx.moveTo(x: 50, y: 100)
ctx.addLineTo(x: 200, y: 100)
ctx.addCurveTo(x1: 250, y1: 50, x2: 300, y2: 150, x3: 350, y3: 100)
ctx.setStrokeColor(UIColor.blue.cgColor)
ctx.setLineWidth(5)
ctx.strokePath()

Kəsmə sahəsi və transformasiyalar

CGContextClip çəkmə sahəsini cari yolla məhdudlaşdırır. Bütün sonrakı çəkmə əməliyyatları yalnız bu sahə daxilindƏ görünəcəkdir. Bu, maskalama, küncləri yuvarlaqlaşdırma və elementlərin qeyri-standart sərhƏdlərini yaratmaq üçün əsas mexanizmdir. Kəsmə sahəsi həmçinin saveGState/restoreGState vasitəsilƏ saxlanılır və bərpa edilir.

Koordinat transformasiyası

CGContextTranslateCTM kontekstin koordinat başlanğıcını yerdəyişdirir. CGContextScaleCTM X və Y oxlarını miqyaslaşdırır. CGContextRotateCTM koordinat sistemini cari başlanğıc ətrafında fırladır. Transformasiyalar toplanır — hər sonrakısı cari koordinat sisteminə nisbətən tətbiq edilir. MürəkkƏb transformasiyalar (yerdəyişmə + fırlanma + miqyas) animasiya və elementlərin yerləşdirilməsi üçün istifadə olunur.

Kəsmə və transformasiyanın birgƏ istifadəsi güclü imkanlar verir: kəsmə vasitƏsilƏ mürəkkƏb maska çəkmək, sonra bütün məzmuna transformasiya tətbiq etmək olar. Tipik nümunə — yuvarlaq kənarlı şəklin bir hissəsini bucaq altında göstərmək. Əməliyyatların ardıcıllığı vacibdir: ƏvvƏl kəsmə sahəsini təyin edin, sonra transformasiya tətbiq edin, daha sonra məzmunu çəkin. Apple render dövründƏ CTM (Current Transformation Matrix) dəyişikliklərinin sayını minimuma endirməyi tövsiyə edir.

swift
override func draw(_ rect: CGRect) {
    guard let ctx = UIGraphicsGetCurrentContext() else { return }
    ctx.saveGState()

    // kəsmə bölgəsi — dairə
    ctx.addEllipse(in: CGRect(x: 50, y: 50, width: 200, height: 200))
    ctx.clip()

    // məzmun transformasiyası
    ctx.translateBy(x: 150, y: 150)
    ctx.rotate(by: .pi / 4)
    ctx.translateBy(x: -150, y: -150)

    UIImage(named: "photo")?.draw(at: CGPoint(x: 50, y: 50))
    ctx.restoreGState()
}

CGContext-də çəkmə nümunəsi

CGContext istifadə edərək gradient diaqramının yaradılmasının tam nümunəsini nəzərdən keçirək. Diaqrama gradient dolğusu və mətn etiketləri olan üç müxtəlif rəngli sektor daxildir. Kod bir kontekstdƏ saveGState, clip, gradientlər və mətn renderinin kombinasiyasını nümayiş etdirir.

swift
class PieChartView: UIView {

    private struct Slice {
        let color: UIColor
        let value: CGFloat
        let label: String
    }

    override func draw(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        let slices = [
            Slice(color: .systemRed, value: 0.4, label: "iOS"),
            Slice(color: .systemGreen, value: 0.35, label: "Android"),
            Slice(color: .systemBlue, value: 0.25, label: "Other")
        ]

        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        let radius = bounds.width * 0.35
        var startAngle: CGFloat = -.pi / 2

        for slice in slices {
            let endAngle = startAngle + .pi * 2 * slice.value

            ctx.saveGState()
            ctx.moveTo(x: center.x, y: center.y)
            ctx.addArc(center: center, radius: radius,
                       startAngle: startAngle, endAngle: endAngle, clockwise: false)
            ctx.closePath()
            ctx.setFillColor(slice.color.cgColor)
            ctx.fillPath()

            // mətn etiketi
            let midAngle = startAngle + endAngle / 2
            let labelPos = CGPoint(
                x: center.x + radius * 0.7 * cos(midAngle),
                y: center.y + radius * 0.7 * sin(midAngle)
            )
            slice.label.draw(at: labelPos, withAttributes: [
                .foregroundColor: UIColor.white,
                .font: UIFont.boldSystemFont(ofSize: 14)
            ])
            ctx.restoreGState()
            startAngle = endAngle
        }
    }
}

Bu nümunƏdƏ diaqramın hər sektoru öz saveGState/restoreGState blokunda çəkilir. Bu yanaşma bir sektorun rəng və yol parametrlərinin digərlərinə təsir etməməsini təmin edir. addArc metodu başlanğıc və son bucaq arasında qövs yaradır, closePath sektoru mərkəzə bağlayır. Mətn etiketi sektor bucağının orta xəttindƏ yerləşdirilir, mövqe üçün cos və sin triqonometrik funksiyalarından istifadə olunur.

Tez-tez yenidƏ çəkmƏ zamanı performansı artırmaq üçün bucaqların və mövqelərin hesablamalarını ayrıca massivdƏ keşlɘmək tövsiyə olunur. CGContext bütün əməliyyatları CPU-da yerinƏ yetirir, buna görƏ onlarla sektoru olan mürəkkƏb səhnƏlər optimizasiya tələb edə bilər — məsəlƏn, CGLayer-dƏ ilkin rastrlşşdırma və ya GPU sürətləndirilməsi üçün Metal istifadəsi. 5–10 elementi olan əksər UI tapşırıqları üçün CGContext performansı məqbuldur.

Tez-tez verilən suallar

iOS-da cari CGContext-i necə əldə etmək olar?

UIView-in draw(_:) metodu daxilindƏ və ya UIGraphicsBeginImageContextWithOptions bloku daxilindƏ UIGraphicsGetCurrentContext() çağırın. CALayer təbəqələri üçün hazır kontekst alan CALayerDelegate-in draw(in:) metodundan istifadə edin.

fillPath və strokePath arasındakı fərq nədir?

fillPath cari yolun daxili sahəsini setFillColor rəngi ilƏ doldurur. strokePath setStrokeColor, setLineWidth və setLineCap parametrlƏri ilƏ yol boyunca xətt çəkir. Hər iki əməliyyat ardıcıl yerinƏ yetirilir: ƏvvƏl fill, sonra zərurət olduqda stroke.

Bitmap CGContext nədir?

Bitmap CGContext — CGBitmapContextCreate vasitƏsilƏ yaradılan və ekran əvəzinƏ yaddaş buferinƏ çəkən kontekst. Fon şəkil generasiyası, göstərmədƏn qrafik emalı və Metal və ya OpenGL üçün tekstur yaratmaq üçün istifadə olunur.

CGContext-in bütün parametrlərini necə sıfırlamaq olar?

Core Graphics bütün parametrləri sıfırlamaq üçün metod təqdim etmir. DəyişikliklərdƏn ƏvvƏl saveGState, ilkin vəziyyətə qayıtmaq üçün restoreGState istifadə edin. Alternativ olaraq eyni parametrlƏrlƏ yeni kontekst yarada bilərsiniz.

Niyə gradient fiqurun içindƏ görünmür?

drawLinearGradient çağırmazdan ƏvvƏl lazımı yolda clip vasitƏsilƏ kəsmə sahəsini təyin edin. Clip olmadan gradient bütün konteksti doldurar. Ardıcıllıq: addPath → clip → drawLinearGradient — fiqurun içindƏ gradienti təmin edir.

Nəticə

  • CGContext — iOS və macOS-da bütün 2D çəkmə əməliyyatları üçün Core Graphics-in mərkəzi obyekti.
  • saveGStaterestoreGState yan təsirlərin qarşısını alaraq kontekst vəziyyətlər yığınını idarə edir.
  • setFillColorsetStrokeColor CGColorRef vasitƏsilƏ dolğu və kontur rənglərini təyin edir.
  • addPath, strokePath, fillPath ixtiyari CGPath konturları ilƏ işləyir.
  • clip maskalar və yuvarlaqlaşdırmalar üçün çəkmə sahəsini cari yolla məhdudlaşdırır.
  • translateCTM, scaleCTM, rotateCTM kontekstin koordinat sistemini transformasiya edir.
  • Bütün CGContext əməliyyatları CPU-da yerinƏ yetirilir — mürəkkƏb qrafika üçün CGLayer və ya Metal istifadə edin.

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun