按照慣例幫各位畫這30天的重點
(趁機靠北一下,為什麼鐵人賽的文章列表10篇就分頁了,至少一次要能看30篇吧,Server loading有這麼重嗎...每次看個文章都要在那邊切來切去)

Modifier,就是在View後面會有個.xxx的function,例如.padding()請把專案的最低支援版本改成iOS15
記得要勾rootViewController

要注意順序| Flutter | SwiftUI |
|---|---|
| Padding | .padding |
| SizedBox | .frame |
| Align | .frame |
| Positioned | .offset |
| (Widget property) | .foregroundColor |
| Container color | .background |
| Container decoration | .border |
一定要用else包起來
edgesIgnoringSafeArea([])
| Flutter | SwiftUI |
|---|---|
| Column | VStack |
| Row | HStack |
| Stack | ZStack/.overlay() |

| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| TextView | UILabel | Text | Text |
.resizable()
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| ImageView | UIImageView | Image | Image |
| Bitmap | UIImage | ImageProvider | - |
| ScaleType | UIViewContentMode | BoxFit | ContentMode |
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| Button | UIButton | RawMaterialButton | Button |
| (尚未研究) | UITapGestureRecognizer | GestureDetector | .onTapGesture |
密碼用SecureField
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| EditText | UITextField | TextField | TextField |
| EditText | UITextView | TextField | TextEditor |
List包住的話會長得不一樣(default跟inline這兩種)| Android | iOS | Flutter(Material) | Flutter(Cupertino) | SwiftUI |
|---|---|---|---|---|
| Spinner | UIPickerView | showBottomSheet | CupertinoActionSheet | Picker |
| Android | iOS | Flutter(Material) | Flutter(Cupertino) | SwiftUI |
|---|---|---|---|---|
| DatePickerDialog | UIDatePicker | showDatePicker/showTimePicker | CupertinoDatePicker | DatePicker |
點背景取消)兩個按鈕
會閃退
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| Dialog | UIAlertController | AlertDialog | Alert |
一定要用Label)

| Flutter | SwiftUI |
|---|---|
| Switch | Toggle |
| Slider | Slider |
| DropdownButton | Stepper |
| Positioned | .contextMenu |
| ExpansionTile | DisclosureGroup |

View

加上相同的效果| Flutter | SwiftUI |
|---|---|
| Divider | Divider |
| VerticalDivider | X |
| Spacer | Spacer |
| ProgressView(菊花) | CircularProgressIndicator |
| ProgressView(進度條) | LinearProgressIndicator |
| Card | X |
.layoutPriority()(Flutter是用Expanded☘️☘️☘️)
| Flutter | SwiftUI |
|---|---|
| GeometryReader | LayoutBuilder |
| UIScreen | MediaQuery |
| EmptyView | Container without child |




可以同時垂直水平滾動⚠️⚠️⚠️| iOS | Flutter | SwiftUI |
|---|---|---|
| UIScrollView | SingleChildScrollView | ScrollView |
indices屬性分隔線的inset
inset style會失效
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| ListView | UITableView static cell | ListView use children | List with content |
| RecycleView | UITableView dynamic cell | ListView.builder | List with data |
分隔線會壞掉(inset太多了)
只要加了Button,點擊效果就是整個row少了前面的這一個點(.padding() 打成padding())size其實是個enum,有以下三種,預設flexible
alignment在GridView上設定,相同方向的alignment在GridItem上設定(spacing也是一樣的概念)再包一層ScrollView
pinnedViews可以決定section要不要有黏貼(sticky)效果加個.padding(.vertical, 0.1)可以解決畫面寬度不足被撐開的情況auto complete失效的情況| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| RecycleView(set GridLayoutManager) | UICollectionView | GridView | LazyVGrid & LazyHGrid |
Link是個按鈕,點了可以開網頁或其他app(like Flutter url_launcher☘️☘️☘️)dismiss
| iOS | Flutter | SwiftUI |
|---|---|---|
| openUrl | url_launcher | Link |
| UINavigationController | Navigator | NavigationView |
| present | modal_bottom_sheet | .sheet |
| present modalPresentationStyle = .fullScreen | CupertinoPageRoute fullscreenDialog | .fullScreenCover |
TabView {
viewA.tabItme{
//很適合放Label
}
viewB.tabItme{
}
viewC.tabItme{
}
}
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| BottomNavigationView | UITabBarController | BottomNavigationBar | TabView |
.tabViewStyle(.page)可以做到滑動換頁效果.animation(.easeInOut, value: selectedPageIndex)| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| TabbedActivity | UIPageViewController | TabController | TabView |
之前呼叫,disappear是消失之後呼叫@AppStorage
App生命週期
| iOS | Android | Flutter | SwiftUI |
|---|---|---|---|
| WillEnterForeground | onRestart | ||
| DidBecomeActive | onStart | resumed | active |
| WillResignActive | onPause | inactive | |
| DidEnterBackground | onStop | paused | background |
View生命週期
| iOS | Android | Flutter | SwiftUI |
|---|---|---|---|
| init | onCreate | createState | init |
| viewDidLoad | initState | ||
| viewWillAppear | onStart | .onAppear() | |
| viewDidLayoutSubviews | build | body | |
| viewDidAppear | onResume | ||
| viewWillDisappear | onPause | ||
| viewDidDisappear | onStop | .onDisappear() | |
| removeFromSuperview | deactivate | ||
| deinit | onDestroy | dispose |
本地儲存
| iOS | Android | Flutter | SwiftUI |
|---|---|---|---|
| UserDefault | SharedPreferences | SharedPreferences | AppStorage |

