Skip to main content

SwiftUI Cheatsheet

This is a concise cheatsheet for SwiftUI development. The original comments, tips, and examples are preserved; only Markdown structure and headings were added for readability.

Import

import SwiftUI

Text

We have a panel with modifiers at the right.

struct SomeView_1: View {
var body: some View {
Text("Some text")
.foregroundColor(.black)

// alternatives
.font(.body) // Aligns to system settings
.font(.system(
size: 24, // fixed
weight: .semibold,
design: .serif
))

// alternatives
.fontWeight(.bold)
.bold()

// alternatives
.underline()
.underline(true, color: Color.green)
//
.italic()
.strikethrough()
// Line spacing. Negative adds space at top
.baselineOffset(10.0)
.kerning(3.0)
.multilineTextAlignment(.leading)

// Text tries to fill all available space
.frame(width: 200, height: 100, alignment: .center)
// Specifies to much font can be scaled to fit in the frame
.minimumScaleFactor(0.1)

// to move text to the beginning of the frame
.frame(alignment: .leading)
}
}

Tip: Just start to type — framewihe -> it will be transformed to what you need

Shapes

struct SomeView_2: View {
var body: some View {
Circle()
// alternatives
.fill(.purple)
.foregroundColor(.pink)

// alternatives
.stroke()
.stroke(lineWidth: 4)
.stroke(Color.blue, lineWidth: 30)
.stroke(Color.orange, style: StrokeStyle(
lineWidth: 20,
lineCap: .butt,
dash: [10]
))
//

.frame(width: 100, height: 100)
// the whole circle
.trim(from: 0.0, to: 1.0)
}
}
struct SomeView_2n1: View {
var body: some View {
Ellipse()
.frame(width: 200, height: 100)
}
}
struct SomeView_3: View {
var body: some View {
// Fills the whole available place
Rectangle()
.fill(.blue)
.frame(width: 200, height: 100)
.cornerRadius(10)

RoundedRectangle(cornerRadius: 25.0)
// makes a slice of the shape
.trim(from: 0.4, to: 1.0)
.frame(width: 200, height: 100)
}
}
struct SomeView_4: View {
var body: some View {
// style can be circular / continuous
Capsule(style: .circular)
.fill(.cyan)
.frame(width: 200, height: 64)
}
}

Colors

struct SomeView_3: View {
var body: some View {
RoundedRectangle(cornerRadius: 25.0)

.fill(Color.red)
.fill(Color(<Select ColorLiteral))
// UIColor from UIKit
.fill(Color(UIColor.secondarySystemBackground))
.fill(Color("name_of_my_custom_color"))

.frame(width: 200, height: 100)

.shadow(radius: 10)
.shadow(
color: Color("CustomColor").opacity(0.3),
radius: 10,
x: 10,
y: -20
)
}
}

Gradients

struct SomeView_3: View {
var body: some View {
RoundedRectangle(cornerRadius: 25.0)
.fill(

LinearGradient(
gradient: Gradient(
colors: [Color.red, Color.blue]
),
startPoint: .leading,
endPoint: .trailing
)

RadialGradient(
gradient: Gradient(
colors: [Color.red, Color.blue]
),
center: .center,
startRadius: 5,
endRadius: 200
)

// Can use mixed area of the gradient
AngularGradient(
gradient: Gradient(
colors: [Color.red, Color.blue]
),
center: .center,
angle: .degrees(180)
)
)
}
}

Icons

struct SomeView_5: View {
var body: some View {
// From SF Symbols
Image(systemName: "heart")
// Specifies that we want the image to fill the frame
.resizable()
// No gradient
.foregroundColor(.pink)
// Changes the size of system icons
// alternatives
.font(.largeTitle)
.font(.system(size: 50))
//
.imageScale(.small)
.frame(width: 100, height: 100) // Doesn't scale the image but the box outside of it

// Multicolor icon
Image("person.fill.badge.plus")
// No turn off inheritance of a color
// before foregroundColor
.renderingMode(.original)
.foregroundColor(.pink)
}
}

Images

struct SomeView_6: View {
var body: some View {
// Exactly same name as in the Assets folder
Image("name-of-the-image")
.resizable()

// alternatives
.scaleToFit() // doesn't fill out the entire frame
.scaleToFill() // moves outside of the frame

.aspectRatio(contentMode: .fill)
.aspectRatio(contentMode: .fit)
//

.frame(width: 100, height: 100)

// alternatives
.clipped() // to trim the image after scaleToFill
.clipShape(Circle())
// if the size is 100x100
.cornerRadius(50)

// We can set renderingMode specially for the current image
// From the Assets page in the right panel
Image("name-of-the-image")
// If an image has transparent background and acts like an icon
// need to try svg
.renderingMode(.template)
.resizable()
.scaleToFit()
// in combination with renderingMode
// changes the color of the icon
.foregroundColor(.red)
}
}

Frame

By default, a frame has the size of the content.

struct SomeView_2n1: View {
var body: some View {
// Has its own frame
Text("Hello, World!")
// Additional frame
.frame(width: 200, height: 100, alignment: .topLeading)
.background(Color.red)

.frame(
// set the width as wide as possible
maxWidth: .infinity,
maxHeight: .infinity,
alignment: .leading
)
}
}

Background and Overlay

