watari開発 – Advent201921 –
stage22: 画像投稿機能
さて、テキスト投稿の機能作成してからしばらく経ってしまったが、次は画像投稿機能だ。順を追ってやっていくことにしよう。
画像の表示、写真の撮影、写真の保存、twitterへの投稿。
こんな流れでやっていこう
画像表示の方針
localにある画像を表示できるようにしよう。そういえばiPhoneのストレージへのアクセスってどこまでできるのかな。あとアプリにだけ画像を保持しているようなサービスとかあるけど、どっちの設計の方がいいんだろう。
https://gist.github.com/y-takagi/9f2cea659fb3f55b56aa04530bf0af39
https://qiita.com/tetsufe/items/9ff5fe190ee190afa1bb
などをみると
- CoreDataに突っ込む
- Document/に突っ込む
- フォトライブラリに突っ込む
- (クラウド上のどこかに入れる)
が打ち手としてはありそうだ。
いったんフォトライブラリから呼び出してみるか。既に自分のローカルにある画像を上げる必要もあるし。フワッとした設計だけど、
フォトライブラリ => 画像読み込み => 投稿 => アプリにデータを保存
かな。こうするとフォトライブラリから画像が削除されたとしてもアプリ内には画像を保持しておくことができる。デメリットはデータ二重になるので圧縮とかしてあげないと肥大化がやばそう。
よし、フォトライブラリから画像を読み込んで表示してみよう。
ページの追加
まず、選んだ画像をpreview的に表示するためのボタンとページを追加しよう。
Add New Fileをして、SwiftUI Viewを追加する。名前は ImageView.swift
とした。
まずはこの画面がbutton tapの際に表示されるようにしよう。
// ContentView.swift
var body: some View {
NavigationView {
VStack {
List {
ForEach(self.entryTexts, id: \.self) {entryText in
VStack {
Text(entryText.body!)
Text("\(entryText.createdAt!)")
}
....
oauthToken: oauthToken,
oauthTokenSecret: oauthTokenSecret)
swifter.postTweet(status: entryText.body!, success: { _ in
print("succeeded.")
}, failure: { error in
print("failed.")
print(error)
})
}
})
NavigationLink("add image", destination: ImageView())
Button("twitter signin", action: {
self.provider.getCredentialWith(nil) { credential, error in
if error != nil {
// Handle error.
}
if credential != nil {
Auth.auth().signIn(with: credential!) { result, error in
....
NavtionViewとNavigationLinkを追加。遷移先を新しく作ったImageViewにする。
これで新しいViewを表示することができるようになる。
フォトライブラリへのアクセス
https://developer.apple.com/documentation/photokit/requesting_authorization_to_access_photos
info.plist
の NSPhotoLibraryUsageDescription
に使用用途を記載する。
+ <key>NSPhotoLibraryUsageDescription</key>
+ <string>This app uses Photo Library to make content using images you stored.</string>
で、ImageViewを以下のようにする。
import SwiftUI
import Photos
struct ImageView: View {
@State var image: UIImage?
@State var showImagePicker: Bool = false
var body: some View {
VStack {
if image != nil {
Image(uiImage: image!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 300, height: 300, alignment: .top)
.clipped()
}
Button("pick up image", action: {
self.showImagePicker = true
})
}.sheet(isPresented: $showImagePicker) {
ImagePickerController(image: self.$image)
}
}
}
struct ImagePickerController: UIViewControllerRepresentable {
@Binding var image: UIImage?
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIImagePickerController {
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = context.coordinator
return imagePickerController
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: ImagePickerController
init(_ imagePickerController: ImagePickerController) {
self.parent = imagePickerController
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
defer {
picker.dismiss(animated: true)
}
guard let image = info[.originalImage] as? UIImage else {
return
}
self.parent.image = image
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
picker.dismiss(animated: true, completion: nil)
}
}
}
struct ImageView_Previews: PreviewProvider {
static var previews: some View {
ImageView()
}
}
これで、画像選択して表示するくらいはできそう。
実行
次回は
写真撮影を行えるようにしていこう。
- 前の記事
watari開発 – Advent201920 – 2019.12.20
- 次の記事
watari開発 – Advent201922 – 2019.12.22