【SwiftUI】State 付きボタンのアニメーション記述

公式チュートリアルを見ながら。


Animating views and transitions — SwiftUI Tutorials | Apple Developer Documentation

思いついたものを書きなぐり試す。



 

🤔 まとめ

- animation(), withAnimation() 記述がなくても effect にはデフォルトでアニメーションがつく。
- animation() で 個別に effect のアニメーションを変更や削除ができる。
- withAnimation() でアニメーションの変更や削除ができる。



【SwiftUI】Apple 公式サンプルでは Animation と Transition をどのように組み合わせているのか

画面上にメッセージを表示する View。


import SwiftUI

struct Message: View {
  var text: String

  var body: some View {
    HStack(spacing: 0) {
      Image(systemName: "heart.fill")
        .foregroundStyle(.red)
        .font(.title)
        .padding()
      Text(text)
        .padding(.trailing, 24)
    }
    .clipShape(.capsule)
    .background(
      .regularMaterial.shadow(.drop(radius: 16)),
      in: .capsule
    )
  }
}

#Preview {
  Message(text: "Hello, world!")
}

どのように、アニメーションやトランジションをつけて、生き生きとした画面にしているか。

Apple 公式サンプルを参考に書いてみます。

 

🧑🏻‍💻 Preview 用 View の準備

挙動を何度も確かめるために、

Preview 専用の View を作っておきます。


private struct RefreshPreview: View {
  var text: String

  @State private var id = false

  var body: some View {
    Message(text: text)
      .id(id)

    Button("Refresh") {
      id.toggle()
    }
    .buttonStyle(.borderedProminent)
  }
}

👉 【SwiftUI】View の 強制再描画 hatena-bookmark

ボタンを押すと強制的に画面再描画がされて、

表示開始からの動きを確認できるようになります。

 

🧑🏻‍💻 まずは アニメーション・トランジションなしでつくる


import SwiftUI

struct Message: View {
  var text: String

  @State private var showIcon = false
  @State private var showText = false

  var body: some View {
    HStack(spacing: 0) {
      if showIcon {
        Image(systemName: "heart.fill")
          .foregroundStyle(.red)
          .font(.title)
          .padding()
      }
      if showText {
        Text(text)
          .padding(.trailing, 24)
      }
    }
    .clipShape(.capsule)
    .background(
      .regularMaterial.shadow(.drop(radius: 16)),
      in: .capsule
    )
    .frame(height: 50)
    .onAppear {
      Task {
        showIcon = true
        try await Task.sleep(for: .seconds(1))
        showText = true
        try await Task.sleep(for: .seconds(1))
        showText = false
        try await Task.sleep(for: .seconds(1))
        showIcon = false
      }
    }
  }
}

private struct RefreshPreview: View {
  var text: String

  @State private var id = false

  var body: some View {
    Message(text: text)
      .id(id)

    Button("Refresh") {
      id.toggle()
    }
    .buttonStyle(.borderedProminent)
  }
}

#Preview {
  RefreshPreview(text: "Hello, world !!!")
    .padding()
    .frame(maxWidth: .infinity)
}

アイコン画像とテキスト部分をそれぞれの @State で


アイコン表示 

  ↓

テキスト表示

  ↓

テキスト非表示

  ↓

アイコン非表示

と Task の中で1秒ごとに変化させています。

しかし、アニメーションやトランジションがないので、

スムーズに View が変化しません。

 

🧑🏻‍💻 アニメーション・トランジションをつける



 

🧑🏻‍💻 まとめ

やっぱ、全然違いますね。

👉 sample-backyard-birds/Multiplatform/Birds/BirdFoodHappinessIndicator.swift at main · apple/sample-backyard-birds hatena-bookmark

 

🧑🏻‍💻 追記: 上記のトランジションっている ?

withAnimation() 記述は必要だとして、

transition() 記述は不要なのではないか。

できるだけシンプルにテンプレート化しておきたいので、

0.25 倍の速度で確認してみます。

上がトランジションなし、

下がトランジションあり。

トランジションはあったほうがいいですね。

やっぱり、Apple 公式サンプルコードは偉大。



ffmpeg で動画を明るくしたり横に並べる

ffmpeg コントラスト、明るさ(輝度)、サチュレーションを調整する


