80758
SwiftでCVPixelBufferをUIImageに変換するにあたって以下の記事を参照しました。

[[swift]
CVPixelBufferからCGImage、UIImageへ変換する](https://qiita.com/tommy19970714/items/bc50d49fcb378c196d4f)

UIImageを以下のように拡張しているのですが、どうやって使えば良いか分かりません。

```

    extension UIImage {
        public convenience init?(pixelBuffer: CVPixelBuffer) {
            var cgImage: CGImage?
            VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &cgImage)
    
            guard let cgImage = cgImage else {
                return nil
            } 
            self.init(cgImage: cgImage)
        }
    }
    
```

以下のような形で試してみたのですが、どうも使い方が違うようで、エラーが出ます。

```

    func session(_ session: ARSession, didUpdate frame: ARFrame)
    {
        guard let currentFrame = session.currentFrame else { return }
        let capturedImage = currentFrame.capturedImage
        let capturedUIImage = UIImage(pixelBuffer:capturedImage)
    }
    
```

エラー内容は、`No exact matches in call to initializer` というものです。  
convenience initとは何なのでしょうか？どのように使うものなのでしょうか？
CC BY-SA 4.0
2021-08-12T04:31:45.180
80739
2021-08-14T11:33:31.827
2021-08-12T04:37:59.100
3060
36446
question
swift
convenience init の使い方がわからない
> UIImageを以下のように拡張している

拡張を定義したファイルがプロジェクト(Swiftコンパイラ)から見えていないようです。

`ViewController`と同じファイルに以下の定義をおいても、ご質問に書かれたエラーは発生しません。

```

    import ARKit
    
    extension ViewController: ARSessionDelegate {
        func session(_ session: ARSession, didUpdate frame: ARFrame) {
            guard let currentFrame = session.currentFrame else { return }
            let capturedImage = currentFrame.capturedImage
            guard let capturedUIImage = UIImage(pixelBuffer: capturedImage) else {
                return
            }
            //...
        }
    }
    
    import VideoToolbox
    
    extension UIImage {
        public convenience init?(pixelBuffer: CVPixelBuffer) {
            var cgImage: CGImage?
            VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &cgImage)
    
            guard let cgImage = cgImage else {
                return nil
            }
            self.init(cgImage: cgImage)
        }
    }
    
```

(`UIImage`のextensionを古いSwiftでもコンパイルできるよう修正したコード。)

```

    import VideoToolbox
    
    extension UIImage {
        public convenience init?(pixelBuffer: CVPixelBuffer) {
            var cgImage: CGImage?
            VTCreateCGImageFromCVPixelBuffer(pixelBuffer, options: nil, imageOut: &cgImage)
    
            guard let theCGImage = cgImage else {
                return nil
            }
            self.init(cgImage: theCGImage)
        }
    }
    
```

* * *

使う側から見れば、convenienceイニシャライザは普通の`init`と変わりません。ただし、自分でサブクラスのイニシャライザを書こうと思うと、designatedイニシャライザとconvenienceイニシャライザの違いは、知らなくてはすまない基本なので、実際にコードを書く前にきちんと学習しておかれることをお勧めします。

[Class Inheritance and Initialization](https://docs.swift.org/swift-
book/LanguageGuide/Initialization.html#ID216)
CC BY-SA 4.0
2021-08-12T23:12:40.430
80758
2021-08-14T11:33:31.827
2021-08-14T11:33:31.827
13972
13972
80739
answer