請 AI 一步一步慢慢教,帶著初學者開發 iOS App — 以 10YearChallenge App 為例

彼得潘出了超過 200 道的 iOS App 作業,因此上課的同學們每天都可以開心地寫作業。

不過如果遇到以下三種情況,倒是可以考慮請聰明善良耐心的 AI 老師幫忙。

  • 作業想破頭寫不出來。
  • 已經完成作業,想請 AI 改作業。
  • 已經完成作業,想了解其它寫法。

ChatGPT,Notion AI & Cursor 都是不錯的 AI 老師。Cursor 目前串接 GPT-4,因此寫程式的功力還不錯。以下彼得潘以 10YearChallenge 為例,請 Cursor 一步一步慢慢教,帶著身為初學者的我們開發 iOS App。

  • 安裝 Cursor App。
  • 打開 Cursor App,按 cmd + l 輸入問題。
請一步一步慢慢教,列出一連串的步驟,教我用 storyboard,IBOutlet & IBAction 做出 10YearChallenge App。
10YearChallenge App 的功能如下。
1. 使用 date picker 選時間,顯示自己 2014 ~ 2023 的變化成長,一年一張照片。
2. date picker 設定最小 & 最大時間,讓時間的範圍為 2014 ~ 2023。
3. 使用 slider 選時間,顯示自己 2014 ~ 2023 的變化成長,一年一張照片。
4. slider 設定最小值為 2014,最大值為 2023。
5. slider 的旁邊有個 label 顯示年份。
6. 滑動 slider 時,slider 會停在整數的位置,比方滑到 2020.6 時會四捨五入到 2021。
7. 當 slider 滑動時,date picker 會更新。比方 slider 滑到 2020,date picker 會選到 2020。
8. 當 date picker 選時間時,slider 會更新。比方 date picker 選到 2020,slider 會滑到 2020。

ps: AI 回答到一半中斷時,請輸入 Continue writing請它繼續寫。

以下為 AI 的回答。

使用 storyboard 建立 UI

  1. 在 Xcode 中建立新的 project,選擇 Single View App。
  2. 在左側的專案導覽欄中,點擊 Main.storyboard。
  3. 在右側的工具欄中,選擇 Date Picker,拖曳到畫面中央。
  4. 在右側的工具欄中,選擇 Image View,拖曳到畫面中央。
  5. 在右側的工具欄中,選擇 Slider,拖曳到畫面下方。
  6. 在右側的工具欄中,選擇 Label,拖曳到 Slider 的旁邊。

設定 Date Picker

  1. 選擇 Date Picker,點擊右側的 Attributes inspector。
  2. 設定 Date Picker 的 Mode 為 Date。
  3. 設定 Date Picker 的 Minimum Date 為 2014 年 1 月 1 日。
  4. 設定 Date Picker 的 Maximum Date 為 2023 年 12 月 31 日。

設定 Slider

  1. 選擇 Slider,點擊右側的 Attributes inspector。
  2. 設定 Slider 的 Minimum Value 為 2014。
  3. 設定 Slider 的 Maximum Value 為 2023。

設定 Label

  1. 選擇 Label,點擊右側的 Attributes inspector。
  2. 設定 Label 的 Text 為 2014。
  3. 設定 Label 的 Alignment 為 Center。

連結 IBOutlet

  1. 在 ViewController.swift 中,宣告 IBOutlet。
  2. 在 Main.storyboard 中,選擇 Date Picker,點擊右側的 Connections inspector。
  3. 將 Date Picker 的 New Referencing Outlet 連結到 ViewController 的 datePicker。

4. 在 Main.storyboard 中,選擇 Image View,點擊右側的 Connections inspector。

5. 將 Image View 的 New Referencing Outlet 連結到 ViewController 的 imageView。

6. 在 Main.storyboard 中,選擇 Slider,點擊右側的 Connections inspector。

7. 將 Slider 的 New Referencing Outlet 連結到 ViewController 的 slider。

8. 在 Main.storyboard 中,選擇 Label,點擊右側的 Connections inspector。

9. 將 Label 的 New Referencing Outlet 連結到 ViewController 的 yearLabel。

連結 IBAction

在 ViewController.swift 中,宣告 IBAction。

@IBAction func datePickerChanged(_ sender: UIDatePicker) {
}

@IBAction func sliderChanged(_ sender: UISlider) {
}
  1. 在 Main.storyboard 中,選擇 Date Picker,點擊右側的 Connections inspector。
  2. 將 Date Picker 的 Value Changed 連結到 ViewController 的 datePickerChanged。
  3. 在 Main.storyboard 中,選擇 Slider,點擊右側的 Connections inspector。
  4. 將 Slider 的 Value Changed 連結到 ViewController 的 sliderChanged。

實作功能

  1. 在 ViewController.swift 中,實作 datePickerChanged 函式。
@IBAction func datePickerChanged(_ sender: UIDatePicker) {
let selectedYear = Calendar.current.component(.year, from: sender.date)
updateUI(year: selectedYear)
}

2. 在 ViewController.swift 中,實作 sliderChanged 函式。

@IBAction func sliderChanged(_ sender: UISlider) {
let roundedValue = round(sender.value)
sender.value = roundedValue
let selectedYear = Int(roundedValue)
updateUI(year: selectedYear)
}

3. 在 ViewController.swift 中,實作 updateUI 函式。

