iOSDC Japan 2020で発表してきた内容でいくつか受けた質問の答えや補足&参加した感想になります
あなたの知らない連絡先の世界
はてなブックマークで紹介されたらしく、えらい数見ていただいてます。
vCard 3.0(iOS)と vCard 2.1(Android)
Androidで取得したvCardは、Quoted-printableがかかっています。
iOS
BEGIN:VCARD
VERSION:3.0
PRODID:-//Apple Inc.//iPhone OS 13.6//EN
N:日向;強;搩;ドクター;三世
FN:ドクター 強 搩 日向 三世
END:VCARD
Android
BEGIN:VCARD
VERSION:2.1
N;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E6=97=A5=E5=90=91=E7=81=98;=E5=BC=B7;=46;=44=72;=4A=72
FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=44=72=20=E6=97=A5=E5=90=91=E7=81=98=20=46=20=E5=BC=B7=20=4A=72
END:VCARD
PersonNameComponentsFormatterはサーバーサイドSwiftで使える?
使えませんでした。NSUnsupportedでした。
https://github.com/apple/swift-corelibs-foundation/blob/2a5bc4d8a0b073532e60410682f5eb8f00144870/Sources/Foundation/PersonNameComponentsFormatter.swift
Objective-Cでしか使えないメソッド
本編で紹介した enumeratorForChangeHistoryFetchRequest:error:
の他にも、
連絡先を取得するenumeratorForContactFetchRequest:error:
もObjective-Cでしか使えません。
SwiftUI? Combine? 甘
https://developer.apple.com/documentation/contacts/cncontactstore/3294191-enumeratorforcontactfetchrequest?changes=_3&language=objc
詳解storyboard
SceneDelegateのリストア
今回発表されていた iPadOSDC: Multiple Windows
で解説されています。
https://speakerdeck.com/hironytic/ipadosdc-multiple-windows
Appleのサンプルドキュメントもあります。
https://developer.apple.com/documentation/uikit/uiscenedelegate/restoring_your_app_s_state
Storyboardの分割
WWDC 19のGreat Developer Habits
にてStoryboardの分割に触れています。
その他にもエンジニアにとって重要な話をしているので、このセッションは非常におすすめです。
https://developer.apple.com/videos/play/wwdc2019/239/
まばたきの検出
本編では省略したまばたきの検出コードですが、例えば AVCaptureVideoDataOutputSampleBufferDelegate
でCMSampleBufferから顔を検出し、目を閉じている、開いているを検出して判定するとまばたきの検出が行えます。
以下のコードは、両目を閉じている人を検出してアクションを起こす例です。まばたき検出はもうちょっとコードが必要になります。
// MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
func captureOutput(_ output: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {
let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let ciImage: CIImage = CIImage(cvPixelBuffer: pixelBuffer)
guard let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: [CIDetectorAccuracy:CIDetectorAccuracyHigh]) else {
return
}
let faceFeatures = faceDetector.features(in: ciImage, options: [
CIDetectorSmile:true,
CIDetectorEyeBlink:true
]) as! [CIFaceFeature]
let closedEyes = faceFeatures.filter { (faceFeature) -> Bool in
return faceFeature.leftEyeClosed && faceFeature.rightEyeClosed
}
if !closedEyes.isEmpty {
self.sendActions(for: .primaryActionTriggered)
}
}
個人的な感想
よかったら二つやりませんか?との打診を受けて、Storyboardだけやろうかなと思ったんですが、せっかくだから俺はどちらとも選ぶぜという勢いのみでやってみました。
結果的には本命のStoryboardではなく連絡先が好評?だったので、フェイルセーフが働いて良かったです。
セッションは20分コースと40分コースがあって、40分喋り続けるのきついなと思ってチキって20分にしたんですが、「持ち時間が40分もらえる」という考えであれば、次出られるのであれば長い時間はありかな、と思いました。Storyboardは説明がいっぱいいっぱいだったので小粋なトークが挟めませんでした。
なんにせよ、見ていただいた方、ご清聴ありがとうございました!ご清聴?