還是要改扣
#if os(macOS)
換個名字
要重啟= =clean build一下看看.environment(.colorScheme, .dark)
只會從下層開始影響兩家PK
| Flutter | SwiftUI |
|---|---|
| Padding | .padding |
| SizedBox | .frame |
| Align | .frame |
| Positioned | .offset |
| (Widget property) | .foregroundColor |
| Container color | .background |
| Container decoration | .border |
| Column | VStack |
| Row | HStack |
| Stack | ZStack/.overlay() |
| Switch | Toggle |
| Slider | Slider |
| DropdownButton | Stepper |
| Positioned | .contextMenu |
| ExpansionTile | DisclosureGroup |
| Divider | Divider |
| VerticalDivider | X |
| Spacer | Spacer |
| ProgressView(菊花) | CircularProgressIndicator |
| ProgressView(進度條) | LinearProgressIndicator |
| Card | X |
| GeometryReader | LayoutBuilder |
| UIScreen | MediaQuery |
| EmptyView | Container without child |
三缺一
| iOS | Flutter | SwiftUI |
|---|---|---|
| UITapGestureRecognizer | GestureDetector | .onTapGesture |
| UIScrollView | SingleChildScrollView | ScrollView |
| openUrl | url_launcher | Link |
| UINavigationController | Navigator | NavigationView |
| present | modal_bottom_sheet | .sheet |
| present modalPresentationStyle = .fullScreen | CupertinoPageRoute fullscreenDialog | .fullScreenCover |
四家廝殺
| Android | iOS | Flutter | SwiftUI |
|---|---|---|---|
| TextView | UILabel | Text | |
| Button | UIButton | RawMaterialButton | Button |
| EditText | UITextField | TextField | TextField |
| EditText | UITextView | TextField | TextEditor |
| Dialog | UIAlertController | AlertDialog | Alert |
| ListView | UITableView static cell | ListView use children | List with content |
| RecycleView | UITableView dynamic cell | ListView.builder | List with data |
| RecycleView(set GridLayoutManager) | UICollectionView | GridView | LazyVGrid & LazyHGrid |
| BottomNavigationView | UITabBarController | BottomNavigationBar | TabView |
| TabbedActivity | UIPageViewController | TabController | TabView.tabViewStyle(.page) |
| WillEnterForeground | onRestart | ||
| DidBecomeActive | onStart | resumed | active |
| WillResignActive | onPause | inactive | |
| DidEnterBackground | onStop | paused | background |
| init | onCreate | createState | init |
| viewDidLoad | initState | ||
| viewWillAppear | onStart | .onAppear() | |
| viewDidLayoutSubviews | build | body | |
| viewDidAppear | onResume | ||
| viewWillDisappear | onPause | ||
| viewDidDisappear | onStop | .onDisappear() | |
| removeFromSuperview | deactivate | ||
| deinit | onDestroy | dispose | |
| UserDefault | SharedPreferences | SharedPreferences | AppStorage |
四天王有五人
| Android | iOS | Flutter(Material) | Flutter(Cupertino) | SwiftUI |
|---|---|---|---|---|
| Spinner | UIPickerView | showBottomSheet | CupertinoActionSheet | Picker |
| DatePickerDialog | UIDatePicker | showDatePicker/showTimePicker | CupertinoDatePicker | DatePicker |
Xcodes
Xcode的版本真的超多,體積超肥,下載也雷
這App可以幫你管理並下載多個app
超方便
cleaner for Xcode
Xcode不只本身肥,產生出來的資料也很肥
這App可以快速幫你掃出有哪些資料佔用空間
隨隨便便就100GB了
寫SwiftUI更肥,隨便寫個Side project一兩個月就50GB
偷渡一下我整理的SwiftUI資源集中地
https://twitter.com/MarkFlyyyyy/status/1558347636302053376
其實這次系列文下來
還有些主題想試試的
但寫不動了就沒放進去
之後有可能會自行嘗試
雖然已經懶得寫成文章了
但還是問問看
如果你覺得還想看到我的文章的在標題左邊按讚並留言投票感興趣的主題,該主題超過10票就開寫,私訊連結給你,但時間不定:
寫文章真的很累,我想我們不會再見了XD
Android版:iOS Developer Learning Android. Lesson 30 - 精彩大結局 (重點整理: 看這一天等於看30天)
Flutter版:iOS Developer Learning Flutter. Lesson29 總複習
https://github.com/mark33699/FDLS