func updateUI(year: Int) {
yearLabel.text = "\(year)"
datePicker.date = Calendar.current.date(from: DateComponents(year: year))!
slider.value = Float(year)
imageView.image = UIImage(named:"image(year)")
}

初始化

在 ViewController.swift 中,實作 viewDidLoad 函式。

override func viewDidLoad() {
super.viewDidLoad()
let initialYear = 2014
updateUI(year: initialYear)
}

這樣就完成了 10YearChallenge App 的基本功能。現在,當您滑動 Slider 或選擇 Date Picker 時,應用程式將顯示對應年份的圖片,並更新 Label 和其他 UI 元素。請確保您的專案中有名為 “image2014”、”image2015" 等的圖片資源。

import UIKit

class ViewController: UIViewController {

@IBOutlet weak var datePicker: UIDatePicker!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var slider: UISlider!
@IBOutlet weak var yearLabel: UILabel!

override func viewDidLoad() {
super.viewDidLoad()
let initialYear = 2014
updateUI(year: initialYear)
}

@IBAction func datePickerChanged(_ sender: UIDatePicker) {
let selectedYear = Calendar.current.component(.year, from: sender.date)
updateUI(year: selectedYear)
}

@IBAction func sliderChanged(_ sender: UISlider) {
let roundedValue = round(sender.value)
sender.value = roundedValue
let selectedYear = Int(roundedValue)
updateUI(year: selectedYear)
}

func updateUI(year: Int) {
yearLabel.text = "\(year)"
datePicker.date = Calendar.current.date(from: DateComponents(year: year))!
slider.value = Float(year)
imageView.image = UIImage(named: "image\(year)")
}

}

請 AI 幫忙的注意事項

彼得潘實測 App 後發現功能完全正確,AI 成功地寫出 10YearChallenge App,而且過程中還耐心地講解每個步驟。

不過 AI 也不是完美的,所以麻煩它寫程式時請注意以下幾點。

  • AI 給出回答後,如果覺得他某個地方寫得不好,可以請他改進。請放心,他沒有心,不會傷心的。

ex: 請將圖片名字改成存在 array 的寫法,年份是 2014 ~ 2023。

class ViewController: UIViewController {

@IBOutlet weak var datePicker: UIDatePicker!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var slider: UISlider!
@IBOutlet weak var yearLabel: UILabel!

let imageNames = (2014...2023).map { "image\($0)" }
var currentYearIndex = 0

override func viewDidLoad() {
super.viewDidLoad()
updateUI(year: 2014)
}

@IBAction func datePickerChanged(_ sender: UIDatePicker) {
let selectedYear = Calendar.current.component(.year, from: sender.date)
updateUI(year: selectedYear)
}

@IBAction func sliderChanged(_ sender: UISlider) {
let roundedValue = round(sender.value)
sender.value = roundedValue
let selectedYear = Int(roundedValue)
updateUI(year: selectedYear)
}

func updateUI(year: Int) {
yearLabel.text = "\(year)"
datePicker.date = Calendar.current.date(from: DateComponents(year: year))!
slider.value = Float(year)
imageView.image = UIImage(named: imageNames[currentYearIndex])
}

}

首先,我們可以先將圖片名字存在一個 array 中,然後再新增一個變數 currentYearIndex 來代表目前顯示的圖片在 array 中的 index。接著在 updateUI 方法中,將 imageView.image 的值改成 UIImage(named: imageNames[currentYearIndex]) 即可。最後在 viewDidLoad 方法中呼叫 updateUI(year: 2014) 即可初始化畫面。

  • AI 可能寫錯,寫錯時我們可以自己修改,或是跟 AI 描述問題,請他再做修改。

剛剛加入圖片名字存在 array 的寫法後,程式出了問題,因此我們請 AI 再做修改。

ex: 程式有問題,currentYearIndex 一直維持 0。

看起來 currentYearIndex 的值一直都是 0,這應該是因為在 updateUI 方法中沒有更新 currentYearIndex 的值。我們可以在 updateUI 方法中加上以下程式碼來更新 currentYearIndex 的值:

if let index = imageNames.firstIndex(of: "image\(year)") {
currentYearIndex = index
}

這樣就可以讓 currentYearIndex 的值隨著年份的改變而更新了。

  • AI 給出回答後,看不懂也可以問她。雖然她不是人,你還是可以幻想她是溫柔的程式老師。

ex: 我看不懂 Calendar.current.component(.year, from: sender.date)。

Calendar.current.component(.year, from: sender.date) 是一个获取日期中年份的方法。在这个例子中,我们从 UIDatePicker 中获取了一个日期,然后使用 Calendar.current 获取当前日历,最后使用 component 方法获取日期中的年份。这个方法返回一个 Int 类型的值,表示日期中的年份。

  • AI 給出回答後,可以請他加入更多功能。

ex: 請在剛剛的 storyboard 加入一個隨機的 button,點選後會隨機某一年的圖片。

在 storyboard 中加入一個 button,並且在 ViewController 中加入以下程式碼:

@IBAction func randomButtonPressed (_ sender: UIButton) {
let randomYear = Int.random(in: 2014...2023)
updateUI (year: randomYear)
}

然後在 storyboard 中將 button 的 action 設定 randomButtonPressed。 這樣點選 button 後就會隨機顯示某一年的圖片了。

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com