Swiftのenumはコンパイルが通れば、本当に安全? (CGImagePropertyOrientation)

CGImagePropertyOrientation -> UIImage.Orientation に変換するコードを、ドキュメントを基に以下のように実装した。

extension UIImage.Orientation {
    init(_ cgOrientation: CGImagePropertyOrientation) {
        switch cgOrientation {
        case .up:
            self = .up
        case .upMirrored:
            self = .upMirrored
        case .down:
            self = .down
        case .downMirrored:
            self = .downMirrored
        case .left:
            self = .left
        case .leftMirrored:
            self = .leftMirrored
        case .right:
            self = .right
        case .rightMirrored:
            self = .rightMirrored
        }
    }
}

コンパイラはエラーも警告も出さない。
CGImagePropertyOrientation には @frozen が指定されており、仕様上 @unknown default も不要だ。

そう思っていた時期がありました

_人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人人_
> Fatal error: unexpected enum case 'CGImagePropertyOrientation(rawValue: 0)' <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄

CGImagePropertyOrientation

Xcode 13.2.1 (13C100) における CGImagePropertyOrientation

/* Possible int values for kCGImagePropertyTIFFOrientation */
@frozen public enum CGImagePropertyOrientation : UInt32 {

    
    case up = 1 // 0th row at top,    0th column on left   - default orientation

    case upMirrored = 2 // 0th row at top,    0th column on right  - horizontal flip

    case down = 3 // 0th row at bottom, 0th column on right  - 180 deg rotation

    case downMirrored = 4 // 0th row at bottom, 0th column on left   - vertical flip

    case leftMirrored = 5 // 0th row on left,   0th column at top

    case right = 6 // 0th row on right,  0th column at top    - 90 deg CW

    case rightMirrored = 7 // 0th row on right,  0th column on bottom

    case left = 8 // 0th row on left,   0th column at bottom - 90 deg CCW
}

CGImagePropertyOrientation の要素は固定になっているはずだが、rawValue UInt32 から変換される経路によって Fatal error が発生しているようだ。
CGImagePropertyOrientation は 1 ~ 8 の範囲を指定することを想定した設計になっているが、カメラアプリによっては今回の "0" のように、範囲外の値を指定してる可能性がある。

回避策

仕方ないので、回避策として default を埋めておくことにする。
変更しても、コンパイラからエラーと警告は出ない。

extension UIImage.Orientation {
    init(_ cgOrientation: CGImagePropertyOrientation) {
        switch cgOrientation {
        case .up:
            self = .up
        case .upMirrored:
            self = .upMirrored
        case .down:
            self = .down
        case .downMirrored:
            self = .downMirrored
        case .left:
            self = .left
        case .leftMirrored:
            self = .leftMirrored
        case .right:
            self = .right
        case .rightMirrored:
            self = .rightMirrored
        default:
            self = .up
        }
    }
}

まとめ

Swift の enum だからといって、網羅性に100%の安心ができるかは、ケースによりますね。
みなさまもお気をつけください。

それでは、よいお年を 🐮 🔜 🐯.

UIImage.Orientation -> CGImagePropertyOrientation の変換はこう

extension CGImagePropertyOrientation {
    init(_ uiOrientation: UIImage.Orientation) {
        switch uiOrientation {
        case .up:
            self = .up
        case .upMirrored:
            self = .upMirrored
        case .down:
            self = .down
        case .downMirrored:
            self = .downMirrored
        case .left:
            self = .left
        case .leftMirrored:
            self = .leftMirrored
        case .right:
            self = .right
        case .rightMirrored:
            self = .rightMirrored
        @unknown default:
            self = .up
        }
    }
}

Xcodeテーマを自作しませんか? #はてなエンジニアアドベントカレンダー2021

これははてなエンジニアアドベントカレンダー2021 6日目の記事です。
昨日は id:mizdraBabel をリファクタリングツールとして使う でした。
はてなエンジニアでのアドベントカレンダー、2021年も盛り上がっております!!!

