LoginSignup
0
0

More than 1 year has passed since last update.

Xcode14のXcode Previewsでエラー `error: '__designTimeString(_:fallback:)' is only available in iOS 13.0 or newer`

Posted at

前提

現在開発中のiOSアプリは幅広いユーザー層を考慮し、現時点ではiOS12もサポート対象となっています。その環境ではSwiftUIを使用することはできませんが、UIKitのビューの開発効率を上げるために、次のコードのようにUIViewRepresentableを用いてXcode Previewsでビューをプレビューできるようにしています。

SampleLabel.swift
import UIKit

class SampleLabel: UILabel {
    override init(frame: CGRect) {
        super.init(frame: frame)
        construct()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        construct()
    }
    
    private func construct() {
        text = "Sample"
    }
}

#if canImport(SwiftUI) && DEBUG
import SwiftUI

@available (iOS 13.0, *)
struct SampleLabelWrapper: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        SampleLabelWrapper()
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {}
}

@available (iOS 13.0, *)
struct SampleLabel_Previews: PreviewProvider {
    static var previews: some View {
        SampleLabelWrapper()
    }
}
#endif

Xcode14のXcode Previewsで発生したエラー

今回、開発環境をXcode14にアップデートしたところ、このようなコードでのXcode Previewsで次のエラーが発生するようになり、プレビューができなくなってしまいました。

error: '__designTimeString(_:fallback:)' is only available in iOS 13.0 or newer
text = __designTimeString("#4947.[1].[2].[0].[0]", fallback: "Sample")

このエラーが起きている箇所は、text = "Sample"の部分です。StringやIntといったプリミティブな型の定数が書かれているところ全般に__designTime~という関数が差し込まれているようです。これがプレビューのために非公開APIで、iOS13以降でしか使用できないためにエラーとなっていそうです。

しかし、なぜUIKitのビューにプレビューのためのコードが差し込まれてしまうのでしょうか...

(参考) XcodePreviews の仕組み

回避策

この問題が回避できないと開発効率に大きく影響するため、回避策を探りました。結論としては以下の2つです。

  • (当たり前ですが)開発中だけMinimum Deployment TargetをiOS13以降にする
  • UIKitのビューのコードと、PreviewProviderのコードを別のファイルに記述する

(検証時のコードはこちら 👉 https://github.com/temoki/Xcode14PreviewsBug)

後者について、次のように別のファイルに記述することでこのエラーは発生しなくなります。

SampleLabel.swift
import UIKit

class SampleLabel: UILabel {
    override init(frame: CGRect) {
        super.init(frame: frame)
        construct()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        construct()
    }
    
    private func construct() {
        text = "Sample"
    }
}
SampleLabel+Previews.swift
#if canImport(SwiftUI) && DEBUG
import SwiftUI

@available (iOS 13.0, *)
struct SampleLabelWrapper: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        SampleLabelWrapper()
    }

    func updateUIView(_ uiView: UIViewType, context: Context) {}
}

@available (iOS 13.0, *)
struct SampleLabel_Previews: PreviewProvider {
    static var previews: some View {
        SampleLabelWrapper()
    }
}
#endif

おそらくですが__designTime~を差し込む条件が、PreviewProviderの記述のあるコード全体になっているのではにでしょうか。そのためUIKitのViewのコードにも差し込まれているのではないかと思います。

本件はAppleにフィードバック済みですので、Xcode14.1あたりで修正されてくれることを祈ります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0