SlideShare uma empresa Scribd logo
1 de 50
Baixar para ler offline
給 iOS ⼯工程師的
Flutter 開發
zonble

zonble@gmail.com
Flutter
• https://flutter.io

• ⼀一個寄宿在⽬目前 iOS、Android 平台上的新平台

• 是設計給 Google 未來來作業系統 Fuchsia 的應⽤用程式開發層

• Dart VM + Skia Render 引擎

• 在 iOS/Android App 中包入 Flutter Framework 後,執⾏行行 Dart
code,同⼀一個 App 在不同平台可以 render 出相同的效果

• 可以與 ObjC/Swift/Java/Kotlin 橋接

• 重新發明 Flash?
⽤用 Flutter 可能有什什麼好處?
• 以⽬目前的執⾏行行效能與完成度來來看,似乎不能不管

• 如果同時需要開發 iOS/Android,可以⼤大量量共⽤用程式碼

• iOS/Android 上可以 Render 出⼀一樣的畫⾯面,設計師可以只
需要做⼀一套設計

• 現在就先投資未來來的 Google 作業系統,以及 Flutter 還可
能移植到 Windows/Mac/瀏覽器執⾏行行的可能
⽤用 Flutter 會犧牲什什麼
• 還不⽀支援⼀一些 iPhone 的特殊功能,如 3D Touch

• 不過你的 App 本來來也就沒在⽀支援 3D Touch

• 犧牲跟 macOS/tvOS/watchOS 共⽤用程式碼的機會

• 不過你本來來也沒在⽀支援

• 好的 Dart 語⾔言的⼯工程師不好找

• 不過反正你本來來也找不到好的 ObjC/Swift/Java/Kotlin ⼯工
程師
⽤用 Flutter 會犧牲什什麼
• 在 iOS 上由於⽤用的不是 UIKit 元件,看起來來會比較像
Google Photo 的感覺,⽽而不像「很 Apple」的 App

• 無法使⽤用 XCTest 測試

• 上線後,從 iOS 的 crash log 中看不出 Dart 程式的問題

• 專案會與 Firebase 變得更更緊密,因為現在供 Flutter 使⽤用的
BaaS、Analytics…都只有 Firebase 這個選擇
使⽤用 Flutter 的挑戰
• Flutter 無法使⽤用⼀一些平台專屬功能,⽽而可能需要寫與該平
台橋接的程式,所以現階段還是得懂⼀一定的 iOS/Android
開發

• 哪些部分⽤用 Flutter 寫,哪些寫在 iOS/Android 橋接端,非
常挑戰 App 架構的能⼒力力
安裝
• 先裝好 Xcode 以及 Android Studio

• 去 https://flutter.io/setup-macos/ 下載 zip 檔解壓

• 執⾏行行 flutter doctor 看看少了了什什麼

• ⽤用 homebrew 裝 ideviceinstaller 以及 ios-deploy

• IDE 可⽤用 Android Studio 或 VSCode
iOS ⼯工程師如何進入?
• Dart 程式語⾔言

• Flutter 的設計典範

• Dart 與 Flutter 的套件/⽣生態系
Dart 程式語⾔言
Dart 程式語⾔言
• 這年年頭的 OO 語⾔言其實都差不多,但還是有少部分差異異

• Dart 除了了可以在 Flutter 執⾏行行以外,也可以編譯成 JS 在網
⾴頁使⽤用,也可以單獨在 Dart VM 執⾏行行

• 所以 Dart 可以寫單獨的 CLI 程式,在 server side 執⾏行行

• Dart 在網⾴頁上可以搭配 Angular 使⽤用…不過這年年頭好像寫
Angular 的⼈人比較少
單獨安裝 Dart
• ⽤用 homebrew 安裝 dart

• brew install dart

• 同時建議安裝 stagehand,Dart 的新專案產⽣生器

• pub global activate stagehand
開始新專案
Swift Package Manager
$swift package init

init 後可接 --type

empty|library|executable|
system-module

Dart
$stagehand [project type]

Project type 可接

• console-full

• package-simple

• server-shelf

• web-angular…
Dependency
iOS/Swift 開發
• 可使⽤用 SPM package 或是
Cocoapods

• Cocoapods 可在 https://
cocoapods.org/ 查詢

• SPM Package 的
Dependency 設定寫在
Package.swift 中

• 使⽤用 swift package update
更更新
Dart
• 使⽤用 pub

• 可在 https://
pub.dartlang.org/ 查詢

• Dependency 設定寫在
pubspec.yaml 中

• ⽤用 pub get 指令更更新
變數、常數
Swift
var -> 可以變動

let -> 不可變動
Dart
var -> 可以變動

final -> 不可變動

