質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

button

HTMLで用いる<button>タグです。

Q&A

解決済

SwiftUI alert ボタンの無効化

shiro555
shiro555

総合スコア4

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

button

HTMLで用いる<button>タグです。

1回答

0グッド

0クリップ

289閲覧

投稿2022/10/27 04:16

編集2022/10/27 04:51

前提

SwiftUIを使ってTODOリストアプリを作っています。
プロフィールページにある名前を編集する際にテキストフィールド付きのアラートを出現させているのですが、Submitボタンの制御方法について質問です。
テキストフィールド付きのアラートはこちらを参考に作りました。https://sarunw.com/posts/swiftui-alert-textfield/

実現したいこと

一文字も入力していない場合、Updateボタンを押しても更新できない(actionは何も起こらず、アラートも閉じない)ようにしたいのですが、方法がわからずつまずきました。
funcとして以下のように1文字以上のときはcurrentUserNameを返すようにtextIsAppropriateをtrueにして、それ以外はfalseにしています。

Button("Update", action:{ if textIsAppropriate() { return( currentUserName = userName ) } })
func textIsAppropriate() -> Bool { if userName.count > 1 { return true } else { return false } }

該当のソースコード

import SwiftUI struct ProfileView: View { @State var showAlert: Bool = false @State var userName: String = "" @AppStorage("user_name") var currentUserName: String? var body: some View { ScrollView { VStack { HStack { Text(currentUserName ?? "User name") Button(action: { showAlert = true }, label: { Image(systemName: "pencil.tip.crop.circle") }) .alert("Update user name", isPresented: $showAlert, actions: { TextField("User name", text: $userName) Button("Update", action:{ if textIsAppropriate() { return( currentUserName = userName ) } }) Button("Cancel", role: .cancel, action: {}) }, message: { Text("Please enter User name") }) } .font(.title) .frame(maxWidth: .infinity, alignment: .leading) } .padding() .multilineTextAlignment(.leading) } .navigationTitle("Profile") } func textIsAppropriate() -> Bool { if userName.count > 1 { return true } else { return false } } } struct ProfileView_Previews: PreviewProvider { static var previews: some View { NavigationView { ProfileView() } } }

試したこと

Updateボタンに対して以下を設定したが、Updateボタン自体なくなってしまった。

.disabled(!textIsAppropriate())

補足情報(FW/ツールのバージョンなど)

swift超初心者です🙏このYoutubeを見てTODO listを作り、カスタマイズをしています。
https://www.youtube.com/playlist?list=PLwvDm4VfkdpheGqemblOIA7v3oq0MS30i

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

ベストアンサー

これは、SwiftUIのAlert機能では(今のところ)無理だろうと思います。どうしてもやりたいなら、UIKitのUIAlertControllerをSwiftUIから使用し、その処理を制御(UIAlertActionのisEnabledをON/OFF)する必要があると思います。

自分自身の勉強にもなるので、ちょっと作ってみました。

swift

1struct AlertController: UIViewControllerRepresentable { 2 @Binding var isPresented: Bool 3 @Binding var text: String 4 5 let title: String? 6 let message: String? 7 let placeholderText: String 8 9 class Coordinator: NSObject { 10 var alert: UIAlertController! 11 12 @objc func textDidChange(_ sender: UITextField) { 13 if sender.text!.count == 0 { 14 alert.actions[1].isEnabled = false 15 } else { 16 alert.actions[1].isEnabled = true 17 } 18 } 19 } 20 21 func makeCoordinator() -> AlertController.Coordinator { 22 return Coordinator() 23 } 24 25 func makeUIViewController(context: Context) -> UIViewController { 26 return UIViewController() 27 } 28 29 func updateUIViewController(_ uiViewController: UIViewController, context: Context) { 30 if isPresented { 31 let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) 32 33 context.coordinator.alert = alert 34 // TextFieldの追加 35 alert.addTextField { textField in 36 textField.placeholder = placeholderText 37 textField.returnKeyType = .done 38 textField.addTarget(context.coordinator, action: #selector(Coordinator.textDidChange(_:)), for: .editingChanged) 39 } 40 41 // キャンセルボタンアクション 42 let cancelAction = UIAlertAction(title: "キャンセル", style: .cancel) {_ in } 43 44 // OKボタンアクション 45 let okAction = UIAlertAction(title: "OK", style: .default) { _ in 46 let textField = alert.textFields!.first! 47 self.text = textField.text! 48 } 49 okAction.isEnabled = false 50 51 alert.addAction(cancelAction) 52 alert.addAction(okAction) 53 54 uiViewController.present(alert, animated: true) { 55 isPresented = false 56 } 57 } 58 } 59}

上記のAlertControllerを作り、それを下記のようなコードで呼び出します。

swift

1 Button(action: { 2 showAlert = true 3 }, label: { 4 Image(systemName: "pencil.tip.crop.circle") 5 }) 6 .background { 7 AlertController(isPresented: $showAlert, text: $currentUserName, title: "Update user name", message: "Please enter User name", placeholderText: "User name") 8 }

投稿2022/10/30 02:43

編集2022/10/30 09:12
TakeOne

総合スコア6210

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

shiro555

2022/10/31 01:24

ご丁寧な返信ありがとうございます!調べてみると今回のようにSwiftUIの中でできない機能などをUIkitを用いて使うことも結構あるのですね。 UIkitは学習していないのですが、これを機に実装試してみます!ありがとうございます!!

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

button

HTMLで用いる<button>タグです。