🌄

【SwiftUI】Live Photoの表示

1 min read 2

単純にUIViewRepresentableで包むだけだとレイアウトの事情で潰れて見えなくなってしまう。なのでViewのアスペクト比をLive Photoのアスペクト比に合わせる。この問題に丸一日費やして悩みに悩んだけど、結局答えは超シンプルだった。

方法

import SwiftUI
import PhotosUI

struct LivePhotoView: View {
    let livePhoto: PHLivePhoto
    
    var body: some View {
        _LivePhotoView(livePhoto: livePhoto)
            .aspectRatio(
	    livePhoto.size.width / livePhoto.size.height,
	    contentMode: .fill
	    )
    }
}

fileprivate struct _LivePhotoView: UIViewRepresentable {
    let livePhoto: PHLivePhoto
    
    func makeUIView(context: Context) -> PHLivePhotoView {
        let livePhotoView = PHLivePhotoView(frame: .zero)
        livePhotoView.livePhoto = livePhoto
        return livePhotoView
    }
    
    func updateUIView(_ livePhotoView: PHLivePhotoView, context: Context) {
    }
}

参考記事

Live Photos(ライブフォト)を表示するクラス PHLivePhotoView を試す - Qiita
How to display PHLivePhotoView in SwiftUI - Stack Overflow
SwiftUI から PHPicker を使用する方法 - SmallDeskSoftware

Discussion

12.9-inch iPad Pro (5th generation), iPadOS 15 Developer Beta 4, Swift Playgrounds 3.4.1 で表示してみたら LivePhotoView 以前に _LivePhotoView でも潰れてませんでした。iPadOS 15 が要因だったり、Swift Playgrounds が要因だったりするかもしれませんが、ご参考に。

https://gist.github.com/kkk669/80ee0ce2b8ba7ad900e1c39312483f22

_LivePhotoViewVStackに配置した場合は問題ないですが、ScrollViewなどの縦方向に伸びることができるView中に配置した場合は潰れますよ。推測ですが、多分SwiftUIとUIKitのレイアウトの決定順が原因です。

//正しく表示されない例
//https://gist.github.com/kkk669/80ee0ce2b8ba7ad900e1c39312483f22 の97行目から
extension ContentView: View {
    var body: some View {
        ScrollView { //👈🏼
            if let livePhoto = self.pickerResult.first {
                _LivePhotoView(livePhoto: livePhoto) //👈🏼
            }
            Button("Select Photo") {
                self.isPresented = true
            }
            .sheet(isPresented: self.$isPresented) {
                PhotoPicker(
                    configuration: self.config,
                    pickerResult: self.$pickerResult,
                    isPresented: self.$isPresented
                )
            }
        }
    }
}

環境:Xcode 13 beta 4, iOS 14.7.1

ログインするとコメントできます