App-Dev World

I'm a new iOS app developer. I'm going to record my programming learning process here, mainly in Swift language. Hope we can help each other:)

View on GitHub
27 January 2026

SwiftUI Fundamentals

by Neoren

History

Main features

声明式界面构建

状态变化驱动视图更新

动画支持

视图组合与复用

自动布局适配

触摸和手势

和UIKit的兼容性

学习资源

SwiftUI Pathway

设计最合适的视图

Take a structured approach to design

Plan for navigation

Dive into data

SwiftUI essentials

Basic protocols

Important components

SwiftUI elements

Basic views

// Text(_:style:) displays a localized date or time
Text("Hello, world!")
Spacer()
Divider()
Image(systemName: "globe"); Image(imageName)
Button("Roll") {}; Button("Remove Dice", systemImage: "minus.circle.fill") {}; Button {} label: {}; Button(action:) {}
ContentUnavailableView("no movies", systemImage: "film.stack"); ContentUnavailableView { Label("no friends", systemImage:"") }
// TextField(_ titleKey: LocalizedStringKey, text: Binding<String>)
TextField("Add Name", text: $nameToAdd)
	.autocorrectionDisabled()
	.onSubmit {
    Names.append(nameToAdd)
    nameToAdd = ""
  }
// Toggle(_ titleKey: LocalizedStringKey, isOn: Binding<Bool>)
// DatePicker(selection: Binding<Date>, label: () -> View)
ColorPicker("color", selection: $colors[0])
Picker("Favorite Movie", selection: $friend.favoriteMovie) {}
NavigationLink { MovieDetail(movie: movie) } label: { Text(movie.title) }
// NavigationLink(_ title: StringProtocol, destination: () -> View)
ToolbarItem(placement: .navigationBarTrailing) { EditButton() }
// ToolbarItem(content: () -> View)
Slider(value: $depth, in: 0...50) { Text("Depth") }
RoundedRectangle(cornerRadius: 17)
Tab("Friends", systemName: "person.and.person") { Text("Friends") }
// 一组动态子视图
ForEach(1numberOfDice, id: \.description) { _ in DiceView() }
ForEach(names, id: \.description) { name in Text(name) }
ForEach(movies) { movie in } //Movie: Identifiable
ForEach($players) { $player in TextField("Name", text: $player.name) }

Container views

// 布局容器
VStack {}; VStack(alignment: .leading, spacing: 20) {} ; HStack {}; ZStack {}
Grid {
  GridRow {}
  GridRow {}
}

// 功能容器
ScrollView(.horizontal) {}
List {}
TabView {}
	.tabViewStyle(.page)
NavigationStack {}
NavigationSplitView {} detail: {}
Group {}  // Useful for wrapping conditions & apply modifiers to all group
Section("Favorited by") {}

Modifiers

/* Nature of modifiers:
1) Most modifiers are methods of the extended View protocol
2) These modifiers typically return a new view that wraps the original view, using some View as return type
3) This design allows us to chain multiple modifiers
4) We can create our own modifiers
5) Other modifiers can be methods of specific view type */

.imageScale(.large)
.padding(); .padding(17); .padding(.horizontal, 17); .padding([.top, .leading], 17); .padding(EdgeInsets(top: 17, leading: 18, bottom: 16, trailing: 678))
.background(.purple, in: RoundedRectangle(cornerRadius: 17)); .background(Gradient(colors: gradientColors)); .background(.appBackground); .background(.bar); .background {}
.shadow(radius: 17); .shadow(color: .gray, radius: 17)
.foregroundStyle(.orange); .foregroundStyle(.tint); .foregroundStyle(.black, .white) // 主要前景、次要前景
.font(.headline); .font(.system(size: 78)); .font(.largeTitle.lowercaseSmallCaps())
.fontWeight(.semibold); .fontDesign(.monospaced); .fontWidth(.compressed)
.multilineTextAlignment(.center)
.border(.purple, width: 1.7)
.resizable()
.frame(width: 170, height: 170); .frame(maxWidth: 170, maxHeight: 170); .frame(maxHeight: .infinity); .frame(maxWidth: .infinity, alignment: .trailing)
.overlay(alignment: .topleading) {} // 闭包有结果构建器@ViewBuilder
.rotationEffect(.degrees(180))
.tabViewStyle(.page)
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.disabled(numberOfDice == 1)
.aspectRatio(1, contentMode: .fit)
.labelStyle(.iconOnly)
.tint(.white)
.symbolRenderingMode(.multicolor)
.autocorrectionDisabled()
.bold(); .bold(true)
.clipShape(RoundedRectangle(cornerRadius: 8))
// .focused(_ condition: FocusState<Bool>.Binding)
.focused($isTextFieldFocused)
.onSubmit {}
.onAppear {} // 不会因为body重算而触发,它只关心视图是否第一次变成可见
.contentShape(Rectangle())
.onTapGesture {}
.navigationTitle("Birthdays")
.navigationBarTitleDisplayMode(.inline)
.safeAreaInset(edge: .bottom) {}
.textFieldStyle(.roundedBorder)
.modelContainer(for: Item.self)
.gesture(
	DragGesture() // 遵循Gesture协议
  	.onChanged { value in
      // 变更状态,闭包被不停回调
    }
 )
.tabItem { Label("Movies", systemImage: "film.stack") }
// .onDelete(perform: Optional<(IndexSet) -> Void>)
.onDelete(perform: deleteItems)
.onMove { indices, newOffset in
  players.move(fromOffsets: indices, toOffset: newOffset)
}
// @ToolbarContentBuilder (result builder)
.toolbar {
  ToolbarItem(placement: ...) { ... }
  ToolbarItem(placement: ...) { ... }
}
.toolbar {
  Button() // 这里直接采用视图是应用了语法糖
}
// @State private var newMovie: Movie?  其中Movie遵循Identifiable
.sheet(item: $newMovie) { movie in NavigationStack {} }
.tag(8) // 给视图附加一个标记值
.searchable(text: $searchText)
.labelsHidden()
.stroke(lineWidth: 17); .strokeBorder(lineWidth: 17)
.offset(y: -170)
.gridColumnAlignment(.leading)
.controlSize(.large)
.accessibilityElement(children: .ignore)
.accessibilityLabel("time remaining")
.accessibilityValue("10 minutes")

Some Explanations

tags: iOS - SwiftUI