struct AboutBackground: View {
var body: some View {
Text("Hello, World!")
.background(

Color.red,

// Gradients

Circle()
.fill(Color.blue)
.frame(width: 200, height: 100)

)
// We can stack backgrounds on each other
.background(
Circle()
.fill(Color.pink)
.frame(width: 200, height: 100)
)
}
}
struct AboutOverlay: View {
var body: some View {
Circle()
.fill(Color.pink)
.frame(width: 200, height: 100)
.overlay(

Text("1")
.font(.largeTitle)
.foregroundColor(.white)

)
.background(
Circle()
.fill(Color.purple)
)
}
}
struct AboutOverlay2: View {
var body: some View {
Rectangle()
.fill(Color.pink)
.frame(width: 100, height: 100)
.overlay(
Rectangle()
.fill(Color.blue)
.frame(width: 50, height: 50),
// we can move objects according to each other
.alignment: .topLeading
)
.background(
Rectangle()
.fill(Color.purple)
.frame(width: 150, height: 150),
// we can move objects according to each other
.alignment: .bottomTrailing
)
}
}
struct GoodExample: View {
var body: some View {
Image(systemName: "heart.fill")
.font(.system(size: 40))
.foregroundColor(Color.white)
.background(
Circle()
.fill(
LinearGradient(
gradient: Gradient(colors: [Color.pink, Color.purple]),
startPoint: .topLeading,
endPoint: .bottomTrailing,
)
)
.frame(width: 100, height: 100)
.shadow(
color: Color.purple.opacity(0.3),
radius: 10,
x: 0.0,
y: 10
)
.overlay(
Circle()
.fill(Color.blue)
.frame(width: 35, height: 35)
.overlay(
Text("5")
.font(.headline)
.foregroundColor(.white)
)
, .alignment: .bottomTrailing
)
)
}
}

Stacks

  • For any stack elements try to move closer to the center
  • In VStack we align only horizontal gravity
  • In HStack we align only vertical gravity
  • In ZStack we align all directions gravity (.bottomTrailing)
struct Stacks: View {
var body: some View {
// Negative spacing makes things overlapping
// By default spacing: 8 / spacing: nil
VStack(alignment: .leading, spacing: 32) {
Rectangle()
.fill(.pink)
.frame(width: 200, height: 100)
.cornerRadius(10)

// thick gray line
Divider()

Rectangle()
.fill(.blue)
.frame(width: 200, height: 100)
.cornerRadius(10)
}
// By default (if no props) it's the size of children
// .frame()

HStack(alignment: .bottom) {

}
}
}

Tips:

  • Double-click on a bracket, it will find the closing bracket
  • Hold down the Cmd key and click the bracket, a context menu appears

Padding

struct SomeView_8: View {
var body: some View {
VStack {
Text("Hello, World")
}
// Default 6pt
.padding() // all edges

//

// Order is important
.background(.blue)
.padding()

//

// Only horizontal
.padding(.horizontal, 32)

// Only vertical
.padding(.vertical, 32)

.padding(.leading)
.padding(.trailing)
.padding(.top)
.padding(.bottom)
}
}

Spacers

struct SomeView_9: View {
var body: some View {
VStack {
// minimum size the spacer can shrink
// 8 is default
Spacer(minLength: 8)

Text("Spacers")

// Fill all the empty space
// Can specify height for HStack
// Can specify width for VStack
Spacer()

HStack {
Text("Something")

Spacer()
}
}
}
}

Initializers and Enums

enum Fruit {
case apple,
case orange
}

struct SomeViewInits: View {
convenience init(fruit: Fruit) {
// process fruit
}

let backgroundColor: Color = Color.red
let count: Int = 5

var body: some View {
VStack(spacing: 12) {
Text("\(count)")
Text("Apples")
}
.frame(width: 150, height: 150)
.background(backgroundColor)
.cornerRadius(10)
}
}

Loops

struct SomeView_10: View {
var body: some View {
VStack {
// Need to provide id
ForEach(0...10, id: \.self) { idx in
Text("Hello, \(index)")
}
}
}
}

Scrollable

struct SomeView_11: View {
var body: some View {
// horizontal axes
ScrollView(.horizontal, showsIndicators: false) {
HStack { // Check, maybe not required
ForEach(images, id: \.self) { image in
Image(image)
.resizable()
.frame(width: 64, height: 64)
.clipShape(Circle())
}
}
}
}
}
struct SomeView_11: View {
var images = []

var body: some View {
ScrollView {
Text("Featured on Uber Eats")
.font(.title2)
.fontWeight(.semibold)
.padding()

ForEach(images, id: \.self) { image in
VStack(alignment: .leading) {
Image(image)
.resizable()
.frame(width: 360, height: 150)
.cornerRadius(10)

VStack(alignment: leading) {
Text("Shoto")
.fontWeight(.semibold)

Text("Delivery Fee 0.99")
.foregroundColor(.gray)
}
.font(.subheading)
}
}
}
}
}
struct SomeView_11: View {
var body: some View {
// order of components
ScrollView {
// or VStack
LazyVStack {
ForEach(0..<100) { index in
Text()
}
}
}
}
}

Grids

struct SomeView_11: View {

let columns: [GridItem] = [
GridItem(.fixed(50), spacing: 8, alignment: nil),
// Takes available width
GridItem(.flexible(), spacing: 8, alignment: nil),
// Strange layout with slots
GridItem(.adaptive(minimum: 50, maximum: 150)),
]
var body: some View {
LazyVGrid(
columns: columns,
alignment: .center,
spacing: 6,
// If we have Sections
pinnedViews: [.sectionHeaders]
) {
Section(header: Text("Header")) {
ForEach(0..<100) { index in
Rectangle()
}
}
}
}
}

Safe Area

struct SomeView_11: View {

/*
Background — to ignore
User interactive — to keep in safe area
*/
var body: some View {
Text("Hello")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.red)
.edgesIgnoringSafeArea(.all)
}
}
struct SomeView_11: View {
var body: some View {
ZStack {
Color.blue
.edgesIgnoringSafeArea(.all)

VStack {
Text("Hello")
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}



}
}