本題

自分はiOSmacOSにDark Modeが入った時から、多くの時間をDark Modeで過ごしている。
2021年ともなると、多くのアプリケーションやWebサイトで、Dark Mode対応が進んだ。
例えば、GitHubでは Day themeNight theme の中にも複数のテーマが用意されていて、ユーザーの好みで選ぶことができる。

ところで、我々は親の顔以上に、エディタを見ている時間が多いのではないだろうか?
自分もXcodeと向き合う時間が、1日の中でも一番多くを占めているようにも感じる。

エディタアプリケーションでも、いくつかのテーマから好みのカラーリングに変更することができるものが多い。

Xcode Themes

Xcodeでは、Preferences > Themes からいくつかの用意されたテーマを選択することだできる。
自分の場合は、Dark Modeが普及するよりも前から、エディタは黒色の背景をベースにするために、 CivicDuskMidnight を使ってきていた。

とは言っても、万人全てが快適なテーマというものはなかなか存在しない。
デフォルトで用意されているテーマを使いながらも、自分の場合は以下のように感じていた。

  • 背景色は黒系統で、明るすぎない色がよい
  • RGB原色に近かづくほど、特に黒背景では見づらく感じる
  • 現代ではGitHubDark defaultDark dimmed の配色を気に入っている
  • 大前提として、自分はデザインの知識がある訳ではないけれど、気になる箇所はいくつかある

ということを踏まえて、Xcodeのテーマを自作することにした。

自作Xcode Theme

github.com

基本は Midnight をベースにしつつ、Civic Dusk に、GItHubのカラーリングを取り入れながら、自分が見やすいと感じる配色を調整した。

Source Editor Console
f:id:yutailang0119:20211205231356p:plain
f:id:yutailang0119:20211205231422p:plain

ちなみに Polarnightスウェーデン語で「極夜」の意味だという。
常にDark Modeで過ごす自分に合うネーミングができた。

Xcodeへ適応

