# IOS
## 各種連結
+ [我的程式碼](https://github.com/Popcorn0924-0924/IOS-3-MARVEL/tree/main/00857202_3)
+ [ch10](https://drive.google.com/file/d/1Eclomt3FfBF887oUcvTB2D0GVHajJbD8/view)
+ [ch9](https://trello.com/c/WTTQiSbU/29-%E4%BD%BF%E7%94%A8-swiftui-%E5%89%B5%E4%BD%9C-crud-%E7%B4%80%E9%8C%84app)
+ [binding](https://drive.google.com/file/d/1wDVGyRbEefaFfzeJ1fykXkuihBV13aYN/view)
+ [random](https://medium.com/%E6%B5%B7%E5%A4%A7-ios-app-%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/bonus-%E4%BA%82%E6%95%B8%E7%B7%B4%E7%BF%92%E4%B9%8B%E5%88%B0%E5%BA%95%E8%A6%81%E5%B9%B9%E5%98%9B-29063ff8b5b4)
+ [動畫](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E7%9A%84-animation-%E5%8B%95%E7%95%AB-2f8eb72d2756)
+ [SwiftUI 選時間的歲月神偷 — DatePicker](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E9%81%B8%E6%99%82%E9%96%93%E7%9A%84%E6%AD%B2%E6%9C%88%E7%A5%9E%E5%81%B7-datepicker-22491c08bc93)
+ [SwiftUI 選擇項目的 Picker & 我要選李白](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E9%81%B8%E6%93%87%E9%A0%85%E7%9B%AE%E7%9A%84-picker-%E6%88%91%E8%A6%81%E9%81%B8%E6%9D%8E%E7%99%BD-aabd95adc601)
+ [SwiftUI 設計 UI 元件樣式的各種方法 ](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E8%A8%AD%E8%A8%88-ui-%E5%85%83%E4%BB%B6%E6%A8%A3%E5%BC%8F%E7%9A%84%E5%90%84%E7%A8%AE%E6%96%B9%E6%B3%95-5350da28bc89)
+ [SwiftUI 擅長展開 & 折疊的 DisclosureGroup](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E6%93%85%E9%95%B7%E5%B1%95%E9%96%8B-%E6%8A%98%E7%96%8A%E7%9A%84-disclosuregroup-8a41010fb4d9)
+ [利用 SwiftUI 繪製同時填滿顏色和線條的形狀](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E5%88%A9%E7%94%A8-swiftui-%E7%B9%AA%E8%A3%BD%E5%90%8C%E6%99%82%E5%A1%AB%E6%BB%BF%E9%A1%8F%E8%89%B2%E5%92%8C%E7%B7%9A%E6%A2%9D%E7%9A%84%E5%BD%A2%E7%8B%80-86f0faee556d)
+ [SwiftUI 調整元件位置的幾種方法](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E8%AA%BF%E6%95%B4%E5%85%83%E4%BB%B6%E4%BD%8D%E7%BD%AE%E7%9A%84%E5%B9%BE%E7%A8%AE%E6%96%B9%E6%B3%95-f925e884cfd1)
+ [利用 NavigationView & NavigationLink 切換頁面](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E5%88%A9%E7%94%A8-navigationview-navigationlink-%E5%88%87%E6%8F%9B%E9%A0%81%E9%9D%A2-3a062833230f)
+ [利用 SwiftUI 的 PageTabViewStyle 實現分頁照片瀏覽](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E5%88%A9%E7%94%A8-swiftui-%E7%9A%84-pagetabviewstyle-%E5%AF%A6%E7%8F%BE%E5%88%86%E9%A0%81%E7%85%A7%E7%89%87%E7%80%8F%E8%A6%BD-cf307285ef20)
+ [格子狀排列的 LazyVGrid & LazyHGrid](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E6%A0%BC%E5%AD%90%E7%8B%80%E6%8E%92%E5%88%97%E7%9A%84-lazyvgrid-lazyhgrid-338a21a7afc3)
+ [link](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E9%BB%9E%E9%81%B8%E6%89%93%E9%96%8B%E9%80%A3%E7%B5%90%E7%9A%84-link-%E6%8C%89%E9%88%95-2b0c382f5468)
+ [讓 SwiftUI List 的 row 有多個可點選的 NavigationLink](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E8%AE%93-swiftui-list-%E7%9A%84-row-%E6%9C%89%E5%A4%9A%E5%80%8B-navigationlink-64e9b8ca6751)
+ [SwiftUI 讓 scaledToFill 圖片等於螢幕寬度的方法](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E8%AE%93%E5%9C%96%E7%89%87%E7%AD%89%E6%96%BC%E8%9E%A2%E5%B9%95%E5%AF%AC%E5%BA%A6-%E8%A8%AD%E5%AE%9A%E6%AF%94%E4%BE%8B%E7%9A%84%E6%96%B9%E6%B3%95-9e4ef427585e)
+ [SwiftUI 維持元件理想尺寸的 fixedSize (修正文字切掉問題)](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E7%B6%AD%E6%8C%81%E5%85%83%E4%BB%B6%E7%90%86%E6%83%B3%E5%B0%BA%E5%AF%B8%E7%9A%84-fixedsize-bce6d2442f92)
+ [利用 Stack,Rectangle & overlay 實現元件一樣大,固定比例 & 照片牆](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E5%88%A9%E7%94%A8-stack-rectangle-overlay-%E5%AF%A6%E7%8F%BE%E5%85%83%E4%BB%B6%E4%B8%80%E6%A8%A3%E5%A4%A7-%E5%9B%BA%E5%AE%9A%E6%AF%94%E4%BE%8B-%E7%85%A7%E7%89%87%E7%89%86-dfe0923983aa)
+ [SwiftUI 裁切形狀的 clipShape & mask](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-%E8%A3%81%E5%88%87%E5%BD%A2%E7%8B%80%E7%9A%84-clipshape-mask-4fc49b34141)
+ [調整元件階層的 SwiftUI zIndex
](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E8%AA%BF%E6%95%B4%E5%85%83%E4%BB%B6%E9%9A%8E%E5%B1%A4%E7%9A%84-swiftui-zindex-72c0c6fc5b1a)
+ [用狀態設計 SwiftUI 畫面 — 認識 @State property,binding & Toggle](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E7%94%A8%E7%8B%80%E6%85%8B%E8%A8%AD%E8%A8%88-swiftui-%E7%95%AB%E9%9D%A2-%E8%AA%8D%E8%AD%98-state-property-binding-27fea6885ead)
+ [fullScreenCover()](https://www.hackingwithswift.com/quick-start/swiftui/how-to-present-a-full-screen-modal-view-using-fullscreencover)
+ [SwiftUI List Row 的 button 點選](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/swiftui-list-row-%E7%9A%84-button-%E9%BB%9E%E9%81%B8-af13892c95ca)
+ [plist 設定 iOS App 的 Launch screen](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E5%95%8F%E9%A1%8C%E8%A7%A3%E7%AD%94%E9%9B%86/%E4%BD%BF%E7%94%A8-plist-%E8%A8%AD%E5%AE%9A-ios-app-%E7%9A%84-launch-screen-a1781a6217f)
## 程式
> [color=#ed6f21]程式碼解釋
:::spoiler
1. 建個列表
```
@ObservedObject var timeData = MyTimeData()//綁定MyTimeData(),若MyTimeData()改變列表跟著變
@State private var showEditMyTime = false//修改的按鈕
```
2.timeData.myTimes為MyTimeData中第13 行
Published var myTimes = [MyTime]()//綁struct
```
ForEach(timeData.myTimes) { (mytime) in
NavigationLink(destination: MyTimeEditor(myTimesData: self.timeData, editMyTime: mytime)) {
MyTimeRow(myTime: mytime)//型態
```
3.點右上+可眺新增畫面(sheet)
```
.navigationBarItems(leading: EditButton() , trailing: Button(action: {
self.showEditMyTime = true
}) {
Image(systemName: "plus.circle.fill")
})
.sheet(isPresented: $showEditMyTime) {
NavigationView {
MyTimeEditor(myTimesData: self.timeData)
}
```
4.MyTimeEditor
![](https://i.imgur.com/n8A7PFb.png)
+ @Environment(\.presentationMode) var presentationMode & self.presentationMode.wrappedValue.dismiss()可返回
```
@Environment(\.presentationMode) var presentationMode
var myTimesData: MyTimeData
@State private var name = ""
@State private var course = ""
@State private var type = ""
@State private var date = Date()
@State private var time = 0
@State private var isDone = false
var editMyTime: MyTime?
```
5.MyTimeEditor
![](https://i.imgur.com/QGFTrlM.png)
![](https://i.imgur.com/JB1Lcwv.png)
```
.navigationBarItems(trailing: Button("Save") {
let myTime = MyTime(name: self.name, course: self.course, type: self.type, date: self.dateFormatter.string(from: self.date), time: self.time, isDone: self.isDone)
if let editMyTime = self.editMyTime {
let index = self.myTimesData.myTimes.firstIndex {
$0.id == editMyTime.id
}!
self.myTimesData.myTimes[index] = myTime
} else {
self.myTimesData.myTimes.insert(myTime, at: 0)
}
self.presentationMode.wrappedValue.dismiss()
})
```
:::
> [color=#ed6f21]重要(在第七章Data binding)
:::spoiler
https://drive.google.com/file/d/1wDVGyRbEefaFfzeJ1fykXkuihBV13aYN/view
+ date
[10years程式碼](https://github.com/hannn0919/2020_iOS_bonus2/blob/master/2020_iOS_bonus2/selfView.swift)
[10years程式碼](https://github.com/00757001/00757001-10years/blob/main/00757001-10years/ContentView.swift)
```
struct TenYearImage: View {
let width: CGFloat
let selectDate: Date
let brightnessAmount: Double
var year: Int {
return Calendar.current.component(.year, from: selectDate)
}
var body: some View {
Image("peter\(year)")
.resizable()
.scaledToFill()
.frame(width: width, height: width / 4 * 3)
.clipped()
.brightness(brightnessAmount)
}
}
```
+ slider
```
struct BrightnessSlider: View {
@Binding var brightnessAmount: Double
var body: some View {
HStack {
Text("亮度")
Slider(value: $brightnessAmount, in: 0...1,
minimumValueLabel: Image(systemName:
"sun.max.fill").imageScale(.small), maximumValueLabel:
Image(systemName: "sun.max.fill").imageScale(.large)) {
Text("")
}
}
}
}
```
+ WheelPickerStyle SegmentedPickerStyle
```
```
+ 動態顯示的 List / Form 欄位
+![](https://i.imgur.com/UK743Xl.png)
```
struct ContentView: View {
@State private var buyPhone = true
@State private var selectPhone = "iPhone 11 Pro Max"
let phones = ["iPhone 11 Pro Max", "iPhone 11 Pro", "iPhone 11"]
var body: some View {
Form {
Toggle("開發 iOS App 要買 iPhone 嗎", isOn: $buyPhone)
if buyPhone {
VStack(alignment: .leading) {
Text("我要買")
Picker("買 iPhone", selection: $selectPhone) {
ForEach(phones, id: \.self) { (phone) in
Text(phone)
}
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
}
}
```
+ sheet
```
struct ContentView: View {
@State private var showSecondPage = false
var body: some View {
Button("show second page") {
showSecondPage = true
}
.sheet(isPresented: $showSecondPage) {
SecondView(showSecondPage: self.
$showSecondPage)
}
}
}
struct SecondView: View {
@Binding var showSecondPage: Bool
var body: some View {
Button("close") {
showSecondPage = false
}
}
}
struct SecondView_Previews: PreviewProvider {
static var previews: some View {
SecondView(showSecondPage: .constant(true))
}
}
```
:::
> [color=#ed6f21]重要(在第九章CRUD App)
:::spoiler
[老師參考](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84%E8%A9%A6%E7%85%89-%E5%8B%87%E8%80%85%E7%9A%84-100-%E9%81%93-swift-ios-app-%E8%AC%8E%E9%A1%8C/90-%E4%BD%BF%E7%94%A8-swiftui-%E5%89%B5%E4%BD%9C-crud-%E7%B4%80%E9%8C%84app-2fcbf20088d2)
[學姊參考](https://medium.com/%E6%B5%B7%E5%A4%A7-ios-app-%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88/crud%E7%B4%80%E9%8C%84-%E6%99%82%E9%96%93%E7%9A%84%E6%94%AF%E9%85%8D%E8%80%85-244ecf8ce887)
+ 以 @Published 決定哪些 property 變化時要通知畫面更新
```
class LoversData: ObservableObject {
@Published var lovers = [Lover]()
}
宣告 lovers 時加上 @Published,
代表 lovers 有變化時會通知觀察 LoversData 的 view,
觀察 LoversData 的 view 將更新畫面
```
+ ToolbarItem
```
.toolbar(content: {
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: {
}, label: {
Image(systemName: "plus.circle.fill")
})
}
})
```
+ editor
```
struct LoverEditor: View {
@State private var name = ""
@State private var weight = 30
@State private var trueHeart = true
var body: some View {
NavigationView {
Form {
TextField("名字", text: $name)
Stepper("體重 \(weight)", value: $weight, in: 30...100)
Toggle("真心", isOn: $trueHeart)
}
.navigationBarTitle("Add new lover")
.toolbar(content: {
ToolbarItem {
Button("Save") {
}
}
})
}
}
}
```
宣告
:::
> [color=#ed6f21]算數(在第二章程式親密接觸不重要啦)
:::spoiler
https://drive.google.com/file/d/1JKODOKSRg_2XGmobLE6wOt1-5S8TGmfy/view
```
func addNumber(startNumber:Int, endNumber:Int) -> Int {
var sum = 0
sum = startNumber + endNumber
return sum
}
var sum1 = addNumber(startNumber:1, endNumber: 100)
var sum2 = addNumber(startNumber:200, endNumber: 300)
var sum3 = sum1 + sum2
```
因為 List 比較適合顯示內容,Form 比較適合呈現輸入的表單
:::
> [color=#ed6f21]圖(在第三章初體驗&繪圖不重要啦)
:::spoiler
https://drive.google.com/file/d/1ELMpwksl8EZji6mNIOSS3rE2KGEsq-Y7/view
```
struct ContentView: View {
var body: some View {
Image("Death on the Nile")
.resizable()
.scaledToFill()
.frame(width: 300, height: 300)
.background(Color.black)
.clipShape(Circle())
.shadow(radius: 10)
}
}
```
```
ZStack {
德國國旗 Path(CGRect(x: 10, y: 10, width: 200,
height: 50))
.fill(Color(red: 0, green: 0, blue: 0))
Path(CGRect(x: 10, y: 60, width: 200,
height: 50))
.fill(Color(red: 1, green: 0, blue: 0))
Path(CGRect(x: 10, y: 110, width: 200,
height: 50))
.fill(Color(red: 1, green: 1, blue: 0))
}
```
```
VStack {
Circle()
.frame(width: 200, height: 200)
Ellipse()
.frame(width: 200, height: 100)
Capsule()
.frame(width: 200, height: 100)
RoundedRectangle(cornerRadius: 30)
.frame(width: 200, height: 100)
}
```
```
struct ContentView: View {
var body: some View {
Path { (path) in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 20, y: 300))
path.addLine(to: CGPoint(x: 300, y: 300))
}
.fill(Color(red: 1, green: 0, blue: 0))
}
}
```
```
VStack {
Path(ellipseIn: CGRect(x: 10, y: 10, width: 100,
height: 100))
Path(ellipseIn: CGRect(x: 10, y: 130, width: 200,
height: 100))
Path(roundedRect: CGRect(x: 10, y: 260, width: 200,
height: 100), cornerRadius: 20)
}
```
```
//曲線
Path { (path) in
path.move(to: CGPoint(x: 157, y: 68))
path.addQuadCurve(to: CGPoint(x: 89, y: 56), control:
CGPoint(x: 139, y: 34))
path.addQuadCurve(to: CGPoint(x: 75, y: 56), control:
CGPoint(x: 82, y: 57))
path.addQuadCurve(to: CGPoint(x: 13, y: 66), control:
CGPoint(x: 35, y: 37))
path.addQuadCurve(to: CGPoint(x: 0, y: 109), control:
CGPoint(x: 0, y: 82))
path.addQuadCurve(to: CGPoint(x: 43, y: 197), control:
CGPoint(x: 1, y: 169))
}
.stroke()
```
```
struct ice: Shape {
func path(in rect: CGRect) -> Path {
Path{(path) in
path.move(to:CGPoint(x: 300, y: 124))
path.addLine(to:CGPoint(x: 270, y: 124))
path.addLine(to:CGPoint(x: 265, y: 154))
path.addLine(to:CGPoint(x: 295, y: 150))
path.addLine(to:CGPoint(x: 300, y: 124))
}
}
}
Group{
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 300, height: 450, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 300, height: 350, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 270, height: 300, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 200, height: 440, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 300, height: 350, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 370, height: 420, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 100, height: 490, alignment: .center)
ice().stroke(Color(red: 230/255, green: 230/255, blue: 230/255),lineWidth:6)
.frame(width: 100, height: 360, alignment: .center)
}
```
:::
> [color=#ed6f21]換頁(button)
:::spoiler
leading & trailing
- 語言順序為由左到右時,leading 為左,trailing
為右
top & bottom
- top 為從上,bottom置底
VStack:垂直
HStack:水平
HStack:重疊
```
struct ContentView: View {
var body: some View {
VStack(alignment: .leading, spacing: 50) {
Image("pic")
.resizable()
.scaledToFill()
.frame(width: 200.0, height: 100.0)
.clipped()
Text("我要一步一步學App")
.background(Color.yellow)
}
.frame(width: 400)
.background(Color.green)
}
}
```
NavigationView
```
NavigationView {
VStack {
NavigationLink(destination: RightPersonView()) {
Text("對的時間點")
}
Image(systemName: "clock")
.resizable()
.scaledToFit()
.frame(width: 200, height: 200)
}
.navigationTitle("那個人是你嗎")
}
```
tab
```
struct AppView: View {
var body: some View {
TabView {
SongList()
.tabItem {
Image(systemName: "music.house.fill")
Text("情歌")
}
ContentView()
.tabItem {
Image(systemName: "info.circle.fill")
Text("About")
}
.accentColor(.orange)
}
}
}
```
滑動分頁(各種聯結有利用 SwiftUI 的 PageTabViewStyle 實現分頁照片瀏覽
![](https://i.imgur.com/Wu03XVV.png)
```
struct ContentView: View {
@State private var currentPage = 0
var body: some View {
VStack {
Text("哈利波特在第\(currentPage+1)頁")
TabView(selection: $currentPage) {
ForEach(1..<8) { (index) in
Image("harry\(index)")
.resizable()
.scaledToFit()
}
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
}
}
}
```
按按鈕分頁
![](https://i.imgur.com/VrBAI4k.png)
```
struct ContentView: View {
@State private var currentPage = 0
var body: some View {
VStack {
Text("哈利波特在第\(currentPage+1)頁")
Button(action: {
currentPage = (currentPage + 1) % 7
}, label: {
Image(systemName: "arrow.right.circle.fill")
.resizable()
.frame(width: 40, height: 40)
})
TabView(selection: $currentPage) {
ForEach(1..<8) { (index) in
Image("harry\(index)")
.resizable()
.scaledToFit()
}
}
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
}
}
}
```
捲動的 scroll view預設上下捲動
```
struct DemoView: View {
var body: some View {
ScrollView {
Color.yellow
.frame(height: 200)
Color.yellow
.frame(height: 200)
Color.yellow
.frame(height: 200)
Color.yellow
.frame(height: 200)
Color.yellow
.frame(height: 200)
}
}
}
```
水平捲動
```
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 20) {
Image("peter0")
.resizable()
.scaledToFill()
.frame(width: 200)
.clipped()
Image("peter1")
.resizable()
.scaledToFill()
.frame(width: 200)
.clipped()
Image("peter2")
.resizable()
.scaledToFill()
.frame(width: 200)
.clipped()
}
.frame(height: 200)
.padding(.horizontal, 20)
}
```
+ sheet
```
struct ContentView: View {
@State private var showSecondPage = false
var body: some View {
Button("show second page") {
showSecondPage = true
}
.sheet(isPresented: $showSecondPage) {
SecondView(showSecondPage: self.
$showSecondPage)
}
}
}
將
```
:::
> [color=#ed6f21]list(在第四章畫面設計ex 圖的分布怎麼放&list)
:::spoiler
https://drive.google.com/file/d/1QntgNpR5XFK2frMxDESAZB540xaiUGpU/view
![](https://i.imgur.com/dpIzh7u.png)
:::
> [color=#ed6f21]其他()
:::spoiler
多行捲動文字的 TextEditor
```
struct ContentView: View {
var body: some View {
TextEditor(text: .constant("""
摘一顆蘋果 等你從門前經過
送到你的手中幫你解渴
像夏天的可樂 像冬天的可可
你是對的時間對的角色
已經約定過 一起過下個週末
你的小小情緒對我來說
我也不知為何 傷口還沒癒合
你就這樣闖進我的心窩
"""
))
.accentColor(.clear)
.frame(width: 200, height: 200)
}
}
```
動畫(第五章)
```
struct ContentView: View {
@State private var show = false
var body: some View {
VStack {
if show {
Image("蒙娜麗莎")
.transition(.opacity)
}
}
.animation(.easeInOut(duration: 5))
.onAppear {
self.show = true
}
}
}
```
點選 button 出現 / 消失
```
struct ContentView: View {
@State private var show = false
var body: some View {
VStack {
Button(show ? "hide" : "show") {
self.show.toggle()
}
if show {
Image("蒙娜麗莎")
.transition(.opacity)
} else {
Image("蒙娜麗莎")
.hidden()
}
}
.animation(.easeInOut(duration: 5))
}
}
圖片不顯示時依然佔著空間
```
[**?!**](https://medium.com/%E5%BD%BC%E5%BE%97%E6%BD%98%E7%9A%84-swift-ios-app-%E9%96%8B%E7%99%BC%E6%95%99%E5%AE%A4/%E7%B0%A1%E6%98%93%E8%AA%AA%E6%98%8Eswift-4-optional-7da19051e835)
[**?!2**](https://www.appcoda.com.tw/swift-optional-intro/)
?裝在盒子裡
![](https://i.imgur.com/o6hAkP7.png)
!解包裝
![](https://i.imgur.com/TilDHIl.png)
??
![](https://i.imgur.com/NgPP78e.png)
![](https://i.imgur.com/gqScnEO.png)
![](https://i.imgur.com/BmW3EBF.png)
![](https://i.imgur.com/Jj0ac2n.png)
:::
> [color=#ed6f21]考古
:::spoiler
:::