ffmpeg -i in.mp4 -vf eq=brightness=0.1:saturation=1.5:contrast=1.5 out.mp4

👉 【ffmpeg】ffmpegコマンドの備忘録(タイムラプス、切り抜き、アニメGIF、ビットレート指定、コーデック、音消し、手振れ補正、明るさ) #ffmpeg - Qiita hatena-bookmark

brightness
Set the brightness expression. The value must be a float value in range -1.0 to 1.0. The default value is "0".

contrast
Set the contrast expression. The value must be a float value in range -1000.0 to 1000.0. The default value is "1".

saturation
Set the saturation expression. The value must be a float in range 0.0 to 3.0. The default value is "1".

👉 FFmpeg Filters Documentation hatena-bookmark

これくらいで。


ffmpeg -i in.mp4 -vf eq=brightness=0.2:contrast=1.15 out.mp4

比較のため、横に並べて結合。


ffmpeg -i in.mp4 -i out.mp4 -filter_complex hstack h.mp4



動画って難しい。

プロは素人には見えないものが見えてる。


【Xcode】ローカルと GitHub のソース管理連携設定

GitHub で久々に新規にリポジトリ作成してみたら、

もしかして、表示されなくなりました? こういうスクリプト。


Quick setup - if you've done this kind of thing before
https://github.com/your-account/sample.git


// ... or create a new repository on the command line

echo "# sample" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/your-account/sample.git
pit push -u origin main


// ... or push an existing repository from the command line

git remote add origin https://github.com/your-account/sample.git
git branch -M main
git push -u orign main

👉 Github Quick setup — if you’ve done this kind of thing before hatena-bookmark

困ったので以下のやり方でやったらいけた。

👉 XcodeとGitHubの連携方法 #macOS - Qiita hatena-bookmark

ローカルにプロジェクトのソースはある。として、

そこからの「連携」の手順を最小限で覚えておく。

Control + クリック、かまたは 右クリックから


「New "PROJECT-NAME" Remote...」 で新規作成

で、リモート側(GitHub側)のリポジトリを作成して連携できる。

リモート側(GitHub側)にすでに作成済みの場合は、


「Add Existing Remote...」で既存リモートに接続

と選択すれば、あとは流れで分かる。

GUIからのキーバインド的なやつ。知らんと見つけるのつらいので書いておこうとな。

👉 Configuring your Xcode project to use source control | Apple Developer Documentation hatena-bookmark

続いて.gitignore はこちら。



【macOS】 時代遅れのアプリ配布形式なのか「dmg」vs「zip」

こういう記事を見かけて。

Having a wrapper just to tell you "please drag the app to /Applications" feels like an outdated practice to me.

「アプリを Applications フォルダ にドラッグしてください」とだけ伝えるラッパーがあるのは、時代遅れのやり方のように思います。

かなり同感できるので2つの形式の違いを調べることにしました。

そもそも、ユーザー側から見ると、今のダウンロードな時代に、

ディスクイメージのマウントとかイジェクトとかも分かりづらいのではないかと思ってます。

その他、pkg 形式とか Homebrew とかの話はここでは無視。

 

🤔 Chrome をインストールする場合の手順 ( dmg 形式 )

その時の手順の流れは、


1. .dmgファイルをダウンロードし、
2. ダウンロードしたフォルダを開き、
3. .dmgファイルをマウントし、
3. 2つ目のフォルダーを開くか、サイドバーをオンにし、
4. .app フォルダをアプリケーションフォルダにドラッグし、
5. マウントされた .dmgファイルをイジェクトし、
6. ダウンロードした .dmg ファイルをゴミ箱に捨てる。

となります。

なんか良く考えたら、だるい !!

 

🤔 VSCode をインストールする場合 ( zip 形式 )

手順。


1. .zipをダウンロードして解凍し、
2. ダウンロードしたフォルダを開き、
3. .app フォルダをアプリケーションフォルダにドラッグします。

簡単で良い !!

 

🤔 有名アプリはどっちの形式なのか


dmg 形式
- Chrome
- Firefox
- Gimp
- VLC
- IINA
- LibreOffice
- Keka
- WhatsApp
- Skype


app 形式
- Visual Studio Code
- Telegram
- iStat Menus
- Plex Media Server

