前提・実現したいこと
SwitfUIで以下の機能を実装すること。
- リストのアイテム削除機能
- 右スワイプによる左メニューの表示機能
- 左メニュー表示時、背景をグレーアウトする機能
上記の2・3の機能を実装中に以下の問題が発生しました。
解決策ご存知の方いらっしゃいましたら、ご教示のほどよろしくお願いいたします。
発生している問題・エラーメッセージ
エラーメッセージ: 無し
以下の該当のソースコード
の以下のコードをアンコメントすると、リストの削除機能が動作しない。
直下のコード(2箇所)が影響し、ListのonDeleteが正常に動作しない。
それぞれのコードは単体では動作します。コメントアウトされたコードのどちらかをアンコメントするとListが動作しなくなります。
該当のソースコード
swift
1import SwiftUI 2import RealmSwift 3 4struct ContentView: View { 5 // メモ 6 @ObservedObject var memos = ContentViewModel() 7 // モーダル表示フラグ 8 @State private var isShow = false 9 // メニューを表示/非表示する為のオフセットを保持 10 @State private var offset = CGFloat.zero 11 @State private var closeOffset = CGFloat.zero 12 @State private var openOffset = CGFloat.zero 13 14 var body: some View { 15 GeometryReader { geometry in 16 ZStack(alignment: .leading) { 17 VStack { 18 ZStack { 19 HStack { 20 Button(action: { 21 self.offset = self.openOffset 22 }){ 23 Image(systemName: "list.bullet") 24 .foregroundColor(.black) 25 } 26 Spacer() 27 } 28 Text("Memo") 29 } 30 .padding(.horizontal) 31 32 Divider() 33 List { 34 ForEach(memos.models, id: .id) { models in 35 Text("(models.content)") 36 } 37 .onDelete(perform: { indexSet in 38 let realm = try! Realm() 39 try! realm.write() { 40 realm.delete(self.memos.models[indexSet.first!]) 41 } 42 }) 43 } 44 } 45 .background(Color.white) 46 .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center) 47 // 以下のコードをアンコメントすると、リストの削除機能が動作しない。 48 // 左メニューが出てきたらメインコンテンツをグレイアウトする 49 // Color.gray.opacity( 50 // Double((self.closeOffset - self.offset)/self.closeOffset) - 0.4 51 // ) 52 53 // 左メニュー 54 LeftMenuView() 55 .background(Color.white) 56 .frame(width: geometry.size.width * 0.7) 57 // 最初に画面のオフセットの値を左メニュー分マイナスする 58 .onAppear(perform: { 59 self.offset = geometry.size.width * -1 60 self.closeOffset = self.offset 61 self.openOffset = .zero 62 }) 63 .offset(x: self.offset) 64 // スライドのアニメーションを設定します 65 .animation(.default) 66 } 67 // 以下のコードをアンコメントすると、リストの削除機能が動作しない。 68 // ジェスチャーに関する実装 69 // .gesture(DragGesture(minimumDistance: 5) 70 // .onChanged{ value in 71 // // オフセットの値(メニューの位置)をスワイプした距離に応じて狭めていく 72 // if (self.offset < self.openOffset) { 73 // self.offset = self.closeOffset + value.translation.width 74 // } 75 // } 76 // .onEnded { value in 77 // // スワイプ終了位置が開始位置よりも右にあればメニューを開く 78 // if (value.location.x > value.startLocation.x) { 79 // self.offset = self.openOffset 80 // } else { 81 // self.offset = self.closeOffset 82 // } 83 // } 84 // ) 85 86 VStack { 87 Spacer() 88 HStack { 89 Spacer() 90 // メモ作成ボタン 91 Button(action: { 92 isShow = true 93 }, label: { 94 Image(systemName: "pencil") 95 .resizable() 96 .frame(width: 20, height: 20) 97 .foregroundColor(.black) 98 .padding(.all,20) 99 }) 100 .sheet(isPresented: $isShow) { 101 ModalView(content: "", isActive: $isShow ) 102 } 103 } 104 } 105 } 106 } 107} 108 109struct ModalView: View { 110 @Environment(.presentationMode) var presentation 111 @State var content: String 112 @Binding var isActive: Bool 113 114 var body: some View { 115 VStack(spacing: 16) { 116 TextField("メモを入力してください", text: $content) 117 .textFieldStyle(RoundedBorderTextFieldStyle()) 118 Button("保存") { 119 let memo = Memo() 120 memo.content = content 121 122 let realm = try! Realm() 123 try! realm.write() { 124 realm.add(memo) 125 } 126 presentation.wrappedValue.dismiss() 127 } 128 Button("閉じる") { 129 isActive = false 130 } 131 } 132 .padding() 133 } 134} 135 136class ContentViewModel: ObservableObject { 137 private var token: NotificationToken? 138 private var results = try? Realm().objects(Memo.self) 139 @Published var models: [Memo] = [] 140 141 init() { 142 token = results?.observe { [weak self] _ in 143 self?.models = self?.results?.map { $0 } ?? [] 144 } 145 } 146 147 deinit { 148 token?.invalidate() 149 } 150}
試したこと
- 問題のコードをコメントアウト/アンコメントし、リストの削除機能へ影響していることの確認
- 環境変数editModeの設定やEditButton()による編集可能状態への変更で削除可能か(=>削除できない)
補足情報(FW/ツールのバージョンなど)
- Xcode Version 12.4 (12D4e)
- Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
Target: x86_64-apple-darwin19.6.0
あなたの回答
tips
プレビュー