私は、バックエンドをAWSを用いてiOSアプリ(Swift)の開発を行っています。
今回、この記事をご覧になる方が多くなるように、あえてこのようなタイトルにしましたが、私が困っているのはタイトルの問題ではありません。
タイトルと違い申し訳ありませんが、私が困っていることはとてもニッチなことだと思いますので、多くの目に触れれるようにさせていただきました。
もし私の困っていることの解決策をご存知の方がいらっしゃいましたら、どうかご教授願います。
前提:AWS Amplifyを用いた,iOS(Swift)アプリの開発を行っています。
GraphQLを用いたDynamoDBとのやりとりを行う際に、Relational models
https://aws-amplify.github.io/docs/ios/datastore を参考にしました。
スキーマはこのような感じです。
GraphQL
1type Post @model { 2 id: ID! 3 title: String! 4 comments: [Comment] @connection(name: "pToc") 5 rating: Int! 6 status: String! 7} 8type Comment @model { 9 id: ID! 10 content: String 11 post: Post @connection(name: "pToc") 12} 13
また、作成されるSwiftFileのModelは
Swift
1 2public struct Post: Model { 3 public let id: String 4 public var title: String 5 public var comments: List<Comment>? 6 public var rating: Int 7 public var status: String 8 9 public init(id: String = UUID().uuidString, 10 title: String, 11 comments: List<Comment>? = [], 12 rating: Int, 13 status: String) { 14 self.id = id 15 self.title = title 16 self.comments = comments 17 self.rating = rating 18 self.status = status 19 } 20} 21 22public struct Comment: Model { 23 public let id: String 24 public var content: String? 25 public var post: Post? 26 27 public init(id: String = UUID().uuidString, 28 content: String? = nil, 29 post: Post? = nil) { 30 self.id = id 31 self.content = content 32 self.post = post 33 } 34} 35
公式ドキュメントを参照し、Postが1個あるときに、Commentがn個取れる構造をしています。
Twitterと同じ構造です。
実際のコードは以下の通りです。
Swift
1let postWithComments = Post(title: "My post with comments", 2 rating: 5, 3 status: "active") 4//Post型のデータを作る。 5 6let comment = Comment(content: "Loving Amplify DataStore", post: postWithComments) 7 8/*Comment型のデータを作る。この時に、なんのPostデータと 1:n構造をとるか指定するために、Comment型の引数に 9post: postWithComments(上のPost型データ) と指定する。 10*/ 11 12Amplify.DataStore.save(postWithComments) { //まずPost型をレコード 13 switch $0 { 14 case .failure(let err): 15 print("Error adding post - (err.localizedDescription)") 16 case .success(let post): //成功した時の処理 17//Post型のレコードが成功した時に、Comment型のレコードも実行する。 18 Amplify.DataStore.save(comment) { 19 switch $0 { 20 case .success: 21 print("Comment saved!") 22 case .failure(let err): 23 print("Error adding comment - (err.localizedDescription)") 24 } 25 } 26 27 } 28}
公式ドキュメントから拝借しました。これを実行するとしっかりとデータベースにレコードされます。
レコードされたPostデータのidが 49E2817D-19BA-46DE-AE63-CA20F6D02AB8 だとすると、これをQueryする方法は
Swift
1 Amplify.DataStore.query(Post.self, byId: "49E2817D-19BA-46DE-AE63-CA20F6D02AB8"){ 2 switch $0 { 3 case .success(let result): 4 print("Posts: (result)") 5 case .failure(let err): 6 print("Error listing posts - (err.localizedDescription)") 7 } 8 } 9 10 11//また、このPostに対して新しいCommentを付け加えたい時は以下のようにします。 12 13 14Amplify.DataStore.query(Post.self, byId: "49E2817D-19BA-46DE-AE63-CA20F6D02AB8"){ 15 switch $0 { 16 case .success(let result): 17 print("Posts: (result)") 18//Queryで呼び出したいPostが呼び出せた時に、comment1のレコードを実行する。 19 20 let comment1 = Comment(content: "New Comment Saved!", post: result) 21 22 Amplify.DataStore.save(comment1) { 23 switch $0 { 24 case .success: 25 print("Comment saved, too!") 26 case .failure(let err): 27 print("Error adding comment - (err.localizedDescription)") 28 } 29 } 30 31 32 case .failure(let err): 33 print("Error listing posts - (err.localizedDescription)") 34 } 35 } 36
さて、ここまでが公式ドキュメントなどを読んで実装したソースコードですが、問題はここからです。
私が困っているのは、Post 1個に対して、Comment n個を抜き出したいのですがその方法がわかりません。
1つのPostに対して複数のCommentがあるわけですが、あるPostをQueryしてそのPostに関連するCommentを配列に保存した場合がわかりません。
Swift
1 2/* case .successの時は、変数resultはPost型です。 3Post型はCommentの配列を持ちますので、クラス変数にComment型の配列を宣言しておきます。 4Queryが成功した時に、上記の配列にPostのCommentを代入しようと思います。 5 6public struct Post: Model { 7 public let id: String 8 public var title: String 9 public var comments: List<Comment>? 10 public var rating: Int 11 public var status: String 12... 略 13} 14*/ 15 16var Com:[Comment]! 17 18Amplify.DataStore.query(Post.self, byId: "49E2817D-19BA-46DE-AE63-CA20F6D02AB8"){ 19 switch $0 { 20 case .success(let result): 21 print("Posts: (result)") 22 Com = result.comments 23 case .failure(let err): 24 print("Error listing posts - (err.localizedDescription)") 25 } 26 } 27
すると、 「Com = result.comments」 のところで
「Cannot assign value of type 'List<Comment>?' to type '[Comment]?'」
というエラーが、ビルドする前に出てしまいます。
ですので、「var Com:[Comment]」を「var Com:List<Comment>!」に変えてやってみると、
Swift
1var Com:List<Comment>! 2 3Amplify.DataStore.query(Post.self, byId: "49E2817D-19BA-46DE-AE63-CA20F6D02AB8"){ 4 switch $0 { 5 case .success(let result): 6 print("Posts: (result)") 7 Com = result.comments 8 print(Com) 9 case .failure(let err): 10 print("Error listing posts - (err.localizedDescription)") 11 } 12 }
ビルドできて、処理も実行できるのですが、「print(Com)」のデバックは、Optional(Amplify.List<daigororo.Comment>)となってしまい、要素が見えない状況です。(daigororoはアプリの名前です。)
私は、このCommentをUITableViewCellに表示したいので、なんとか要素を見えるよな配列に保存したいのですができません。もしわかる方がいらっしゃたら、ご教授お願いいたします。
回答2件
あなたの回答
tips
プレビュー