- 投稿日:2020-07-02T23:41:58+09:00
Swift学習要点(随時更新予定)
文法編
空白(スペース)は、=、+、-などの演算子の前後にはあってもなくてもOKである。但し、前後どちらか一方にしかないとエラーになる
letもvarも複数の宣言を「;」で区切って1行にまとめて書くことができる
ex) let max_length = 10; var current_length = 5変数var で再代入する際には、「var 」やデータ型はいらない
連結ではなく、文字列の中に変数(定数)の値を埋め込むこともできる。(変数)のように書くことで文字列内に変数を埋め込むことができます。これを変数の「展開」と呼ぶ。
Bool型の定数や変数の名前は、慣習上”is”から始めることが多い
Xcode編
IBはInterface Builderの略
させたい処理を書くのがIBActionである
要素とプログラムを結びつける方法をIBOutletという。IBActionで記した動作とストーリーボード上に配置したパーツとを紐付けるものである。
Outlet: UI部品をプロパティとして接続する
Action: UI部品をメソッドとして接続するviewDidLoadの中に書いたコードは、一番最初に実行される。
label.textに文字列を代入すると実際のラベルの内容が変化する。
- 投稿日:2020-07-02T20:26:08+09:00
Swiftで今「ニューモーフィズム」のアプリを作るなら
はじめに
こちらの記事は #Qiita夏祭り2020_パソナテック への応募記事になります。
LGTM上位の記事に豪華なプレゼントがもらえるそうなので、ぜひこの記事を読んでLooks Goodだと思っていただけたらLGTMお願いします!ニューモーフィズムとは
ニューモーフィズム(Neumorphism)とは背景から要素が押し出されていたり、凹んでいるように見えるスタイルのデザインのことを言います。
2020 年初頭から流行り始めているそうです。カッコいいですね?
一目惚れした僕はニューモーフィズムで何かアプリを作ることにしました。 DDD(デザイン駆動開発)です(そんな言葉はありません)。題材はAI寝言録音アプリです。
睡眠中の音声に音声認識をかけることで寝言だけを録音しちゃおうというアプリです。
自分は寝言がとても面白いらしく、自分でもぜひ聞いてみたくなり、世に出回っている寝言録音アプリを使ってみました。しかし寝返りの音といびきの音ばかりが録音されていて寝言を探すのが大変だったので、音声認識を噛ませることで寝言だけを録音できるのではないかと思いました。ニューモーフィズムを作る
ニューモーフィズムのデザインの方法を学ぶために、まずはKeynote(Mac純正のパワポ)を使ってアプリアイコンを作ってみたいと思います。
1. ベースカラーを決める
ベースカラーは#C4D2E9にします。
背景色をベースカラーで染めます。2. 2つの影のカラーを決める
ベースカラーの輝度を変更して「明るい影」と「暗い影」を決めます。
こちらのオンラインツールを使ってベースカラーの明るい影と暗い影のカラーコードを作成しました。明るい影: #ECF0F7
暗い影: #0E16243. オブジェクトを置く
押し出したい(もしくは凹ませたい)オブジェクトを置きます。
今回は寝言っぽく吹き出しにしてみました。4. 右下に暗い影を落としたオブジェクトを作ります
枠線は消して、右下に先ほど決めた暗い影(#0E1624)を落とします。
5. 左上に明るい影を落としたオブジェクトを作ります
同様に、枠線を消して左上に先ほど決めた明るい影(#0E1624)を落とします。
6. 二つのオブジェクトを重ねます
5、6で作った二つのオブジェクトをぴったりと重ねます。
すると、オオ・・・浮かび上がった・・・7. 最後に仕上げをしてアイコン完成
ZZZと文字を上に置いただけですが、これでアイコン完成です。
Swiftでニューモーフィズムのアプリを作る
さてアイコンもできたので、みなさんお待ちかね、Swiftでニューモーフィズムを実装していきましょう!!
早速僕は「Swift ニューモーフィズム github」で検索しました。
そして見つけました!!偉大な先人のライブラリ!!
https://github.com/hirokimu/EMTNeumorphicViewニューモーフィズムなUIViewを提供してくれる最高のライブラリです。
え?フルスクラッチで実装しないのかって?しません。AIの寝言録音機能を実装する
swiftにはSiriと同じ音声認識機能を使えるSFSpeechRecognizerがあります。
こちらを使って音声認識を行います。
いびきや物音に音声認識を当てるとエラーになるため、これを利用して寝言だけを識別することにします。録画画面
EMTNeumorphicViewを使ってボタンを配置していきます。
凹んだボタンが可愛いですね。再生画面
録音した音声に音声認識をかけて寝言らしき音だけを音声認識結果とともに表示します。
リストにしてもうるさくありません。ソースコード公開します
技術的に面白いことはやっていないので今回はソースコードを公開するだけに留めます・・・
コードレビューしてくれる人歓迎!?♂️
https://github.com/KitaharaMugiro/NegotoRecorder「AI寝言レコーダー」 AppStoreで配信中!
ついでにAppStoreにリリースもしました。250円です(無料なものなどない)。
バージョンアップも予定しています。
https://apps.apple.com/jp/app/id1521147935
- 投稿日:2020-07-02T17:28:56+09:00
アラート表示
アラートを表示する
swiftSimpleAlert.showAlert(viewController: self, title: "タイトル", message: "内容を描いてください", buttonTitle: "OK")アラート表示
swiftimport UIKit struct SimpleAlert { static func showAlert(viewController: UIViewController, title: String, message: String, buttonTitle: String) { let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) let okAction = UIAlertAction(title: buttonTitle, style: .default) { (action) in alert.dismiss(animated: true, completion: nil) } alert.addAction(okAction) viewController.present(alert, animated: true, completion: nil) } }
- 投稿日:2020-07-02T16:27:15+09:00
NavigationControllerからモーダル遷移をする時に出たエラーCould not cast value of type..
遭遇したエラー
Could not cast value of type..
状況
NavigationControllerにTableViewCellを配置し(LINEのイメージ)基本的な遷移(以下①)はTableViewCellを押すことで行っている。
ある時のみ(具体的には開発者によるアカウント削除)にはモーダル遷移(以下②)を行う。原因と対処
segue.identifierによる条件分岐ができておらず、②の遷移の時に①で行うときの値遷移の処理がおこなわれ、クラッシュしていた。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "cellSegue" { let indexPath = self.roomTableView.indexPathForSelectedRow let NextVC = segue.destination as! ChatViewController NextVC.roomName = self.joinedRoomName[indexPath!.section]! NextVC.roomPassword = self.joinedRoomPassword[indexPath!.section]! NextVC.password = "\(joinedRoomName[indexPath!.section]!)\(joinedRoomPassword[indexPath!.section]!)" } }のように
if segue.identifier == ""
を設定することでクラッシュを防ぐことができた。
- 投稿日:2020-07-02T16:22:29+09:00
[Swift]30踏んだら負けのゲームを、iOSアプリ開発で作ってみた。
こんにちはMottyです。今回は話題のSwiftを使った簡単なアプリ制作です。
概要
SwiftはiOSアプリ開発用のプログラミング言語です。
以下のようなメリットが一般的に挙げられます。
・Webフレームワークが充実している
・処理速度が速い
・Apple製品のアプリを一貫して開発できる
・コーディングがシンプル
従来まではObjective-Cという言語でのアプリ開発が主流だったそうですが、
速さやコーディングのシンプルさなど性能面でSwiftが上回り、現在市場に
浸透しつつある新しい言語、といった特徴があります。(データは少し古いですが・・・可視化しても高い成長率が特徴的ですね。)
30言ったら負けのゲーム
こちらに関しては説明は不要でしょうか(?)。
交互に数字を宣言し、先に30を宣言してしまった方の負けのゲームです。
・宣言は交互に行う。初めの数字は1
・プレイヤーが1度に宣言できる数は3つまで。
・連続した整数でつないでいかなければならない。つまり先行が1,2,3と言い終えたあと、
相手は4から始めていく。ソースコード
30.swift// // ViewController.swift // 30 // // Created by Motty on 2020/07/01. // Copyright © 2020 Motty. All rights reserved. import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. //初期化の際に1回だけ実行されるメソッド Counter.text = "0" Turn_Board.text = Turn1 } //Propaties var CountNumber = 0 //0<CN<30 var Turn1 = "Player1のターンです" var Turn2 = "Player2のターンです" var IsPlayer1 = true //If False : Now is Player2 var AddCount1 = 0 //0<AC1<3 var AddCount2 = 0 //0<AC2<3 //Methods //プレイヤーのターンをスイッチする func player_switch() { if IsPlayer1 == true{ IsPlayer1 = false Turn_Board.text = Turn2 }else{ IsPlayer1 = true Turn_Board.text = Turn1 } } // 勝利判定のメソッド func WinnerJudge() { if CountNumber >= 30 { if IsPlayer1 == true{ Turn_Board.text = "Player1の敗北です!" } else { Turn_Board.text = "Player2の敗北です”!" } } } //アドカウント判定のメソッド func AddCountJudge(){ if IsPlayer1 == true{ if AddCount1 >= 3{ AddCount1 = 0 player_switch() } }else{ if AddCount2 >= 3{ AddCount2 = 0 player_switch() } } } // リセット func Reset0(){ AddCount1 = 0 AddCount2 = 0 CountNumber = 0 IsPlayer1 = true Counter.text = "0" Turn_Board.text = Turn1 } //Arranging UIParts //Outlets @IBOutlet weak var Counter: UILabel! @IBOutlet weak var Turn_Board: UILabel! //Actions @IBAction func Add1(_ sender: Any) { CountNumber += 1 AddCount1 += 1 Counter.text = String(CountNumber) WinnerJudge() AddCountJudge() } @IBAction func Add2(_ sender: Any) { CountNumber += 1 AddCount2 += 1 Counter.text = String(CountNumber) WinnerJudge() AddCountJudge() } @IBAction func End1(_ sender: Any) { player_switch() Turn_Board.text = Turn2 } @IBAction func End2(_ sender: Any) { player_switch() Turn_Board.text = Turn1 } @IBAction func Reset(_ sender: Any) { Reset0() } }<表示画面>
動きました。一応機能は動きますが
レイアウトやバグ等はガバガバです。処女作ということでご勘弁を・・・。
しかし、UIパーツは便利ですね・・・GUI操作でアプリを作れるので
プログラミングの担う工程は全体の半分ー6割程度になります。
- 投稿日:2020-07-02T15:49:30+09:00
ラジオボタン(選択肢)を作る(xcode)
備忘録として。参考になったとしたら幸いです。
できるもの
どれか一つだけを選択させたい時。他の選択肢をタップしたらそれまで選択されていたもののチェックが外れるようなものを作りたいなんかに。
使う知識
isSelected
UIButtonには
isSelected
というBool型のプロパティがあります。(推されているかいないかの状態を表す。)
ボタンを押す時にそのisSelected
を反対にするには@IBActionの中に
radio1Button.isSelected = !radio1Button.isSelected
とすることで状態を変えることができます。そして、その時他のボタンが選択されているつまり
isSelected
がtrueならばfalseにすれば良いのでif radio2Button.isSelected { radio2Button.isSelected = !radio2Button.isSelected }のようにします。
radio2Button.isSelected = false
でもOK
これを選択肢の数だけ行うことでラジオボタンを実装することができます。setImage
UIButtonの
setImage
メソッドにはforという引数名があります。
radio1Button.setImage(uncheckedImage, for: .normal)
これは上述したisSelected
と密接に関わっていて、normal
が選択されていない時、selected
が選択された時の状態を表します。
なのでsetImage
の際にそれぞれの状態に応じた画像を決めることで、視覚的に選択されているのかどうかを表現することができます。
ex)normalにはハート、.selectedには塗りつぶされたハートを設定するなどradio1Button.setImage(uncheckedImage, for: .normal) radio2Button.setImage(uncheckedImage, for: .normal機能そのものは
ソースコード
override func viewDidLoad() { super.viewDidLoad() radio1Button.setImage(uncheckedImage, for: .normal) radio2Button.setImage(uncheckedImage, for: .normal } @IBAction func radio1Button(_ sender: Any) { radio1Button.isSelected = !radio1Button.isSelected reportString = "スパム/宣伝目的" if radio2Button.isSelected { radio2Button.isSelected = !radio2Button.isSelected } if radio3Button.isSelected { radio3Button.isSelected = !radio3Button.isSelected } if radio4Button.isSelected { radio4Button.isSelected = !radio4Button.isSelected } if radio5Button.isSelected { radio5Button.isSelected = !radio5Button.isSelected } if radio1Button.isSelected || radio2Button.isSelected || radio3Button.isSelected || radio4Button.isSelected || radio5Button.isSelected { submitButton.isEnabled = true submitButton.setTitleColor(UIColor.black, for: .normal) } else { submitButton.isEnabled = false submitButton.setTitleColor(UIColor.gray, for: .normal) } }
- 投稿日:2020-07-02T12:53:43+09:00
textFieldShouldReturn
- 投稿日:2020-07-02T12:20:07+09:00
NavigationController下においての画面遷移
- 投稿日:2020-07-02T12:09:42+09:00
メルカリ・フリルなどのフリマアプリホーム画面の3カラムデザインの作り方
はじめに
メルカリ/フリルなどのフリマアプリでよく目にするホーム画面の3カラムのデザインを作成する方法を紹介します。
今回はUICollectionViewControllerをSwiftUI上で動かしています。(これでUIKitにホットリロードのCanvasを導入する事が出来ます)*ストーリーボードは使用していないので、Extension.swiftファイルに制約のルールを設定しています。(ステップ3をご覧ください)
開発環境
Swift 5.2.4
Xcode 11.5(Deployment Target 13.0)
ストーリーボードなしステップ1
SceneDelegate.swift内に初期ページ設定をします。初期ページはFrimaContentViewとします
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). // Create the SwiftUI view that provides the window contents. let frimaContentView = FrimaContentView() // Use a UIHostingController as window root view controller. if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = UIHostingController(rootView: frimaContentView) self.window = window window.makeKeyAndVisible() } }ステップ2: SwiftUIからUICollectionViewControllerを表示する
以下を実装するとUIKitでもホットリロード機能(canvas)が使えるため一々Runしなくてもいいので便利です。
import UIKit import SwiftUI class FrimaController: UICollectionViewController { override func viewDidLoad() { super.viewDidLoad() //背景を白にする collectionView.backgroundColor = .white } } struct FrimaIntegratedViewController: UIViewControllerRepresentable { func makeUIViewController(context: UIViewControllerRepresentableContext<FrimaIntegratedViewController>) -> FrimaController { return FrimaController(collectionViewLayout: UICollectionViewFlowLayout()) } func updateUIViewController(_ uiViewController: FrimaController, context: Context) { } } struct FrimaContentView: View { var body: some View { FrimaIntegratedViewController().edgesIgnoringSafeArea(.all) } } struct FrimaContentView_Previews: PreviewProvider { static var previews: some View { FrimaContentView() } }ステップ3: 個々のアイテムセルを作成
セル上にアイテムの名前と値段、いいねボタンを作成します。
class FrimaItemCell: UICollectionViewCell { let priceLabel: UILabel = { let label = UILabel() label.text = "¥1,000" label.textColor = .white return label }() let itemNameLabel: UILabel = { let label = UILabel() label.text = "Tシャツ" label.textColor = .white return label }() let likeButton: UIButton = { let button = UIButton(type: .system) //Xcodeにデフォルトである画像を使用 *これはDeplotment Targetが13.0以降で使えます button.setImage(UIImage(systemName: "heart")?.withRenderingMode(.alwaysOriginal), for: .normal) return button }() override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .systemRed setupView() } fileprivate func setupView() { addSubview(priceLabel) priceLabel.anchor(top: nil, left: leftAnchor, bottom: bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 5, paddingBottom: 5, paddingRight: 0, height: 0, width: 0) addSubview(itemNameLabel) itemNameLabel.anchor(top: nil, left: priceLabel.leftAnchor, bottom: priceLabel.topAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 5, paddingRight: 0, height: 0, width: 0) addSubview(likeButton) likeButton.anchor(top: nil, left: nil, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 5, paddingRight: 5, height: 0, width: 0) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }制約ルールは別ファイルExtensions.swiftで設定しています。
//Extensions.swift import Foundation import UIKit extension UIView { func anchor(top: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?, paddingTop: CGFloat, paddingLeft: CGFloat, paddingBottom: CGFloat, paddingRight: CGFloat, height: CGFloat, width: CGFloat){ translatesAutoresizingMaskIntoConstraints = false if let top = top { self.topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true } if let left = left { self.leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true } if let bottom = bottom { bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true } if let right = right { rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true } if width != 0 { widthAnchor.constraint(equalToConstant: width).isActive = true } if height != 0 { heightAnchor.constraint(equalToConstant: height).isActive = true } } }ステップ4: レイアウトを作成
ステップ3で作成したCellをFrimaController上に登録し、レイアウトを作成します。
class FrimaController: UICollectionViewController, UICollectionViewDelegateFlowLayout { let frimaItemCellId = "frimaItemCellId" override func viewDidLoad() { super.viewDidLoad() collectionView.backgroundColor = .white //ステップ3で作成したFrimaCellを登録 collectionView.register(FrimaItemCell.self, forCellWithReuseIdentifier: frimaItemCellId) } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 20 } override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: frimaItemCellId, for: indexPath) as! FrimaItemCell return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: view.frame.width / 3 - 4, height: view.frame.width / 3) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 4 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 0 } }完成
最後に
今は全てのアイテムが"Tシャツ"、と¥1,000そして画像がありませんが、
次回はアイテムクラスを作り個々のアイテムを設定していきます。最後に一句(初心者時代にやっていたNG行動)
テラテイル 聞きすぎ怒られ 気がメイル
- 投稿日:2020-07-02T11:53:58+09:00
Swift UITextField
今回はTextFieldの使い方です
TextFieldは選択すると文字を入力できるものですね
今回もUIの接続をしたところから解説していきます
ViewController.swiftimport UIKit class ViewController: UIViewController { @IBOutlet weak var label: UILabel! @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func button(_ sender: Any) { } }接続後のコードです
まずは
textField
に入力した文字をbutton
を押した時にlabel
に表示するようにしていきましょうViewController.swiftimport UIKit class ViewController: UIViewController { @IBOutlet weak var label: UILabel! @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() } @IBAction func button(_ sender: Any) { label.text = textField.text } }これで
label
に文字を表示できます
しかし、このままではキーボードが表示されたままになってしまいます
なので、キーボードのreturn
を押した時にキーボードを閉じるようにしますViewController.swiftimport UIKit class ViewController: UIViewController { @IBOutlet weak var label: UILabel! @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() textField.delegate = self //追記 } @IBAction func button(_ sender: Any) { label.text = textField.text } } //以下を追記 extension ViewController: UITextFieldDelegate { func textFieldShouldReturn(_ textField: UITextField) -> Bool { textField.resignFirstResponder() } }
textField.delegate = self
でdelegateを設定してあげます
delegateについてはいづれ記事を書きます
delegateを設定するとUITextFieldDelegate
を継承して!と言われるのでfix
を押してもいいですし、extensionで拡張してから書いてもいいです
あとは決まり文句みたいなものだと思って書いてください雑な解説になってしまいすみません
今回はこれで終わります
- 投稿日:2020-07-02T03:26:10+09:00
iOS 14 の Widgets 全サイズを一度に Preview する【コピペで使える】
本記事は Qrunch とのクロス投稿です。
iOS 14 の Widgets 全サイズを一度に Preview する【コピペで使える】 | Qrunch(クランチ)
iOS & iPadOS 14 および macOS Big Sur から WidgetKit が導入され、Widget を作るためには SwiftUI で書くこととなっています。ここでは iOS 14 での Widget のお話をします。
Widgets の iOS Human Interface Guidelines を見ると "Adapting to Different Screen Sizes" セクションに1つの表があります。そこには各 iPhone のスクリーンサイズと、それぞれに対応する "Small"、"Medium"、"Large" Widget のサイズが記載されています。
せっかく SwiftUI で書くので、Xcode Previews で全てのサイズを表示させながらレイアウトするのはいかがでしょうか。このように一度に表示されると何かと便利です。
以下、3サイズの Widget のサイズを記載済みの
PreviewProvider
です。コピペしてお使いください。Small Widget
struct SmallWidgetContentView_Previews: PreviewProvider { static var contentView: some View { ContentView() .preferredColorScheme(.dark) } static var previews: some View { Group { // 320pt × 568pt (iPhone SE 第1世代) contentView .previewLayout(.fixed(width: 141.0, height: 141.0)) // 375pt × 667pt (iPhone 6/6s/7/7s/8/SE 第2世代) contentView .previewLayout(.fixed(width: 148.0, height: 148.0)) // 414pt × 736pt (iPhone 6 Plus/6s Plus/7 Plus/8 Plus) contentView .previewLayout(.fixed(width: 159.0, height: 159.0)) // 375pt × 812pt (iPhone X/XS/11 Pro) contentView .previewLayout(.fixed(width: 155.0, height: 155.0)) // 414pt × 896pt (iPhone XR/XS Max/11/11 Pro Max) contentView .previewLayout(.fixed(width: 169.0, height: 169.0)) } } }Medium Widget
struct MediumWidgetContentView_Previews: PreviewProvider { static var contentView: some View { ContentView() .preferredColorScheme(.dark) } static var previews: some View { Group { // 320pt × 568pt (iPhone SE 第1世代) contentView .previewLayout(.fixed(width: 291.0, height: 141.0)) // 375pt × 667pt (iPhone 6/6s/7/7s/8/SE 第2世代) contentView .previewLayout(.fixed(width: 322.0, height: 148.0)) // 414pt × 736pt (iPhone 6 Plus/6s Plus/7 Plus/8 Plus) contentView .previewLayout(.fixed(width: 348.0, height: 159.0)) // 375pt × 812pt (iPhone X/XS/11 Pro) contentView .previewLayout(.fixed(width: 329.0, height: 155.0)) // 414pt × 896pt (iPhone XR/XS Max/11/11 Pro Max) contentView .previewLayout(.fixed(width: 360.0, height: 169.0)) } } }Large Widget
struct LargeWidgetContentView_Previews: PreviewProvider { static var contentView: some View { ContentView() .preferredColorScheme(.dark) } static var previews: some View { Group { // 320pt × 568pt (iPhone SE 第1世代) contentView .previewLayout(.fixed(width: 291.0, height: 299.0)) // 375pt × 667pt (iPhone 6/6s/7/7s/8/SE 第2世代) contentView .previewLayout(.fixed(width: 322.0, height: 324.0)) // 414pt × 736pt (iPhone 6 Plus/6s Plus/7 Plus/8 Plus) contentView .previewLayout(.fixed(width: 348.0, height: 357.0)) // 375pt × 812pt (iPhone X/XS/11 Pro) contentView .previewLayout(.fixed(width: 329.0, height: 345.0)) // 414pt × 896pt (iPhone XR/XS Max/11/11 Pro Max) contentView .previewLayout(.fixed(width: 360.0, height: 376.0)) } } }