Core Graphics — фреймворк 2D-рендерингу від Apple, що входить до складу Core Foundation і доступний на iOS, macOS, tvOS та watchOS. Він надає низькорівневий C-API для роботи з векторною та растровою графікою, включаючи відмальовування контурів, градієнтів, тіней, зображень і тексту. Core Graphics слугує основою для UIKit, SwiftUI та AppKit. За даними Apple Developer Documentation, 2026, фреймворк використовується більш ніж у 90% iOS-додатків, оскільки будь-який видимий елемент проходить через Core Graphics або його апаратний аналог.
Головне
Core Graphics (також відомий як Quartz 2D) — це фреймворк, що реалізує 2D-графічний рушій Apple. Він заснований на портативній графічній бібліотеці Quartz і використовує модель малювання на основі сторінки, де кожна дія — це команда в послідовності, що нагадує малювання на папері. Core Graphics підтримує антиаліасинг, прозорість (альфа-композитинг) та колірні простори ICC.
Архітектура Core Graphics побудована навколо графічного контексту (CGContext), який інкапсулює цільовий пристрій виведення — екран, принтер, PDF-документ або растровий буфер. Контекст керує поточними налаштуваннями: кольором, товщиною лінії, трансформацією, областю відсікання та шрифтами. Такий підхід забезпечує уніфікований API для різних пристроїв виведення без зміни коду малювання.
Core Graphics працює переважно на CPU, використовуючи векторну модель (незалежну від роздільної здатності). Це означає, що лінії та криві растерізуються з поточною роздільною здатністю пристрою під час відмальовування. На відміну від Metal, Core Graphics не вимагає явного керування GPU-ресурсами — всю оптимізацію бере на себе система. Для більшості 2D-задач (графіка, діаграми, кастомні елементи UI) продуктивності Core Graphics достатньо для підтримки 60 FPS.
Core Graphics включає близько 50 базових типів (непрозорих типів), кожен з яких відповідає за певну функціональність. Усі типи дотримуються правил керування пам'яттю Core Foundation: створюються через функції з Create у назві, потребують виклику CGRelease і не є ARC-сумісними в Objective-C (однак Swift автоматично керує пам'яттю через анотації CF_RETURNS_RETAINED).
CGContext — контекст малювання, центральний тип фреймворку. CGPath — незмінний векторний контур. CGColor — колір із зазначенням колірного простору. CGGradient — градієнтна заливка. CGImage — растрове зображення. CGLayer — оптимізований офлайн-буфер для повторюваного малювання. CGDataProvider — джерело даних для зображень. CGColorSpace — колірний простір (sRGB, Display P3, Gray).
Кожен тип спроєктовано для мінімального оверхеду: CGPath може кешуватися та перевикористовуватися між різними контекстами, CGColor перетворюється на апаратне представлення GPU при передачі, CGLayer зберігає попередньо растерізований вміст. Така архітектура дозволяє Core Graphics ефективно працювати як у простих UI-задачах, так і в професійних графічних редакторах.
| Тип | Призначення | Керування пам'яттю |
|---|---|---|
| CGContext | Графічний контекст | CFRelease або автоматичне в Swift |
| CGPath | Векторний контур | CFRelease (незмінний) |
| CGColor | Колір у колірному просторі | CFRelease або CGColorCreate |
| CGImage | Растрове зображення | CFRelease (після створення) |
| CGLayer | Офлайн-буфер | CFRelease або CGLayerCreate |
CGPath — незмінний об'єкт, що описує послідовність геометричних сегментів: прямих ліній, кривих Безьє, дуг та замикань. На відміну від UIBezierPath, CGPath не містить методів малювання — він лише зберігає геометрію. Для відмальовування CGPath додається в контекст (CGContextAddPath) і потім малюється через strokePath або fillPath. Незмінність гарантує потокобезпеку та можливість кешування.
CGPathCreateMutable створює змінюваний шлях (CGMutablePathRef) для поетапної побудови. Після фінального складання він перетворюється на незмінний CGPathRef. Apple рекомендує мінімізувати кількість точок у CGPath — надто складні контури (понад 1000 сегментів) сповільнюють растеризацію. Для оптимізації використовуйте CGPathCreateCopyBySimplifyingPath, який видаляє надлишкові колінеарні точки.
Для анімації форми між двома CGPath можна використовувати CABasicAnimation на властивості path CAShapeLayer. Обмеження: обидва CGPath повинні мати однакову кількість сегментів (контрольних точок). Функція CGPathApply дозволяє обійти всі елементи шляху та порівняти їх структуру. Якщо сегменти не збігаються, анімація буде сіпаною — у цьому випадку використовуйте CADisplayLink для ручної інтерполяції точок.
// створити змінюваний шлях
let mutablePath = CGMutablePath()
mutablePath.moveTo(to: CGPoint(x: 0, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 0))
mutablePath.addLine(to: CGPoint(x: 100, y: 100))
mutablePath.closeSubpath()
// перетворити на незмінний для безпечного кешування
let immutablePath: CGPath = mutablePath
CATransaction.perform {
shapeLayer.path = immutablePath
}
CGGradient — об'єкт, що визначає плавний перехід між двома або більше кольорами вздовж прямої лінії (лінійний градієнт) або від центру до країв (радіальний градієнт). CGGradient створюється із зазначенням колірного простору, масиву CGColorRef та масиву позицій зупинок від 0.0 до 1.0. Після створення градієнт можна використовувати багаторазово в різних контекстах.
CGShading — потужніший механізм, що дозволяє задавати функцію зміни кольору вздовж шляху. На відміну від CGGradient, який працює з фіксованим набором кольорів, CGShading використовує callback-функцію (CGFunctionRef), що обчислює колір у кожній точці. Це дозволяє створювати складні градієнти з нелінійними переходами та складовими колірними схемами.
Для відмальовування градієнта всередині фігури необхідний clip на контур цієї фігури. Порядок: додати шлях у контекст, викликати CGContextClip, потім намалювати градієнт. Без clip градієнт заповнює весь контекст повністю. В iOS рекомендується використовувати CGGradient як простіший та продуктивніший варіант — CGShading виправданий лише для нестандартних функцій зміни кольору.
func drawGradient(ctx: CGContext, rect: CGRect) {
let colors = [UIColor.red.cgColor, UIColor.blue.cgColor] as CFArray
guard let gradient = CGGradient(
colorsSpace: CGColorSpaceCreateDeviceRGB(),
colors: colors,
locations: [0.0, 1.0]
) else { return }
ctx.saveGState()
ctx.addEllipse(in: rect)
ctx.clip()
ctx.drawLinearGradient(
gradient,
start: CGPoint(x: rect.midX, y: rect.minY),
end: CGPoint(x: rect.midX, y: rect.maxY),
options: []
)
ctx.restoreGState()
}
CGImage — растрове зображення в Core Graphics, яке може бути завантажене з файлу, створене програмно або отримане з UIImage. CGImage містить піксельні дані, інформацію про колірний простір, розмір, бітову глибину та розташування даних. На відміну від UIImage, CGImage не керує масштабуванням для Retina — цю відповідальність бере на себе розробник через параметр scale.
CGLayer — офлайн-буфер для попередньої растеризації статичного вмісту. Якщо один і той самий набір графічних команд відмальовується багаторазово (наприклад, патерн фону), CGLayer растерізує його один раз і потім просто копіює в контекст. За даними Apple, використання CGLayer може прискорити повторюване малювання в 2–5 разів на CPU та до 10 разів при апаратному прискоренні.
Для завантаження зображень використовуйте CGImageSource — потужний API для читання метаданих, мініатюр та окремих кадрів із GIF/APNG. CGImageSource дозволяє завантажувати зображення прогресивно та отримувати лише необхідні фрагменти. При роботі з великими зображеннями (що перевищують розмір екрану) рекомендується створювати CGImageSource з опцією кешування на диску та використовувати CGImageSourceCreateThumbnailAtIndex для відображення зменшеної версії.
func createLayer(ctx: CGContext, size: CGSize) -> CGLayer? {
guard let layer = CGLayer(ctx, size: size, auxiliaryInfo: nil) else { return nil }
let layerCtx = layer.context !
// намалювати один раз
layerCtx.setFillColor(UIColor.lightGray.cgColor)
layerCtx.addEllipse(in: CGRect(origin: .zero, size: size))
layerCtx.fillPath()
return layer
}
// використання в draw()
for i in 0..<20 {
ctx.draw(layer, at: CGPoint(x: CGFloat(i) * 30, y: 0))
}
Розробимо кастомне View для відображення водяного знака на зображенні з використанням Core Graphics. Водяний знак включає напівпрозорий текст та векторний логотип, накладені поверх вихідного зображення. Код демонструє роботу з CGContext, CGImage, текстом та прозорістю в одному контексті.
class WatermarkView: UIView {
private let watermarkText = "IT Sectr"
private let watermarkOpacity: CGFloat = 0.3
override func draw(_ rect: CGRect) {
guard let ctx = UIGraphicsGetCurrentContext() else { return }
// намалювати фонове зображення
UIImage(named: "background")?.draw(in: rect)
// налаштувати прозорість водяного знака
ctx.saveGState()
ctx.translateBy(x: rect.midX, y: rect.midY)
ctx.rotate(by: -.pi / 6)
// напівпрозорий текст
let attributes: NSAttributedString.Attributes = [
.font: UIFont.boldSystemFont(ofSize: 48),
.foregroundColor: UIColor.white.withAlphaComponent(watermarkOpacity)
]
let textSize = watermarkText.size(withAttributes: attributes)
watermarkText.draw(
at: CGPoint(x: -textSize.width / 2, y: -textSize.height / 2),
withAttributes: attributes
)
// векторна іконка (коло з хрестом) під текстом
ctx.setStrokeColor(UIColor.white.withAlphaComponent(watermarkOpacity).cgColor)
ctx.setLineWidth(3)
ctx.addEllipse(in: CGRect(x: -25, y: -75, width: 50, height: 50))
ctx.strokePath()
ctx.moveTo(x: -15, y: -50)
ctx.addLineTo(x: 15, y: -50)
ctx.moveTo(x: 0, y: -65)
ctx.addLineTo(x: 0, y: -35)
ctx.strokePath()
ctx.restoreGState()
}
}
У коді використано ключові можливості Core Graphics: saveGState/restoreGState для ізоляції ефектів водяного знака від фону, translateBy та rotate для позиціонування та повороту, напівпрозорий текст через withAlphaComponent та векторна іконка через addEllipse та addLineTo. Весь водяний знак малюється як єдина композиція після фонового зображення.
При створенні водяних знаків для фотографій у продакшені важливо враховувати продуктивність. Якщо зображення більше екрану, перед накладанням водяного знака зменшіть його через CGImageSourceCreateThumbnailAtIndex. Core Graphics обробляє всі операції на CPU — для пакетної обробки десятків зображень використовуйте фонову чергу та CGBitmapContext для уникнення блокування UI.
Поширені запитання
UIKit — високорівневий фреймворк UI, що використовує Core Graphics всередині себе для відмальовування. Core Graphics — низькорівневий C-API для 2D-графіки. UIKit зручніший для стандартних елементів, Core Graphics дає повний контроль над кожним пікселем.
Core Graphics підходить для статичної 2D-графіки, діаграм та кастомних UI-елементів. Metal — для 3D-графіки, складних анімацій та обробки великих масивів пікселів із GPU-прискоренням. Для 95% UI-задач достатньо Core Graphics.
Використовуйте CGImageSource для завантаження мініатюр через createThumbnailAtIndex замість повного завантаження. Для відображення великих зображень створюйте CGImage з опцією даунсемплу. Звільняйте CGImage через CGImageRelease коли він більше не потрібен.
Так, Core Graphics включає повноцінну підтримку PDF через CGPDFDocument для читання та CGPDFContext для створення PDF-документів. Можна малювати будь-який CGContext-контент прямо в PDF-сторінку зі збереженням векторів.
Core Graphics автоматично використовує роздільну здатність пристрою при відмальовуванні на екрані. Для офлайн-контекстів використовуйте UIGraphicsBeginImageContextWithOptions з параметром scale = 0 (системний масштаб) або явно вкажіть 2.0/3.0 для Retina/Retina HD.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також