前端框架选型是企业提升开发效率与用户体验的关键因素
690
2022-10-17
使用Elm构建iOS应用程序
Elm for iOS
Build iOS apps with Elm. Use native or web UI. Or mix and match.
Continuous integration status:
Example
Let's build a counter:
Functional core
100% platform independent100% type safe100% purely functional
port module Counter exposing (..)type alias Model = Intmodel : Modelmodel = 0type alias Flags = { initialCount : Int }init : Flags -> ( Model, Cmd Msg )init flags = let initialModel = flags.initialCount in ( initialModel, view initialModel )type Msg = Increment | Decrementupdate : Msg -> Model -> ( Model, Cmd Msg )update msg model = let newModel = case msg of Increment -> model + 1 Decrement -> model - 1 command = view newModel in ( newModel, command )type alias View = { count : String }view : Model -> Cmd Msgview model = setCountLabelText (toString model)port userDidTapIncrementButton : (() -> msg) -> Sub msgport userDidTapDecrementButton : (() -> msg) -> Sub msgport setCountLabelText : String -> Cmd msgsubscriptions : Model -> Sub Msgsubscriptions _ = Sub.batch [ userDidTapIncrementButton (\_ -> Increment) , userDidTapDecrementButton (\_ -> Decrement) ]main : Program Flags Model Msgmain = Platform.programWithFlags { init = init , update = update , subscriptions = subscriptions }
Tests:
module Tests exposing (..)import Test exposing (..)import Expectimport Counter exposing (..)model : ( Model, Cmd Msg ) -> Modelmodel = Tuple.firstcommand : ( Model, Cmd Msg ) -> Cmd Msgcommand = Tuple.secondall : Testall = describe "Update" [ describe "Increment" [ test "Change model 1" <| \() -> update Increment 1 |> model |> Expect.equal 2 , test "Change model 2" <| \() -> update Increment 2 |> model |> Expect.equal 3 , test "Send command 1" <| \() -> update Increment 1 |> command |> Expect.equal (setCountLabelText "2") , test "Send command 2" <| \() -> update Increment 2 |> command |> Expect.equal (setCountLabelText "3") ] , describe "Decrement" [ test "Change model 1" <| \() -> update Decrement -1 |> model |> Expect.equal -2 , test "Change model 2" <| \() -> update Decrement -2 |> model |> Expect.equal -3 , test "Send command 1" <| \() -> update Decrement -1 |> command |> Expect.equal (setCountLabelText "-2") , test "Send command 2" <| \() -> update Decrement -2 |> command |> Expect.equal (setCountLabelText "-3") ] ]
Imperative shell
Platform dependentDivided into two parts — safe and unsafe
Safe part:
import UIKitimport Elmfinal class ViewController: UIViewController, Elm { @IBOutlet var countLabel: UILabel? struct Flags { let initialCount: Int } enum Input { case userDidTapIncrementButton case userDidTapDecrementButton } enum Output { case setCountLabelText(String) } override func viewDidLoad() { super.viewDidLoad() start(module: "counter", flags: .init(initialCount: 0)) } @IBAction func userDidTapIncrementButton() { send(.userDidTapIncrementButton) } @IBAction func userDidTapDecrementButton() { send(.userDidTapDecrementButton) } func observe(_ output: Output) { switch output { case .setCountLabelText(let text): countLabel?.text = text } }}
Unsafe part where we convert data between Swift to JavaScript:
extension ViewController.Flags: ElmValue { var javaScript: String { return ["initialCount": initialCount].javaScript }}extension ViewController.Input: ElmInput { var port: (ElmPort, ElmValue?) { switch self { case .userDidTapIncrementButton: return ("userDidTapIncrementButton", nil) case .userDidTapDecrementButton: return ("userDidTapDecrementButton", nil) } }}extension ViewController.Output: ElmOutput { init(port: ElmPort, value: ElmValue) { switch port { case "setCountLabelText": let value = value as! String self = .setCountLabelText(value) default: fatalError() } }}
Build
Add the following Run Script build phase to compile Elm during Xcode build:
elm make "$SRCROOT"/Elm/src/Counter.elm --output "$CONFIGURATION_BUILD_DIR"/"$UNLOCALIZED_RESOURCES_FOLDER_PATH"/counter.js --yes
Notes
Due to this bug, all port modules need to include:
import Json.Decode
Thanks
Questions? Comments? Concerns?
Say hello!
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~