Open3

Swift: Switch文のcaseの書き方について

kabeyakabeya

別記事で以下のようなswitch文を書きました。

var imageSize: CGFloat {
        switch dynamicTypeSize {
        case .xSmall:           return 18
        case .small:            return 19
        case .medium:           return 21.5
        case .large:            return 22
        case .xLarge:           return 24.5
        case .xxLarge:          return 27
        case .xxxLarge:         return 29
        case .accessibility1:   return 28
        case .accessibility2:   return 33
        case .accessibility3:   return 32
        case .accessibility4:   return 37.5
        case .accessibility5:   return 42
        default:                return 22
        }
    }

このdefaultを抜くと以下のような警告が出ます。

要は「いまの時点ですべてのケースがカバーされているけど、将来増えるかも知れないよ?」という話なんでしょうが、ここにdefaultを追加してしまうと、将来増えたあとでコンパイルしたときに、それがカバーされていないにも関わらずエラーにならないという問題があるような気がします。

一方でdefaultがなければ、ケースが増えたときに何の値も返らない(それがどんなことになるのか分かりませんが)、という動きになります。

default: return 22をなくし、switchの外にreturn 22を置くと、最後のreturnには

の警告が出ます。

そもそも普通のenumは「将来増えるかも知れないよ?」みたいなことを言われないと思うのですが、これ何か特別な仕組みがあるのかしら。
だとすると何かこういうメッセージを回避するような書き方ができそうな気もしますが。

kabeyakabeya

XcodeでFixボタンを押すと@unknown default: fatalEror()のひな形を追加してくれました。

fatalErrorにするっていうのもどうなのかと思いますので、この場合は通常の.largeと同じ22を返すことにします。

これ@unknown defaultにしておけば、いまはメッセージが出ませんが、ケースが増えたときに警告

が出ますね。defaultだと今も、ケースが増えたときも、ともに警告は出ません。

defaultを書くケースでは優先的に@unknown defaultの利用を検討したほうが良い気がしてきました。

kabeyakabeya

enumの定義がプロジェクトローカルなソースコードにある場合、そのenumは自動的に@frozen扱いされるので、default@unknown defaultを用意すると

の警告になります。

ライブラリとしてコンパイルする場合、@frozenを付けていないenumはnon-frozenになります。
そのライブラリのenumを参照するswitchは、defaultもしくは@unknown defaultがないと

の警告になります。

https://www.swift.org/blog/library-evolution/

に色々書いてあります。
ライブラリとしてコンパイルする場合はXcodeのターゲット→Build SettingsでBUILD_LIBRARY_FOR_DISTRIBUTIONを検索し、「Build Libraries for Distribution」をNo→Yesに変えれば良さそうです(Xcode 15.4の場合)。