const -> 全域的常數
Class
Swift
class Sample {

var x:Int

init (x: Int) {

self.x = x

}

func someMethod() {

self.hi()

}

}

var sample = Sample(x: 1)
Dart
class Sample {

int x = 0;

Sample(this.x) {

}

someMethod() {

this.hi();

}

}

Sample sample = new
Sample(1);
字串串格式
Swift Package Manager
var x = “1 + 1 = ( 1 + 1)”

print(x)
Dart
String x = “1 + 1 = ${ 1 + 1}”;

print(x);
匿名函式
Swift
{ x in …

}

或

{ $0.doSomething() }
Dart
(int x) {

…

}

或寫成單⾏行行

(x) => doSomething(x);
匿名函式
Swift
class MyClass {

	 var f: ((Int)->Int)?

}

var x = MyClass()

x.f = { $0 + 1 }

print("(x.f!(2))"

// Swift 也可以⽤用 typealias
Dart
// ⼀一定要⽤用 typedef

typedef int Call(int);

class MyClass {

Call f;

}

main() {

var x = new MyClass();

x.f = (i) => i + 1;

print(x.f(2));

}
Nullability
Swift
必須要將任何變數的形態設定
為 optional,才可以將變數指
向 nil。
Dart
可以將任意變數指向 null,任
何變數⼀一開始不給予值也是
null,但是可以使⽤用與 Swift
相同的 ?? 語法判斷是否是
null。
Callback
Swift
• URLSessionTask 使⽤用
Closure 處理理 callback

• 加裝 promise kit 等套件之
後,可以使⽤用 promise 語
法
Dart
• import ‘dart/async’;

• 使⽤用 Future 物件

• 可使⽤用 Promise 語法或是
async/await
Delegate?
• 在 ObjC/Swift 中⼤大量量使⽤用 Delegate Pattern

• 在 Dart 中改⽤用 Stream Controller

• Stream Controller 可以⽤用來來發送事件,Listener 則監聽從
Stream Controller 發送的事件
Stream Controller in Dart
import 'dart:async';

class MyClass {

StreamController controller = new StreamController.broadcast();

Stream get didSomething = controller.stream;

someMethod() {

this.controller.add(‘Test’);

}

}

MyClass obj = new MyClass();

obj.didSomething.listen( (String s) {

print(s);

});
Dart 也有叫做 Delegate 的東⻄西
• 不是每個叫做 Delegate 的東⻄西都是同樣意思

• ObjC/Swift 的 Delegate 通常⽤用在 Model 或 View 發⽣生改變
的時候,⽤用來來通知 Controller,也就是 Controller 是 Model
或 View 的 Delegate

• Dart 上也可以實作 ObjC/Swift 的 delegate,⽤用 abstract 代
替 protocol…但好像沒有⼈人這麼做
Dart 也有叫做 Delegate 的東⻄西
• Dart 的 Delegate 則指的是某個物件要使⽤用的規則,比較是
⼀一種純 Model 物件

• Dart 的 Delegate 很像 CocoaTouch 中 UICollectionView
與 UICollectionViewLayout 的關係

• 像是 Flutter 的 GirdView 的 delegate,就是 Grid 有幾⾏行行、
間距多少…等邏輯
Notification Center?
• 有類似的東⻄西 https://github.com/stevenroose/dart-events

• 另外也有⼈人在 Flutter 上實作 redux https://
pub.dartlang.org/packages/flutter_redux
Flutter
這個框架的設計概念念跟你
以前寫過的東⻄西差很多喔
Widget Model/Builder
• iOS 上畫⾯面主要由 View Controller/View 組成,View Controller
管理理⼀一個 view property,然後在上⾯面新增/移除 subview

• Flutter 的畫⾯面是由 Widget 組成,每個 Widget ⼜又都是⼀一個
builder,build 出這個 Widget 下有哪些內部的 Widget

• …其實 Flutter 裡頭什什麼都是 Widget

• Build 出的 Widget 再交給 Flutter 的 Renderer 給 render 成畫⾯面

• 某⽅方⾯面來來看,Flutter 的架構中比較沒有明確的 MVC 之分,⼀一個
Widget 像是扮演了了 Controller 與 View 的⾓角⾊色,但本質上
Widget 卻⼜又是 Model…
Widget Model/Builder
• Widget 在 Build 出底下的 Widget 之後,就無法再改動,
要改變畫⾯面,就要再 Build ⼀一次,Build 出另外⼀一份 Widget

• ⼀一個 widget 有點像是 Web 開發的 Virtual DOM,但比較不
同的時,Flutter 的 widget model 沒有做 HTML Tag/CSS
分離,⽽而是 widget 本⾝身就帶有樣式的性質

• Widget 做的事情也超過 DOM Element,Layout/動畫/
對比 iOS 開發看 Widget
• iOS 上,每個 view 的重繪,是在對 UIView 呼叫
setNeedDisplay 之後,才會呼叫 UIView 的 drawRect: 或
是 CALayer 的 drawInContext: 重繪

• 更更新⼀一個 widget 似乎有點類似:對 Widget 的 State 呼叫
setState() 後,才會重新 build 出⼀一份 widget ,由這份
widget render 出新的畫⾯面

• 也有點像是在 Vue.js 裡頭對某個 component 呼叫
$nextTick()
Widget 有兩兩種
• Stateless Widget:Widget build 出來來之後就不會改變內部
widget,往往⽤用在最⼤大或最⼩小的元件。最⼤大如整個 App 的
框架(MaterialApp Class)最⼩小的元件如⽂文字框(Text
Class)

• Stateful Widget:會改變狀狀態的 widget,負責掌管⼀一個
State 屬性,在 State 中再負責 build 出 widget。⼤大多時間
我們會寫這類的 Widget。
App:第⼀一個 Widget
void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {

// This widget is the root of your application.

@override

Widget build(BuildContext context) {

return new MaterialApp(

title: ‘My App',

theme: new ThemeData(

primarySwatch: Colors.blue,

),

home: new HomePage(title: ‘Home Page’),

);

}

} // 然後我們就可以繼續寫 HomePage class
Widget 有兩兩種
• 在前⾯面的範例例中

• MyApp 是 Stateless Widget

• Home Page 是 Stateful Widget
Decorator 風格
• 在其他框架中的元件屬性,在 Flutter 中則往往設計成被另
外⼀一個 Widget 包裝起來來

• ⼀一堆⽂文字置中: Center -> Column -> [Text, Text]

• 圖形放在圓框裡:Box Decoration -> Image
⼀一堆⽂文字置中
把圖放在圓框裡頭
處理理觸控事件
• 有些元件本⾝身就有 onTap,可以傳入匿名函式或某個物件
的 method

• 所有的物件都可以被包在 GestureDetector 當中
Navigation
Widget 不⼀一定是 UI Element
什什麼時候去呼叫 Web API?
• 可以使⽤用 Future Block

• 或是在 initState 的時候,呼叫 Web API call,在 Promise
結束的時候呼叫 setState() 更更新畫⾯面

• 如果要做⾴頁⾯面 retry 的話,後⾯面這種作法可能比較好
Widget 深度往往深得亂七八糟…
Scaffold
• ⼀一個 App 最常⽤用的框架

• AppBar -> 類似 iOS NavigationBar

• Drawer -> 漢堡選單

• Floating Action Button -> Material Design 的特殊 UI

• Bottom Navigation Bar -> 類似 iOS 的 TabBar
建構畫⾯面的流程
• 從 Home Page 建置 Scaffold

• 根據各種⾏行行為,更更換 Scaffold 中的 body
⼀一些眉眉⾓角⾓角
• ListView 與 Grid View 只能單個 Section,如果想要多
Section 的 ListView 或 GridView,要改⽤用
CustomScrollView

• CustomScrollView 的 children 得要⽤用 SliverListView 以及
SliverGridView,⽽而不是直接把 ListView 或 GridView 放進
去
Flutter Plug-in
Flutter Plug-in
• 有些跟平台有關的事情,Flutter 不直接⽀支援

• 可以⾃自⼰己撰寫與平台橋接的程式(Platform Channel)
https://flutter.io/platform-channels/

• 或是安裝已經有⼈人包好的 Flutter Plug-in
Open URL
• 在 iOS 上可以呼叫 UIApplication 的 openURL: 以及
canOpenURL:

• Flutter 上要安裝 url_launcher https://pub.dartlang.org/
packages/url_launcher

• 改寫 pubspec.yaml 然後⽤用 flutter packages get 更更新
dependencies
學習資源
• Flutter 原廠⽂文件 https://flutter.io/docs/

• Coding with Flutter https://medium.com/coding-with-
flutter

• Google IO 2018 其實沒講什什麼東⻄西

Mais conteúdo relacionado

Mais procurados

openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートIIopenFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
Atsushi Tadokoro
 
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdfThe aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
Sara Pellegrini
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya
 
Media Art II openFrameworks 複数のシーンの管理・切替え
Media Art II openFrameworks 複数のシーンの管理・切替えMedia Art II openFrameworks 複数のシーンの管理・切替え
Media Art II openFrameworks 複数のシーンの管理・切替え
Atsushi Tadokoro
 
Android起動周りのノウハウ
Android起動周りのノウハウAndroid起動周りのノウハウ
Android起動周りのノウハウ
chancelab
 

Mais procurados (20)

Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized project
 
Alpine linuxを触ってみよう
Alpine linuxを触ってみようAlpine linuxを触ってみよう
Alpine linuxを触ってみよう
 
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートIIopenFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
openFrameworks – パーティクルを動かす、静的配列と動的配列 - 多摩美メディアアートII
 
64ビット対応Dllインジェクション
64ビット対応Dllインジェクション64ビット対応Dllインジェクション
64ビット対応Dllインジェクション
 
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdfThe aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
 
Debugging concurrency programs in go
Debugging concurrency programs in goDebugging concurrency programs in go
Debugging concurrency programs in go
 
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in DepthA Brief History of UniRx/UniTask, IUniTaskSource in Depth
A Brief History of UniRx/UniTask, IUniTaskSource in Depth
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
Laravel Design Patterns
Laravel Design PatternsLaravel Design Patterns
Laravel Design Patterns
 
Flutter workshop
Flutter workshopFlutter workshop
Flutter workshop
 
BindableProperty 書くのクソダリーんだけど、 あいつなんやねん(仮)
BindableProperty書くのクソダリーんだけど、あいつなんやねん(仮)BindableProperty書くのクソダリーんだけど、あいつなんやねん(仮)
BindableProperty 書くのクソダリーんだけど、 あいつなんやねん(仮)
 
Embedded Recipes 2019 - Pipewire a new foundation for embedded multimedia
Embedded Recipes 2019 - Pipewire a new foundation for embedded multimediaEmbedded Recipes 2019 - Pipewire a new foundation for embedded multimedia
Embedded Recipes 2019 - Pipewire a new foundation for embedded multimedia
 
Mobile 開發常見資安議題
Mobile  開發常見資安議題Mobile  開發常見資安議題
Mobile 開發常見資安議題
 
TDC 2019: transformando 
dados
públicos
em mapas interativos
TDC 2019: transformando 
dados
públicos
em mapas interativosTDC 2019: transformando 
dados
públicos
em mapas interativos
TDC 2019: transformando 
dados
públicos
em mapas interativos
 
[嵌入式系統] 嵌入式系統進階
[嵌入式系統] 嵌入式系統進階[嵌入式系統] 嵌入式系統進階
[嵌入式系統] 嵌入式系統進階
 
Media Art II openFrameworks 複数のシーンの管理・切替え
Media Art II openFrameworks 複数のシーンの管理・切替えMedia Art II openFrameworks 複数のシーンの管理・切替え
Media Art II openFrameworks 複数のシーンの管理・切替え
 
使用 Passkeys 打造無密碼驗證服務
使用 Passkeys 打造無密碼驗證服務使用 Passkeys 打造無密碼驗證服務
使用 Passkeys 打造無密碼驗證服務
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理.NET Core 3.0時代のメモリ管理
.NET Core 3.0時代のメモリ管理
 
Android起動周りのノウハウ
Android起動周りのノウハウAndroid起動周りのノウハウ
Android起動周りのノウハウ
 

Semelhante a 給 iOS 工程師的 Flutter 開發

docker intro
docker introdocker intro
docker intro
koji lin
 
2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt
tka
 
Java Build Tool course in 2011
Java Build Tool course in 2011Java Build Tool course in 2011
Java Build Tool course in 2011
Ching Yi Chan
 
使用Lua提高开发效率
使用Lua提高开发效率使用Lua提高开发效率
使用Lua提高开发效率
gowell
 
Java Jdk6学习笔记[Ppt]
Java Jdk6学习笔记[Ppt]Java Jdk6学习笔记[Ppt]
Java Jdk6学习笔记[Ppt]
yiditushe
 
Build desktop app_by_xulrunner
Build desktop app_by_xulrunnerBuild desktop app_by_xulrunner
Build desktop app_by_xulrunner
Rack Lin
 
Web development with zend framework
Web development with zend frameworkWeb development with zend framework
Web development with zend framework
thinkinlamp
 
Struts Mitac(1)
Struts Mitac(1)Struts Mitac(1)
Struts Mitac(1)
wangjiaz
 
Java 1(Java概述)
Java 1(Java概述)Java 1(Java概述)
Java 1(Java概述)
xzdbd
 

Semelhante a 給 iOS 工程師的 Flutter 開發 (20)

docker intro
docker introdocker intro
docker intro
 
2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt2012 java two-desktop-appliction-using-j-ruby-with-swt
2012 java two-desktop-appliction-using-j-ruby-with-swt
 
Java Build Tool course in 2011
Java Build Tool course in 2011Java Build Tool course in 2011
Java Build Tool course in 2011
 
專案啟動與設定
專案啟動與設定專案啟動與設定
專案啟動與設定
 
使用Lua提高开发效率
使用Lua提高开发效率使用Lua提高开发效率
使用Lua提高开发效率
 
淺談 Groovy 與 Gradle
淺談 Groovy 與 Gradle淺談 Groovy 與 Gradle
淺談 Groovy 與 Gradle
 
Java Jdk6学习笔记[Ppt]
Java Jdk6学习笔记[Ppt]Java Jdk6学习笔记[Ppt]
Java Jdk6学习笔记[Ppt]
 
基于 FRIDA 的全平台逆向分析
基于 FRIDA 的全平台逆向分析基于 FRIDA 的全平台逆向分析
基于 FRIDA 的全平台逆向分析
 
打造你專屬的Xcode plugin
打造你專屬的Xcode plugin打造你專屬的Xcode plugin
打造你專屬的Xcode plugin
 
使用 laravel 的前與後
使用 laravel 的前與後使用 laravel 的前與後
使用 laravel 的前與後
 
beidakejian
beidakejianbeidakejian
beidakejian
 
Build desktop app_by_xulrunner
Build desktop app_by_xulrunnerBuild desktop app_by_xulrunner
Build desktop app_by_xulrunner
 
Web development with zend framework
Web development with zend frameworkWeb development with zend framework
Web development with zend framework
 
4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf4. Go 工程化实践-0124-v2.pdf
4. Go 工程化实践-0124-v2.pdf
 
Struts Mitac(1)
Struts Mitac(1)Struts Mitac(1)
Struts Mitac(1)
 
[2020 .NET Conf] 企業Azure DevOps Service 實際應用架構與秘辛
[2020 .NET Conf] 企業Azure DevOps Service 實際應用架構與秘辛[2020 .NET Conf] 企業Azure DevOps Service 實際應用架構與秘辛
[2020 .NET Conf] 企業Azure DevOps Service 實際應用架構與秘辛
 
Cloudstack dev/user sharing
Cloudstack dev/user sharingCloudstack dev/user sharing
Cloudstack dev/user sharing
 
Java 1(Java概述)
Java 1(Java概述)Java 1(Java概述)
Java 1(Java概述)
 
Android gradle 从入门到gg 3
Android gradle 从入门到gg 3Android gradle 从入门到gg 3
Android gradle 从入门到gg 3
 
CRUD 綜合運用
CRUD 綜合運用CRUD 綜合運用
CRUD 綜合運用
 

Mais de Weizhong Yang

苦集滅道:透過開發客製 Sketch Plug-in 改善產品設計流程
苦集滅道:透過開發客製 Sketch Plug-in  改善產品設計流程苦集滅道:透過開發客製 Sketch Plug-in  改善產品設計流程
苦集滅道:透過開發客製 Sketch Plug-in 改善產品設計流程
Weizhong Yang
 
Aspect Oriented Programming
Aspect Oriented ProgrammingAspect Oriented Programming
Aspect Oriented Programming
Weizhong Yang
 
Python 的文件系統
Python 的文件系統Python 的文件系統
Python 的文件系統
Weizhong Yang
 

Mais de Weizhong Yang (18)

Flutter BLE
Flutter BLEFlutter BLE
Flutter BLE
 
關於延長役期這件事情
關於延長役期這件事情關於延長役期這件事情
關於延長役期這件事情
 
Dart null safety
Dart null safetyDart null safety
Dart null safety
 
Github Actions
Github ActionsGithub Actions
Github Actions
 
iPlayground: CarPlay and MFI Hearing Aids
iPlayground: CarPlay and MFI Hearing AidsiPlayground: CarPlay and MFI Hearing Aids
iPlayground: CarPlay and MFI Hearing Aids
 
CocoaPods private repo
CocoaPods private repoCocoaPods private repo
CocoaPods private repo
 
那些年被蘋果 Ban 掉的 API
那些年被蘋果 Ban 掉的 API那些年被蘋果 Ban 掉的 API
那些年被蘋果 Ban 掉的 API
 
苦集滅道:透過開發客製 Sketch Plug-in 改善產品設計流程
苦集滅道:透過開發客製 Sketch Plug-in  改善產品設計流程苦集滅道:透過開發客製 Sketch Plug-in  改善產品設計流程
苦集滅道:透過開發客製 Sketch Plug-in 改善產品設計流程
 
使用 switch/case 重構程式碼
使用 switch/case 重構程式碼使用 switch/case 重構程式碼
使用 switch/case 重構程式碼
 
怎樣寫出比較沒有問題的 Code
怎樣寫出比較沒有問題的 Code怎樣寫出比較沒有問題的 Code
怎樣寫出比較沒有問題的 Code
 
貪食蛇
貪食蛇貪食蛇
貪食蛇
 
Aspect Oriented Programming
Aspect Oriented ProgrammingAspect Oriented Programming
Aspect Oriented Programming
 
Mac OS X 與 iOS 的 Audio API
Mac OS X 與 iOS 的 Audio APIMac OS X 與 iOS 的 Audio API
Mac OS X 與 iOS 的 Audio API
 
Html 5 native drag
Html 5 native dragHtml 5 native drag
Html 5 native drag
 
Retina mac
Retina macRetina mac
Retina mac
 
Python 的文件系統
Python 的文件系統Python 的文件系統
Python 的文件系統
 
Refactoring
RefactoringRefactoring
Refactoring
 
Core animation
Core animationCore animation
Core animation
 

給 iOS 工程師的 Flutter 開發

  • 1. 給 iOS ⼯工程師的 Flutter 開發 zonble zonble@gmail.com
  • 2. Flutter • https://flutter.io • ⼀一個寄宿在⽬目前 iOS、Android 平台上的新平台 • 是設計給 Google 未來來作業系統 Fuchsia 的應⽤用程式開發層 • Dart VM + Skia Render 引擎 • 在 iOS/Android App 中包入 Flutter Framework 後,執⾏行行 Dart code,同⼀一個 App 在不同平台可以 render 出相同的效果 • 可以與 ObjC/Swift/Java/Kotlin 橋接 • 重新發明 Flash?
  • 3. ⽤用 Flutter 可能有什什麼好處? • 以⽬目前的執⾏行行效能與完成度來來看,似乎不能不管 • 如果同時需要開發 iOS/Android,可以⼤大量量共⽤用程式碼 • iOS/Android 上可以 Render 出⼀一樣的畫⾯面,設計師可以只 需要做⼀一套設計 • 現在就先投資未來來的 Google 作業系統,以及 Flutter 還可 能移植到 Windows/Mac/瀏覽器執⾏行行的可能
  • 4. ⽤用 Flutter 會犧牲什什麼 • 還不⽀支援⼀一些 iPhone 的特殊功能,如 3D Touch • 不過你的 App 本來來也就沒在⽀支援 3D Touch • 犧牲跟 macOS/tvOS/watchOS 共⽤用程式碼的機會 • 不過你本來來也沒在⽀支援 • 好的 Dart 語⾔言的⼯工程師不好找 • 不過反正你本來來也找不到好的 ObjC/Swift/Java/Kotlin ⼯工 程師
  • 5. ⽤用 Flutter 會犧牲什什麼 • 在 iOS 上由於⽤用的不是 UIKit 元件,看起來來會比較像 Google Photo 的感覺,⽽而不像「很 Apple」的 App • 無法使⽤用 XCTest 測試 • 上線後,從 iOS 的 crash log 中看不出 Dart 程式的問題 • 專案會與 Firebase 變得更更緊密,因為現在供 Flutter 使⽤用的 BaaS、Analytics…都只有 Firebase 這個選擇
  • 6. 使⽤用 Flutter 的挑戰 • Flutter 無法使⽤用⼀一些平台專屬功能,⽽而可能需要寫與該平 台橋接的程式,所以現階段還是得懂⼀一定的 iOS/Android 開發 • 哪些部分⽤用 Flutter 寫,哪些寫在 iOS/Android 橋接端,非 常挑戰 App 架構的能⼒力力
  • 7. 安裝 • 先裝好 Xcode 以及 Android Studio • 去 https://flutter.io/setup-macos/ 下載 zip 檔解壓 • 執⾏行行 flutter doctor 看看少了了什什麼 • ⽤用 homebrew 裝 ideviceinstaller 以及 ios-deploy • IDE 可⽤用 Android Studio 或 VSCode
  • 8. iOS ⼯工程師如何進入? • Dart 程式語⾔言 • Flutter 的設計典範 • Dart 與 Flutter 的套件/⽣生態系
  • 10. Dart 程式語⾔言 • 這年年頭的 OO 語⾔言其實都差不多,但還是有少部分差異異 • Dart 除了了可以在 Flutter 執⾏行行以外,也可以編譯成 JS 在網 ⾴頁使⽤用,也可以單獨在 Dart VM 執⾏行行 • 所以 Dart 可以寫單獨的 CLI 程式,在 server side 執⾏行行 • Dart 在網⾴頁上可以搭配 Angular 使⽤用…不過這年年頭好像寫 Angular 的⼈人比較少
  • 11. 單獨安裝 Dart • ⽤用 homebrew 安裝 dart • brew install dart • 同時建議安裝 stagehand,Dart 的新專案產⽣生器 • pub global activate stagehand
  • 12. 開始新專案 Swift Package Manager $swift package init init 後可接 --type empty|library|executable| system-module Dart $stagehand [project type] Project type 可接 • console-full • package-simple • server-shelf • web-angular…
  • 13. Dependency iOS/Swift 開發 • 可使⽤用 SPM package 或是 Cocoapods • Cocoapods 可在 https:// cocoapods.org/ 查詢 • SPM Package 的 Dependency 設定寫在 Package.swift 中 • 使⽤用 swift package update 更更新 Dart • 使⽤用 pub • 可在 https:// pub.dartlang.org/ 查詢 • Dependency 設定寫在 pubspec.yaml 中 • ⽤用 pub get 指令更更新
  • 14. 變數、常數 Swift var -> 可以變動 let -> 不可變動 Dart var -> 可以變動 final -> 不可變動 const -> 全域的常數
  • 15. Class Swift class Sample { var x:Int init (x: Int) { self.x = x
 } func someMethod() { self.hi()
 }
 } var sample = Sample(x: 1) Dart class Sample { int x = 0; Sample(this.x) {
 } someMethod() { this.hi();
 }
 } Sample sample = new Sample(1);
  • 16. 字串串格式 Swift Package Manager var x = “1 + 1 = ( 1 + 1)” print(x) Dart String x = “1 + 1 = ${ 1 + 1}”; print(x);
  • 17. 匿名函式 Swift { x in … } 或 { $0.doSomething() } Dart (int x) { …
 } 或寫成單⾏行行 (x) => doSomething(x);
  • 18. 匿名函式 Swift class MyClass { var f: ((Int)->Int)? } var x = MyClass() x.f = { $0 + 1 } print("(x.f!(2))" // Swift 也可以⽤用 typealias Dart // ⼀一定要⽤用 typedef typedef int Call(int); class MyClass { Call f; } main() { var x = new MyClass(); x.f = (i) => i + 1; print(x.f(2)); }
  • 19. Nullability Swift 必須要將任何變數的形態設定 為 optional,才可以將變數指 向 nil。 Dart 可以將任意變數指向 null,任 何變數⼀一開始不給予值也是 null,但是可以使⽤用與 Swift 相同的 ?? 語法判斷是否是 null。
  • 20. Callback Swift • URLSessionTask 使⽤用 Closure 處理理 callback • 加裝 promise kit 等套件之 後,可以使⽤用 promise 語 法 Dart • import ‘dart/async’; • 使⽤用 Future 物件 • 可使⽤用 Promise 語法或是 async/await
  • 21. Delegate? • 在 ObjC/Swift 中⼤大量量使⽤用 Delegate Pattern • 在 Dart 中改⽤用 Stream Controller • Stream Controller 可以⽤用來來發送事件,Listener 則監聽從 Stream Controller 發送的事件
  • 22. Stream Controller in Dart import 'dart:async'; class MyClass { StreamController controller = new StreamController.broadcast(); Stream get didSomething = controller.stream; someMethod() { this.controller.add(‘Test’);
 }
 } MyClass obj = new MyClass(); obj.didSomething.listen( (String s) { print(s); });
  • 23. Dart 也有叫做 Delegate 的東⻄西 • 不是每個叫做 Delegate 的東⻄西都是同樣意思 • ObjC/Swift 的 Delegate 通常⽤用在 Model 或 View 發⽣生改變 的時候,⽤用來來通知 Controller,也就是 Controller 是 Model 或 View 的 Delegate • Dart 上也可以實作 ObjC/Swift 的 delegate,⽤用 abstract 代 替 protocol…但好像沒有⼈人這麼做
  • 24. Dart 也有叫做 Delegate 的東⻄西 • Dart 的 Delegate 則指的是某個物件要使⽤用的規則,比較是 ⼀一種純 Model 物件 • Dart 的 Delegate 很像 CocoaTouch 中 UICollectionView 與 UICollectionViewLayout 的關係 • 像是 Flutter 的 GirdView 的 delegate,就是 Grid 有幾⾏行行、 間距多少…等邏輯
  • 25. Notification Center? • 有類似的東⻄西 https://github.com/stevenroose/dart-events • 另外也有⼈人在 Flutter 上實作 redux https:// pub.dartlang.org/packages/flutter_redux
  • 28. Widget Model/Builder • iOS 上畫⾯面主要由 View Controller/View 組成,View Controller 管理理⼀一個 view property,然後在上⾯面新增/移除 subview • Flutter 的畫⾯面是由 Widget 組成,每個 Widget ⼜又都是⼀一個 builder,build 出這個 Widget 下有哪些內部的 Widget • …其實 Flutter 裡頭什什麼都是 Widget • Build 出的 Widget 再交給 Flutter 的 Renderer 給 render 成畫⾯面 • 某⽅方⾯面來來看,Flutter 的架構中比較沒有明確的 MVC 之分,⼀一個 Widget 像是扮演了了 Controller 與 View 的⾓角⾊色,但本質上 Widget 卻⼜又是 Model…
  • 29. Widget Model/Builder • Widget 在 Build 出底下的 Widget 之後,就無法再改動, 要改變畫⾯面,就要再 Build ⼀一次,Build 出另外⼀一份 Widget • ⼀一個 widget 有點像是 Web 開發的 Virtual DOM,但比較不 同的時,Flutter 的 widget model 沒有做 HTML Tag/CSS 分離,⽽而是 widget 本⾝身就帶有樣式的性質 • Widget 做的事情也超過 DOM Element,Layout/動畫/
  • 30. 對比 iOS 開發看 Widget • iOS 上,每個 view 的重繪,是在對 UIView 呼叫 setNeedDisplay 之後,才會呼叫 UIView 的 drawRect: 或 是 CALayer 的 drawInContext: 重繪 • 更更新⼀一個 widget 似乎有點類似:對 Widget 的 State 呼叫 setState() 後,才會重新 build 出⼀一份 widget ,由這份 widget render 出新的畫⾯面 • 也有點像是在 Vue.js 裡頭對某個 component 呼叫 $nextTick()
  • 31. Widget 有兩兩種 • Stateless Widget:Widget build 出來來之後就不會改變內部 widget,往往⽤用在最⼤大或最⼩小的元件。最⼤大如整個 App 的 框架(MaterialApp Class)最⼩小的元件如⽂文字框(Text Class) • Stateful Widget:會改變狀狀態的 widget,負責掌管⼀一個 State 屬性,在 State 中再負責 build 出 widget。⼤大多時間 我們會寫這類的 Widget。
  • 32. App:第⼀一個 Widget void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( title: ‘My App', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new HomePage(title: ‘Home Page’), ); } } // 然後我們就可以繼續寫 HomePage class
  • 33. Widget 有兩兩種 • 在前⾯面的範例例中 • MyApp 是 Stateless Widget • Home Page 是 Stateful Widget
  • 34. Decorator 風格 • 在其他框架中的元件屬性,在 Flutter 中則往往設計成被另 外⼀一個 Widget 包裝起來來 • ⼀一堆⽂文字置中: Center -> Column -> [Text, Text] • 圖形放在圓框裡:Box Decoration -> Image
  • 36.
  • 38.
  • 39. 處理理觸控事件 • 有些元件本⾝身就有 onTap,可以傳入匿名函式或某個物件 的 method • 所有的物件都可以被包在 GestureDetector 當中
  • 42. 什什麼時候去呼叫 Web API? • 可以使⽤用 Future Block • 或是在 initState 的時候,呼叫 Web API call,在 Promise 結束的時候呼叫 setState() 更更新畫⾯面 • 如果要做⾴頁⾯面 retry 的話,後⾯面這種作法可能比較好
  • 44. Scaffold • ⼀一個 App 最常⽤用的框架 • AppBar -> 類似 iOS NavigationBar • Drawer -> 漢堡選單 • Floating Action Button -> Material Design 的特殊 UI • Bottom Navigation Bar -> 類似 iOS 的 TabBar
  • 45. 建構畫⾯面的流程 • 從 Home Page 建置 Scaffold • 根據各種⾏行行為,更更換 Scaffold 中的 body
  • 46. ⼀一些眉眉⾓角⾓角 • ListView 與 Grid View 只能單個 Section,如果想要多 Section 的 ListView 或 GridView,要改⽤用 CustomScrollView • CustomScrollView 的 children 得要⽤用 SliverListView 以及 SliverGridView,⽽而不是直接把 ListView 或 GridView 放進 去
  • 48. Flutter Plug-in • 有些跟平台有關的事情,Flutter 不直接⽀支援 • 可以⾃自⼰己撰寫與平台橋接的程式(Platform Channel) https://flutter.io/platform-channels/ • 或是安裝已經有⼈人包好的 Flutter Plug-in
  • 49. Open URL • 在 iOS 上可以呼叫 UIApplication 的 openURL: 以及 canOpenURL: • Flutter 上要安裝 url_launcher https://pub.dartlang.org/ packages/url_launcher • 改寫 pubspec.yaml 然後⽤用 flutter packages get 更更新 dependencies
  • 50. 學習資源 • Flutter 原廠⽂文件 https://flutter.io/docs/ • Coding with Flutter https://medium.com/coding-with- flutter • Google IO 2018 其實沒講什什麼東⻄西