iOS Mobile Инженер

iOS Mobile Инженер

Роадмап навыков для прокачки

Image и SF Symbols

SwiftUIViews BasicsBuilt-in Views

Основная идея

Image — view для отображения изображений в SwiftUI. SF Symbols — это библиотека из 5000+ векторных иконок от Apple, которые автоматически масштабируются и поддерживают Dynamic Type.

Ключевые аспекты

  • Image(systemName:) — загружает SF Symbol по имени
  • Image("name") — загружает изображение из Asset Catalog
  • resizable() — делает изображение масштабируемым
  • aspectRatio() — сохраняет пропорции при масштабировании
  • symbolRenderingMode() — режим рендеринга для SF Symbols (monochrome, multicolor, hierarchical, palette)

Плюсы SF Symbols

  • Векторные, масштабируются без потери качества
  • Автоматическая поддержка Dynamic Type
  • Согласованы с системным дизайном iOS
  • Мультицветные варианты с iOS 15+

Минусы

  • Только для Apple-платформ
  • Ограниченный набор иконок (хотя и большой)
  • Кастомные символы требуют дополнительной настройки

Частые ошибки на собеседованиях

  • Забывают resizable() перед изменением размера изображения
  • Путают scaledToFit() и scaledToFill()
  • Не знают про SF Symbols App для поиска иконок
  • Используют растровые изображения там, где подходят SF Symbols

Введение и проблематика

Изображения и иконки — неотъемлемая часть любого приложения. SwiftUI предоставляет Image view для работы с изображениями, а SF Symbols — это бесплатная библиотека векторных иконок от Apple, интегрированная в систему.

SF Symbols содержит более 5000 иконок, которые автоматически подстраиваются под размер текста (Dynamic Type) и поддерживают различные веса шрифта.


Базовая теория

Способы создания Image

Code Example 1: Какие способы загрузки изображений существуют в SwiftUI?

swift
// SF Symbol
Image(systemName: "star.fill")
 
// Из Asset Catalog
Image("myPhoto")
 
// Из Bundle
Image("photo", bundle: .main)
 
// Декоративное изображение (игнорируется VoiceOver)
Image(decorative: "background")
 
// UIImage
Image(uiImage: UIImage(named: "photo")!)

Популярные SF Symbols

КатегорияПримеры символов
Навигацияarrow.left, arrow.right, chevron.down
Действияplus, minus, xmark, checkmark
Общиеstar, heart, bell, gear
Медиаplay, pause, forward, backward
Коммуникацияenvelope, phone, message

Практические примеры

Базовое использование SF Symbols

Code Example 2: Как использовать SF Symbols и настроить их размер?

swift
struct SymbolsDemo: View {
    var body: some View {
        HStack(spacing: 20) {
            // Размер через font
            Image(systemName: "star.fill")
                .font(.caption)
 
            Image(systemName: "star.fill")
                .font(.title)
 
            Image(systemName: "star.fill")
                .font(.largeTitle)
 
            // Точный размер
            Image(systemName: "star.fill")
                .font(.system(size: 50))
        }
    }
}

Цвет и стиль символов

Code Example 3: Как изменить цвет SF Symbols?

swift
struct ColoredSymbols: View {
    var body: some View {
        HStack(spacing: 20) {
            // Одноцветный
            Image(systemName: "heart.fill")
                .foregroundStyle(.red)
 
            // Иерархический (автоматические оттенки)
            Image(systemName: "square.stack.3d.up.fill")
                .symbolRenderingMode(.hierarchical)
                .foregroundStyle(.blue)
 
            // Палитра (до 3 цветов)
            Image(systemName: "person.crop.circle.badge.checkmark")
                .symbolRenderingMode(.palette)
                .foregroundStyle(.blue, .green)
 
            // Мультицветный (оригинальные цвета Apple)
            Image(systemName: "externaldrive.badge.icloud")
                .symbolRenderingMode(.multicolor)
        }
        .font(.largeTitle)
    }
}

Работа с изображениями из Asset Catalog

Code Example 4: Как правильно масштабировать изображения?

swift
struct ImageScaling: View {
    var body: some View {
        VStack(spacing: 20) {
            // ❌ Не работает — изображение не масштабируется
            Image("photo")
                .frame(width: 100, height: 100)
 
            // ✅ Правильно — добавляем resizable()
            Image("photo")
                .resizable()
                .frame(width: 100, height: 100)
 
            // ✅ С сохранением пропорций
            Image("photo")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 100, height: 100)
 
            // ✅ Заполнение с обрезкой
            Image("photo")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 100, height: 100)
                .clipped()
        }
    }
}
⚠️

Всегда добавляйте resizable() перед frame(), иначе изменение размера не сработает!

Сравнение scaledToFit и scaledToFill

