SwiftUI series 12: Creating a Thumbnail Maker App in SwiftUI and Add Save to Photo Library Functionality

In this tutorial, we'll build a Thumbnail Maker app using SwiftUI that allows users to select images, add text overlays, and save the resulting thumbnails to their photo library. This app is perfect for content creators who need to quickly create thumbnails for their videos or social media posts.

Features

  • Image selection from photo library
  • Text overlay with customizable input
  • High-quality thumbnail generation
  • Save functionality to photo library
  • Clean and intuitive UI

Prerequisites

  • Xcode 15 or later
  • iOS 17 or later
  • Basic knowledge of SwiftUI

Step 1: Setting Up the Project

First, let's look at the main structure and state variables we need:

struct ContentView: View {
    @State private var selectedImage: UIImage?
    @State private var imageSelection: PhotosPickerItem?
    @State private var overlayText: String = ""
    @State private var showingSaveAlert = false
    @State private var saveError: String?
    @FocusState private var isFocused: Bool
}

Step 2: Building the User Interface

The UI consists of three main components:

  1. Image picker button
  2. Image display with text overlay
  3. Text input field

Here's how we implement the image picker:

PhotosPicker(selection: $imageSelection,
            matching: .images) {
    Text("Select Image")
        .padding()
        .background(Color.blue)
        .foregroundColor(.white)
        .cornerRadius(8)
}

Step 3: Implementing the Image Display

The image display section includes both the selected image and the text overlay:

if let selectedImage {
    ZStack {
        Image(uiImage: selectedImage)
            .resizable()
            .scaledToFit()
            .frame(maxHeight: 300)

        Text(overlayText)
            .font(.system(size: 32, weight: .bold))
            .foregroundColor(.white)
            .shadow(color: .black, radius: 3, x: 1, y: 1)
            .multilineTextAlignment(.center)
            .padding()
    }
}

Step 4: Adding Text Input

The text input field is implemented using TextEditor:

TextEditor(text: $overlayText)
    .frame(height: 100)
    .padding(4)
    .overlay(
        RoundedRectangle(cornerRadius: 8)
            .stroke(Color.gray.opacity(0.2), lineWidth: 1)
    )
    .padding(.horizontal)

Step 5: Implementing Save Functionality

The save functionality uses ImageRenderer to create high-quality thumbnails:

private func saveImageWithOverlay() {
    guard let selectedImage else { return }

    let aspectRatio = selectedImage.size.width / selectedImage.size.height
    let renderHeight = 1024 / aspectRatio

    let renderer = ImageRenderer(content: 
        ZStack {
            Image(uiImage: selectedImage)
                .resizable()
                .scaledToFit()

            Text(overlayText)
                .font(.system(size: 96, weight: .bold))
                .foregroundColor(.white)
                .shadow(color: .black, radius: 3, x: 1, y: 1)
        }
        .frame(width: 1024, height: renderHeight)
    )
}

Key Features Explained

  1. Image Selection: We use PhotosPicker for easy image selection from the photo library.
  2. Text Overlay: The text overlay uses a shadow effect for better visibility on any background.
  3. High-Quality Output: The app generates 1024px wide images while maintaining the aspect ratio.
  4. Error Handling: Comprehensive error handling with user feedback through alerts.