iPhone 14 Proでオートフォーカスが効かなかった。

13シリーズまではこれだけのコードで済んでたのが、14 Proでオートフォーカスが効かなくなって、だいぶ試行錯誤したのでメモ。
captureDevice = AVCaptureDevice.default(for: .video)

default(for:) | Apple Developer Documentation

Returns the default device that captures the specified media type.

(ここで言っているオートフォーカスとは、 AVCaptureDevice.FocusMode に .autoFocus か .continuousAutoFocus を指定したときの挙動です。)

AVCaptureDevice.FocusMode | Apple Developer Documentation

Constants to specify the focus mode of a capture device.

まず、最終的にはこんな感じになってます。
// iPhone15,2 (iPhone 14 Pro) または iPhone15,3 (iPhone 14 Pro Max)
if platform().hasPrefix("iPhone15") {
  captureDevice = AVCaptureDevice.default(.builtInTripleCamera, for: .video, position: .back)
}
if captureDevice == nil {
  if let device = AVCaptureDevice.default(.builtInDualCamera, for: .video, position: .back) {
    captureDevice = device
  } else if let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) {
    captureDevice = device
  } else if let device = AVCaptureDevice.default(for: .video) {
    captureDevice = device
  }
}

default(_:for:position:) | Apple Developer Documentation

Returns the default device for the specified device type, media type, and position.

ちなみに platform() はこんな感じでなってて、 iPhone13,3 とか iPhone15,2 みたいなマシンID(って呼び方でいいんですかね?)が返る。
func platform() -> String {
  var size = 0
  sysctlbyname("hw.machine", nil, &size, nil, 0)
  var machine = [CChar](repeating: 0, count: size)
  sysctlbyname("hw.machine", &machine, &size, nil, 0)
  return String(cString: machine)
}
モデル名との対応はこちら。(まとめありがたい。)

List of Apple’s mobile device codes types a.k.a. machine ids (e.g. `iPhone1,1`, `Watch1,1`, etc.) and their matching product names

List of Apple’s mobile device codes types a.k.a. machine ids (e.g. `iPhone1,1`, `Watch1,1`, etc.) and their matching product names

で、ここからは経緯です。

最初は AVCaptureDevice.FocusMode を指定するときになにかオプションが増えているんじゃないかと疑い、APIドキュメントを読みながら関連しそうなオプションを片っ端から試すも、挙動に影響が出ず丸一日を溶かす。
次にデバイスを取得するところを、ってことで AVCaptureDevice.default を疑い、オプションを端から試したところビンゴだったがここでまた別の問題が発生。
手元にあった実機がiPhone 12 ProとiPhone 14 Proで、どちらもカメラが3つのため DeviceType に .builtInTripleCamera を指定してデバイスが取れるが、14 Proでは問題なくオートフォーカスが効くようになったものの、今度は12 Proで効かなくなる。
では12 Proで効くパターンはというと、 .builtInDualCamera を指定したとき。カメラ3つなのに。
そして .builtInTripleCamera は .builtInDualCamera の上位互換なので14 Proでも .builtInDualCamera でデバイスは取れるものの、こっちはオートフォーカスが効かない。

ということで、マシンIDを見てTripleとDualの指定を分けなければいけない状態になりました。
たぶんどちらも .builtInTripleCamera で問題なく動くべきで、これはAPIのバグなんじゃないかと疑っている次第なんですが、今後のアップデートで挙動は変わるんでしょうか。ひとまず。

タイトルとURLをコピーしました