swift
// Изображение полностью помещается в рамку
// Могут быть пустые области
Image("photo")
    .resizable()
    .scaledToFit()
    .frame(width: 200, height: 200)
    .border(Color.red)

Пограничные кейсы

Круглые изображения (аватары)

Code Example 5: Как создать круглый аватар?

swift
struct Avatar: View {
    let imageName: String
    let size: CGFloat
 
    var body: some View {
        Image(imageName)
            .resizable()
            .scaledToFill()
            .frame(width: size, height: size)
            .clipShape(Circle())
            .overlay(
                Circle()
                    .stroke(Color.white, lineWidth: 2)
            )
            .shadow(radius: 3)
    }
}
 
// Использование
Avatar(imageName: "profile", size: 80)

Символы с переменным значением

swift
// iOS 16+ — анимация символов
Image(systemName: "wifi", variableValue: 0.5)
    .font(.largeTitle)
 
// Значение от 0 до 1 показывает "уровень"
// Работает для определённых символов: wifi, speaker, battery и др.

AsyncImage для загрузки из сети

swift
AsyncImage(url: URL(string: "https://example.com/photo.jpg")) { image in
    image
        .resizable()
        .scaledToFit()
} placeholder: {
    ProgressView()
}
.frame(width: 200, height: 200)

Плюсы и минусы

АспектОписание
SF Symbols✅ Бесплатные, векторные, огромный выбор
Dynamic Type✅ Автоматическое масштабирование
Accessibility✅ Автоматические описания
Кастомизация⚠️ Требует знания rendering modes
Сетевые изображения⚠️ Базовая поддержка через AsyncImage

Вопросы интервьюера

Q: Где найти все доступные SF Symbols?

Скачайте бесплатное приложение SF Symbols от Apple. Оно показывает все символы с поиском и возможностью копирования имени.

Q: Чем отличается .fit от .fill?

.fit гарантирует, что всё изображение видно (возможны пустые области). .fill заполняет весь контейнер (часть изображения может обрезаться).

Q: Как создать свой SF Symbol?

Экспортируйте шаблон из SF Symbols App, создайте SVG в векторном редакторе и импортируйте в Asset Catalog как Symbol Image Set.

Q: Почему frame() без resizable() не работает?

По умолчанию Image отображается в своём натуральном размере. resizable() делает изображение гибким для изменения размера.


Источники

Code Example 1: Loading images

❓ Какие способы загрузки изображений существуют в SwiftUI?

swift
Image(systemName: "star.fill")
 
Image("myPhoto")
 
Image("photo", bundle: .main)
 
Image(decorative: "background")
 
Image(uiImage: UIImage(named: "photo")!)

Code Example 2: SF Symbols sizing

❓ Как использовать SF Symbols и настроить их размер?

swift
struct SymbolsDemo: View {
    var body: some View {
        HStack(spacing: 20) {
            Image(systemName: "star.fill")
                .font(.caption)
 
            Image(systemName: "star.fill")
                .font(.title)
 
            Image(systemName: "star.fill")
                .font(.largeTitle)
 
            Image(systemName: "star.fill")
                .font(.system(size: 50))
        }
    }
}

Code Example 3: Colored SF Symbols

❓ Как изменить цвет SF Symbols?

swift
struct ColoredSymbols: View {
    var body: some View {
        HStack(spacing: 20) {
            Image(systemName: "heart.fill")
                .foregroundStyle(.red)
 
            Image(systemName: "square.stack.3d.up.fill")
                .symbolRenderingMode(.hierarchical)
                .foregroundStyle(.blue)
 
            Image(systemName: "person.crop.circle.badge.checkmark")
                .symbolRenderingMode(.palette)
                .foregroundStyle(.blue, .green)
 
            Image(systemName: "externaldrive.badge.icloud")
                .symbolRenderingMode(.multicolor)
        }
        .font(.largeTitle)
    }
}

Code Example 4: Image scaling

❓ Как правильно масштабировать изображения?

swift
struct ImageScaling: View {
    var body: some View {
        VStack(spacing: 20) {
            Image("photo")
                .frame(width: 100, height: 100)
 
            Image("photo")
                .resizable()
                .frame(width: 100, height: 100)
 
            Image("photo")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 100, height: 100)
 
            Image("photo")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .frame(width: 100, height: 100)
                .clipped()
        }
    }
}

Code Example 5: Circular avatar

❓ Как создать круглый аватар?

swift
struct Avatar: View {
    let imageName: String
    let size: CGFloat
 
    var body: some View {
        Image(imageName)
            .resizable()
            .scaledToFill()
            .frame(width: size, height: size)
            .clipShape(Circle())
            .overlay(
                Circle()
                    .stroke(Color.white, lineWidth: 2)
            )
            .shadow(radius: 3)
    }
}