dmg 形式のほうが多いです。

 

🤔 みんなの意見

いろいろ言っております。

最終的には、ソフトウェアを .dmg ファイルとして配布するか .zip ファイルとして配布するかの選択は、開発者の好みと、アプリケーションとそのユーザーの特定のニーズによって決まります。

Apple は単純に ZIP 形式を活用することもできたが、そうしないことを選択した。Apple は独自の歴史があるため、一般的に独自の方法で独自のことを行っている。それはそれでよいことだ。Apple が採用しているモデルには利点があり、その利点はより一般的なメカニズムを使用して別の方法で構築することもできたが、物事はそのままでいることもある。

DMG を使用すると、インストール エクスペリエンスが向上します。DMG に背景画像を設定したり、利用規約に同意するための EULA を提供したりできます。「インストールするにはここにドラッグしてください」などの内容の DMG を開くと、実際には背景画像とアプリケーション フォルダーのエイリアスが表示されます。DMG は通常、読み取り専用として配布されるため、ユーザーはアーカイブして後で使用できるように保存し、アプリケーション フォルダーに簡単にドラッグできます。DMG は、ソフトウェア ディスクを購入してコンピューターに挿入し、デスクトップにマウントするエクスペリエンスを模倣しています。DMG には、PKG ファイルまたは prefPane ファイル (設定ベースのアプリ インストーラー) が含まれる場合があり、これらは単独で配布できます。ただし、DMG のカスタマイズ機能は、視覚的なエクスペリエンスをユーザーにアピールしたい開発者にとって魅力的です。

DMG を生成するのがもっと複​​雑でした。なぜなら、DMG を作成するための簡単な開発者スクリプトがなかったからです。誰もが DMG を使用していましたが、今ではスクリプトがあるところでは zip ファイルに移行しています。これもまた歴史の皮肉です。

好みの問題か、.dmg ファイルの作成方法がわからないということだと思います。

ls(1) コマンドを使用してコマンドラインから確認すると、.app ファイルは実際にはファイルではなくディレクトリであることがわかります。したがって、.app ファイルが配布されることは決してありません。それらは何かにアーカイブする必要があります。

.app はファイルではなく、ファイルが入ったディレクトリです。一般的なファイル転送プロトコルで送信したい場合は、そのディレクトリをファイルに変換する必要があります。2 つの明らかな選択肢は、zip ファイルとディスク イメージです。

zip ファイルはシンプルで、ダウンロード フォルダから解凍したアプリをアプリケーション フォルダにコピーするだけです。ただし、ディスク イメージにはいくつかの利点があります。ユーザーにライセンスへの同意を求めるように作成したり、Finder ウィンドウにイメージ背景の形式でブランドを追加したり、複数の部分から成るインストーラを簡単に配置したりできます。

などなど...。

[blogcard url=”https://www.quora.com/Why-are-most-MacOS-applications-distributed-as-dmg-files-rather-than-zip″]

👉 Why are most MacOS applications distributed as .dmg files rather than .zip? - Quora hatena-bookmark

 

🤔 まとめ

いきなりまとめます。

dmg 形式の利点として、


- 「アプリを Applications フォルダ にドラッグしてください」と表示
- カスタム背景
- ライセンス契約、リリースノートの追加

dmg 形式のほうができることが少し多いようです。

しかし、作成手順が面倒なので、

環境に合わせて、以下のツールなどを使うと良さげです。

👉 create-dmg/create-dmg: A shell script to build fancy DMGs hatena-bookmark
👉 create-dmg — Homebrew Formulae hatena-bookmark
👉 dmgbuild · PyPI hatena-bookmark
👉 sindresorhus/create-dmg: Create a good-looking DMG for your macOS app in seconds hatena-bookmark
👉 LinusU/node-appdmg: 💾 Generate your app dmgs hatena-bookmark

ひとつ使って簡単に作成してみました。


まあ、dmg 形式にしとくのが無難なんでしょうね。

 

🤔 参考

以上、以下の issues を見ながらのエントリーでした。

👉 [macOS] Use Drag to Install idiom in published DMG releases · Issue #4062 · transmission/transmission hatena-bookmark

👉 Use .app bundle instead of .dmg file for macOS distribution · Issue #6783 · transmission/transmission hatena-bookmark