GUIから作成する場合は、Preferences画面の + から作り始めることになる。
このファイルはデフォルトで ~/Library/Developer/Xcode/UserData/FontAndColorThemes/*.xccolortheme に配置される。
GUIで調整した設定は、このファイルを同じパスに配置することで、他のマシンでも同期できるというわけだ。

まとめ

Polarnight はこのアドベントカレンダーのために改めて作ったテーマなので、まだまだ未成熟だろう。
使いながら改良しつつ、手に馴染ませていくことになる。
実は数年前にもXcode Themeを作っていたのだけど、マシンが移り変わっていく中で使用をやめ、どこかに無くしてしまった。
このテーマは大事に育てていこうと思っている。

ということで、みなさんも年末年始の休暇に自分だけのXcodeを作ってみてはどうだろうか?


明日の担当は id:Furutsuki です、明日もお楽しみに!

GitHub ActionsのYAMLフォーマット、統一されてなくて困る

Twitterでも、社Slackでも度々愚痴を漏らしているのだけど、GitHub ActionsのYAMLフォーマットが統一されてなくて枕を濡らしている。

GitHub Actions カテゴリーの記事一覧 - がんばってなんか書く にも書いている通り、自分はいくつかのGitHub Actionsを細々と作っている。
しかし、プロジェクト毎に、さらにはプロジェクト内でも統一ができていなった。

自分はこういった細かいことを気にしてしまう性分なので、重い腰を上げて統一することにした。
熟考の末、自分の管理するGitHub Actionsでは、 kebab-case に統一した。
理由はいくつかあるけど、最終的には自分が見た時の見やすさが一番優先された形だ。

これまでに利用してくれている方にはお手数おかけしますが、変更お願いします。 *1

余談

ところで、actions/typescript-action をテンプレートとしてGitHub Actionsを作り始めると、 kebab-case の入力をテストできない問題が、かつて存在していた。
JavaScriptは得意ではないので後回しにしていたけれど、新たにテンプレートからGitHub Actionsを生成した時に、すでにあるプロジェクトとの差分を読んだことで解決方法に気づいた。

github.com

現在はテンプレートから新規作成すると、kebab-caseでもテストが実行できる。

*1:lintのGitHub Actionsには、これ以外にもBreaking Changeがあります。

action-github-pr-release を作った

github.com

これはご存知 x-motemen/git-pr-release の再発明だ。
まだまだ本家には機能が足りないけれど、簡単に使うには十分なものになったので公開。
こんな感じ になる。

特にTemplateの機能がないと置き換えれない利用ケースが多いと思うので、対応したいとは思っているが...

最小だとこれだけで動いて便利

name: github-pr-release
on:
  push:
    branches:
    - develop
jobs:
  github-pr-release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: yutailang0119/action-github-pr-release@v1
        with:
          token: ${{ github.token }}

余談

内部では GitHub GraphQL API を使って *1 いて、いろいろな学びがあった。
しばらく TypeScript を書いていなかったのと、体系的に学んでいないことで時間がかかってしまったので、ちゃんと時間を取って学ぼうと思った。

作ったGitHub Actionsもだいぶ増えてきた *2

SwiftUI.AsyncImageのBackportを作っている

github.com

iOS 15/macOS 12/tvOS 15/watchOS 8から使えるようになる予定の SwiftUI.AsyncImage が便利で早く使いたいので、SwiftUIが使えるプラットフォーム全てで使えるように、Backportライブラリを作ってみています。

はてなの同僚たちに協力してもらって、AsyncImageのインターフェースと動作をトレースできるようになってきました。
Xcode 13 RCがリリースされるまでに変更はあるかもしれないけれど、対応していくので、ぜひ使ってみて、フィードバック、スターをもらえるとうれしいです💪

PixelaUI 1.0.0 リリースのお知らせ #pixela #PixelaUI

本日、すばらしい発表をみなさんにできることを、大変嬉しく思っています。

v1.0.0

本日、PixelaUI 1.0.0 をリリースしました!
主なアップデートは以下です。

  • アイコンをPixelaUIオリジナルに
  • iOS/iPadOS 14からのWidgetをサポート
  • ログイン情報の取り扱いを調整

ログイン情報に関わる改修をしたため、ファーストリリース時にもお知らせしていた 非互換の変更 を行なっています。 アップデート後、初回は再ログインが必要になるため、ご注意ください。

PixelaUI

PixelaUI

  • Yutaro Muta
  • ユーティリティ
  • 無料
apps.apple.com

ファーストリリースが 2020/01/22 なので、1年半かかりましたが、ついに v1 を迎えることができました。
Pixela本体のAdminである id:a-know さんの協力なしには、実現できませんでした。
改めて、感謝です。

アイコンのリニューアルについて

Appleレビューで、サードパーティアプリとしてアプリ名、アイコンが相応しくないとのリジェクトとなりました。
アプリ名は PixelaUI を変更せずにいたいですが、バージョンを 1 とするいいタイミングなので、アイコンをオリジナルのものに変更することにしました。

PixelaUIの新アイコン
新アイコン

このすばらしいアイコンは、はてなで同僚の id:mazco さんにお願いしました。
Pixelaのオウムを意識しつつ、他の鳥類がいいなと思っていました。
自分のカメラロールを見返して、ペンギンの写真多いと気づいたので、 結構ペンギンが好きみたいです。*1
その中でも、かっこいい感じがいいなと思ったので、イワトビペンギンをモデルにしてもらいました。

yutailang0119が描いた構想
yutailang0119が描いた構想

ちなみに

アプリ名やPixelaの素材利用について、現在はPixelaに利用規約ガイドラインがなく、個別に許諾をもらっています。
DroidKaigi 2018 iOS appのApple審査が通るまで - Konifar's WIP の事例を記憶していたので、 id:konifar さんに相談し、協力していただきました。
ありがとうございました!

有料化について

メジャーバージョンを 1 とする時に、アプリを有料にするかは悩んでいました。
広く使ってもらいたいという気持ちが勝ったので、少なくとも v1 の間は無料アプリとして提供します。

もし、個別にサポートしたいという方がいましたら、以下から支援いただけると、とてもありがたいです。

One more thing...

PixelaUI 1.0.0では、ついに macOS Big Surをサポート しました!
これまで、PixelaUIはAppleSoCマシン向けに、iOS/iPadOS互換アプリとしての配信をしていました。*2
v1 からはmacOS App Storeにも配信を開始したことで、AppleSoCマシン以外 *3 でも、PixelaUIをご利用いただけます。
もちろん、今回のアップデートに含まれるWidgetも、macOSで利用可能です。

ただし、現在はMac CatalystによるiPadOS互換の仕組みを利用したものとなっています。
最適なmacOS UIとはできていません。
今後のアップデートにご期待ください。

今回のお知らせは以上です。
今後しばらくは細かい修正になる気もしますが、引き続きよろしくお願いします!

*1:関係ないけど、南極にいるから寒い場所のイメージのあるペンギンだけど、実はほぼ南半球にしかいないの意外じゃないですか?

*2:betaの位置付けとして告知なし

*3:いわゆるIntel Mac

WEB+DB PRESS Vol.121 特集2 「iOS 14最前線」に寄稿しました #wdpress

宣伝

2021/02/22 (月) に発売予定WEB+DB PRESS Vol.121 *1 に寄稿しました!
担当は、特集2「iOS 14最前線」で、はてなで同僚の id:cockscomb id:kouki_dan との共著です。
その中で、自分は2章「UIKit」と5章「ウィジェット」の2つを担当しています。

一部の大手書店様では、2/15 (月) から、先行販売もあるようです。
もし見かけたら、お手にとってご覧ください!
また、電子書籍版の販売もありますので、合わせてよろしくお願いします!

f:id:yutailang0119:20210204171843j:plain:w300
表紙
WEB+DB PRESS|gihyo.jp … 技術評論社

経緯

昨年の10月に編集長の 稲尾さん に別件にて連絡をした流れで、「iOS 14の特集記事どうですか?」と声をかけていただきました。
今回はiOSにフォーカスした特集だったので、はてな社内でやりたいなと思って話を持っていき、同僚のid:cockscomb id:kouki_dan と一緒に共著とすることにしました。

前回 から1年を待たずしての再登場となりました。

余談

1

リポジトリに紐づくまとまった文章を書く時にはVisual Studio Codeを使っていましたが、 M1 Macにはインストールしていない ので、GitHubCodespaces を使って作業を進めました。
サンプルコードはXcodeで動かす必要があるけれど、日本語を書くだけの時はどこからでも同じ環境を使うことができて便利でした。
Gitnpm をブラウザ上でも使えるので、ちょっとした変更にはiPadで楽に作業ができてよかったです。

2

前回の執筆時には、textlint/textlint が途中で導入され、これが便利だったので、今回は特集リポジトリを作った段階で、初手で導入しました。
せっかくなので、もっと進んだ使い方にしたいなと思って、GitHub Actions用の yutailang0119/action-textlint を作りました。

3

今回の執筆では、2回目にしてかなり正確に分量を調整できて、我ながら驚きました。
しかも、これは担当した2章分両方でのことです。

もちろん、この後にはレビューや校正を経て、リライトや分量調整は再度行っています。

謝辞

一緒に書いてくれた id:cockscomb id:kouki_dan のお二方、ありがとうございました!

編集長の 稲尾さん を始めとした編集部の皆様、今回もありがとうございました!

最後に

2021/2/22 (月) 発売 WEB+DB PRESS Vol.121 を、よろしくお願いします!

*1:URLはまだ404だけど、たぶんこれのはず