Генератор QR-кодов на Swift: Core Image, CIFilter и собственные решения

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Генерация QR-кодов на Swift (iOS/macOS): от Core Image до кастомных решений

QR-коды стали неотъемлемой частью современных приложений — от передачи ссылок до авторизации и оплаты. На платформах Apple (iOS, macOS, watchOS, tvOS) существует встроенный мощный инструмент для генерации QR-кодов — фреймворк Core Image с фильтром CIQRCodeGenerator. В этой статье мы подробно разберем, как создать собственный генератор QR-кодов на Swift, включая настройку цвета, размера, добавление логотипа и интеграцию с SwiftUI.

Основы: Core Image и CIQRCodeGenerator

Core Image — это встроенный фреймворк Apple для обработки изображений. Фильтр CIQRCodeGenerator позволяет создать QR-код из любой строки (URL, текст, контактные данные). Он поддерживает коррекцию ошибок (уровни L, M, Q, H) и кодирование до 7089 символов (в зависимости от уровня коррекции).

Базовый пример генерации QR-кода в виде UIImage:

import UIKit
import CoreImage

func generateQRCode(from string: String) -> UIImage? {
    let data = string.data(using: .utf8)
    guard let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
    filter.setValue(data, forKey: "inputMessage")
    filter.setValue("H", forKey: "inputCorrectionLevel") // Максимальная коррекция ошибок
    
    guard let outputImage = filter.outputImage else { return nil }
    
    // Увеличиваем разрешение (по умолчанию маленькое)
    let transform = CGAffineTransform(scaleX: 10, y: 10)
    let scaledImage = outputImage.transformed(by: transform)
    
    return UIImage(ciImage: scaledImage)
}

// Использование
if let qrImage = generateQRCode(from: "https://pythonlib.ru") {
    // Отображаем qrImage в UIImageView
}

Настройка цвета и фона

По умолчанию QR-код черно-белый. Чтобы изменить цвета, нужно преобразовать CIImage в UIImage, затем выполнить заливку с использованием Core Graphics или CIFilter. Проще всего — использовать CIFalseColor:

func generateColoredQRCode(from string: String, color: UIColor, backgroundColor: UIColor) -> UIImage? {
    guard let data = string.data(using: .utf8),
          let qrFilter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
    qrFilter.setValue(data, forKey: "inputMessage")
    qrFilter.setValue("M", forKey: "inputCorrectionLevel")
    
    guard let qrImage = qrFilter.outputImage else { return nil }
    
    // Применяем цветовой фильтр
    let colorFilter = CIFilter(name: "CIFalseColor")
    colorFilter?.setValue(qrImage, forKey: "inputImage")
    colorFilter?.setValue(CIColor(color: color), forKey: "inputColor0")   // Цвет модулей
    colorFilter?.setValue(CIColor(color: backgroundColor), forKey: "inputColor1") // Цвет фона
    
    guard let coloredImage = colorFilter?.outputImage else { return nil }
    
    let transform = CGAffineTransform(scaleX: 10, y: 10)
    let scaledImage = coloredImage.transformed(by: transform)
    
    return UIImage(ciImage: scaledImage)
}

Добавление логотипа в центр QR-кода

Для брендирования часто требуется вставить логотип в центр. Это снижает читаемость, поэтому лучше использовать высокий уровень коррекции ошибок (H). Алгоритм: сначала создаем QR-код, затем накладываем поверх него UIImage с логотипом.

func generateQRWithLogo(from string: String, logo: UIImage, qrColor: UIColor = .black, bgColor: UIColor = .white) -> UIImage? {
    guard let qrImage = generateColoredQRCode(from: string, color: qrColor, backgroundColor: bgColor) else { return nil }
    
    let qrSize = qrImage.size
    let logoSize = CGSize(width: qrSize.width * 0.25, height: qrSize.height * 0.25) // 25% от QR
    let logoOrigin = CGPoint(x: (qrSize.width - logoSize.width) / 2,
                             y: (qrSize.height - logoSize.height) / 2)
    
    UIGraphicsBeginImageContextWithOptions(qrSize, false, qrImage.scale)
    qrImage.draw(at: .zero)
    logo.draw(in: CGRect(origin: logoOrigin, size: logoSize))
    let finalImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    return finalImage
}

Интеграция с SwiftUI

В SwiftUI удобно использовать генератор через @State и Image. Пример компонента:

import SwiftUI
import CoreImage.CIFilterBuiltins

struct QRCodeView: View {
    let text: String
    let color: UIColor = .blue
    let bgColor: UIColor = .white
    
    var body: some View {
        if let image = generateColoredQRCode(from: text, color: color, backgroundColor: bgColor) {
            Image(uiImage: image                    

Рекомендаций