Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」...
Search
monoqlo
September 01, 2018
Programming
31k
10
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」 / iOSDC 2018
iOSDC 2018 2018/09/01 14:40〜 Track B レギュラートーク(15分)
monoqlo
September 01, 2018
More Decks by monoqlo
See All by monoqlo
入門 SwiftUI Alignment Guide / iOSDC2022
monoqlo
11
6.4k
Hey Siri!マルチプラットフォームでのSiriショートカットの地雷を教えて / iOSDC2021
monoqlo
0
890
あなたのアプリ、✨リブランディング✨できますか? / iosdc2020
monoqlo
9
1.7k
実践 CallKit/PushKit ときどき🐛退治 / iOSDC 2019
monoqlo
4
4.1k
WWDC2016のススメ
monoqlo
0
140
Other Decks in Programming
See All in Programming
共通化で考えるべきは、実装より公開する型だった
codeegg
0
200
フィードバックで育てるAI開発
kotaminato
1
110
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
2.3k
SLOをサービス品質の共通言語にするために 取り組んできたこと
wakana0222
0
480
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
200
SREは、MCPとSRE Agentをこう使え!
kazumax55
0
150
初めてのKubernetes 本番運用でハマった話
oku053
0
120
そのテスト、説明できますか?~LWテスト戦略FW~のご紹介
nakahara
0
200
Performance Engineering for Everyone
elenatanasoiu
0
270
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.8k
エンジニアと一緒にテストコードの設計と実装を改善した話
mototakatsu
0
260
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
150
Featured
See All Featured
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
970
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
260
Claude Code のすすめ
schroneko
67
230k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
63
55k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.2k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
220
A Soul's Torment
seathinner
6
3k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
370
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.6k
Design in an AI World
tapps
1
260
Transcript
@monoqlo QRίʔυಡΈऔΓʁ ָউͰ͢Α AVFoundationΛ৴ͨ͡ ͓Ε͕όΧͩͬͨ
None
ḪΔ͜ͱ ಥવͰ͕͢
1
2017 3 ݄
ָউͰ͢Α✌✌ QRίʔυಡΈऔΔ ΞϓϦͭ͘ΕΔʁ
͜ͷ࣌ߟ͍͑ͯͨ͜ͱ
AVFoundation Ͱ༨༟Ͱ͠ΐ • AVCaptureSession • AVCaptureMetadataOutput • AVMetadataMachineReadableCodeObject • etc…
QRίʔυ ͞Εͨ
https://www.55truck.com/shaken.html
https://www.55truck.com/shaken.html
None
"8/-/1/-/- /- /999999/02” "2/- //160114/1001/BKG-NKR85” "AN/0168/- /- /0381/13/09” "2/ɹɹ̔̌̌ͤ̒̐̎” “̒/1/NKR85-7011300/4JJ1/1"
http://mangalifewin.takeshobo.co.jp/rensai/popute3/
"8/-/1/-/- /- /999999/02” "2/- //160114/1001/BKG-NKR85” "AN/0168/- /- /0381/13/09” "2/ɹɹ̔̌̌ͤ̒̐̎” “̒/1/NKR85-7011300/4JJ1/1"
"2/- //160114/1001/BKG-NKR85AN/0168/- /- /0381/13/098/-/1/-/- /- /999999/02” "2/ɹɹ̔̌̌ͤ̒̐̎̒/1/NKR85-7011300/4JJ1/1”
φχϞϊ ͜Ε…
None
http://www.qrcode.com
None
ͬͱ QRίʔυ ΛΖ͏
ใٕज़ʵࣗಈೝࣝٴͼσʔλऔಘٕज़ʵ ̧̦ίʔυόʔίʔυγϯϘϧମܥ༷ JIS ن֨ X0510
http://www.jisc.go.jp/
શ 115 ϖʔδ…
QRίʔυͷΈ μΠδΣετ൛
ࠇനϞδϡʔϧͷೝࣝ START ܕࣜใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ
“Ϟʔυ” ղऍ ෮߸͢ΔͨΊʹॏཁͳͷ͕
“Ϟʔυ” ͱ
• ECI • ߏత࿈ • FNC1 • (ऴύλʔϯ) • ࣈ
• ӳࣈ • 8ϏοτόΠτ • ࣈ Ϟʔυ = σʔλΛ֨ೲ͢Δܗࣜ • ѹॖޮ্Λతͱ͠ɺଟͷϞʔυ͕ఆٛ͞Ε͍ͯΔ • QRίʔυੜ࣌ɺσʔλʹ߹Θͤͯ࠷దͳͷΛબ͢Δ • ϔομʔͱͯ͠จࣈࢦࣔࢠͱͱʹσʔλʹՃ͢Δ • Έ߹Θͤͯ༻Մʢex. ӳࣈ + ࣈʣ ߏత࿈
• ࣈ • ӳࣈ • 8ϏοτόΠτ • ࣈ • ECI
• ߏత࿈ • FNC1 • (ऴύλʔϯ) Ϟʔυ = σʔλΛ֨ೲ͢Δܗࣜ • ѹॖޮ্Λతͱ͠ɺଟͷϞʔυ͕ఆٛ͞Ε͍ͯΔ • QRίʔυੜ࣌ɺσʔλʹ߹Θͤͯ࠷దͳͷΛબ͢Δ • ϔομʔͱͯ͠จࣈࢦࣔࢠͱͱʹσʔλʹՃ͢Δ • Έ߹Θͤͯ༻Մʢex. ӳࣈ + ࣈʣ ߏత࿈
ߏత࿈ Ϟʔυ
ϔομʔ༷ 1. Ϟʔυࢦࣔࢠʢ0011ʣɿ4bit 2. γϯϘϧྻࢦࣔࢠɿ8bit 1. γϯϘϧҐஔɿ4bit 2. ࿈݁͞ΕΔγϯϘϧͷ߹ܭɿ4bit 3.
ύϦςΟɿ8bit ׂલͷσʔλΛόΠτ͝ͱʹXORԋࢉͨ͠
None
ϓϩύςΟ var corners: [CGPoint] A Swift array of corner points.
var stringValue: String? Returns the error corrected data decoded into a human- readable string.
ͦΜͳͷͳ͍ AVMetadataMachineReadableCodeObject ʹ
ࠇനϞδϡʔϧͷೝࣝ START ܕࣜใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ AVMetadataMachine ReadableCodeObject ͷ
stringValue ෳ߹ޙͷίϨ
ϥΠϒϥϦΛ୳͢ ߏత࿈Λ͏·͘ѻ͑Δ
None Swift ͷϥΠϒϥϦ
None
ZXingObjC ٹੈओ TheLevelUp/ZXingObjC: An Objective-C Port of ZXing
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return }
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … }
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return }
ղܾ ͬͨʔʂʂ
ຊʹʁ
ZXingObjC ͷऑ • ಡΈऔΓਫ਼͕͋·Γߴ͘ͳ͍ • AVFoundation σϯιʔެࣜΞϓϦʹൺΔͱ݁ߏ ͕͔͔࣌ؒΔ͜ͱ͕͋Δ • ։ൃ͕࣮࣭ࢭ·͍ͬͯΔ
• Swift ʹஔ͖͍͑ͨͱ͔ॻ͔ΕͯΔ͚Ͳ͍ͭʹͳΔ ͔·ͬͨ͘Θ͔Βͳ͍
ઈ ະདྷ͕ͳ͍
ઈ ະདྷ͕ͳ͍ ʁ
ઈ ະདྷ͕ͳ͍ ʁ 2017 ·Ͱͷ͓
࣌ྲྀΕ… 2018 9 ݄ 1
iOS ͷόʔδϣϯγΣΞભҠ ݄ ݄ ݄
݄ ݄ ݄ ݄ ݄ ݄ iOS 11 iOS 10 iOS 9 or Earlier ※ 20189݄༧ଌ
iOS 10 ͷαϙʔτ ͦΖͦΖΕ·͢ΑͶʁ ࠓ݄ iOS 12 ͕ϦϦʔε͞Ε·͢
CIQRCodeDescriptor ਅͷٹੈओ in AVMetadataMachineReadableCodeObject
ϓϩύςΟ var corners: [CGPoint] A Swift array of corner points.
var stringValue: String? Returns the error corrected data decoded into a human- readable string. var descriptor: CIBarcodeDescriptor? A barcode description for use in Core Image.
CIQRCodeDescriptor ͱ
CIQRCodeDescriptor ͱ • iOS 11 ͰՃ͞ΕͨڧྗͳΫϥε • நΫϥε CIBarcodeDescriptor ͷαϒΫϥε
• QRίʔυΛੜ͢ΔͨΊʹඞཁेͳσʔλΛ࣋ͭ • CIFilter Ͱ QRίʔυը૾Λੜ͢Δ͜ͱͰ͖Δ
CIQRCodeDescriptor ͱ • iOS 11 ͰՃ͞ΕͨڧྗͳΫϥε • நΫϥε CIBarcodeDescriptor ͷαϒΫϥε
• CIFilter Ͱ QRίʔυը૾Λੜ͢Δ͜ͱͰ͖Δ func generateQRCodeImage(from descriptor: CIQRCodeDescriptor) -> UIImage? { let inputParams: [String: Any] = ["inputBarcodeDescriptor": descriptor] let barcodeCreationFilter = CIFilter(name: "CIBarcodeGenerator", parameters: inputParams) guard let outputImage = barcodeCreationFilter?.outputImage, let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
େࣄͳͷ͜ͷ 2 ͭ var errorCorrectedPayload: Data The error-corrected payload containing
the data encoded in the QR code. var symbolVersion: Int The version of the QR code.
ࠇനϞδϡʔϧͷೝࣝ START ܕࣜใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ AVMetadataMachine ReadableCodeObject ͷ
stringValue ෳ߹ޙͷίϨ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ errorCorrectedPayload ίίͷσʔλʂ
େࣄͳͷ͜ͷ 2 ͭ var errorCorrectedPayload: Data The error-corrected payload containing
the data encoded in the QR code. var symbolVersion: Int The version of the QR code.
େࣄͳͷ͜ͷ 2 ͭ var errorCorrectedPayload: Data The error-corrected payload containing
the data encoded in the QR code. var symbolVersion: Int The version of the QR code.
จࣈࢦࣔࢠͷϏοτ ܕ൪ TZNCPM7FSTJPO ࣈ Ϟʔυ ӳࣈ Ϟʔυ ϏοτόΠτ Ϟʔυ ࣈ
Ϟʔυ ʙ ʙ ʙ
symbolVersion + errorCorrectedPayload σίʔυͰ͖Δ
ͱ͍͏͜ͱ…ʁ
iOS 11 Ҏ߱ͷੈքͰ 1. AVCaptureSession ͰಡΈऔΔ ߴਫ਼Ͱ͍
iOS 11 Ҏ߱ͷੈքͰ AVMetadata Machine ReadableCode Object 2. CIQRCodeDescriptor #errorCorrectedPayload
ΛऔΓग़͢ 1. AVCaptureSession ͰಡΈऔΔ
iOS 11 Ҏ߱ͷੈքͰ AVMetadata Machine ReadableCode Object 2. CIQRCodeDescriptor #errorCorrectedPayload
ΛऔΓग़͢ σίʔυ͢Δ 1. AVFoundation ͰಡΈऔΔ ͕Μͬͯ 3.
ղܾ ͬͨʔʂʂࠓͦ͜
σίʔυ͢Δ ͕Μͬͯ 3. ͕Μͬͯ
͕ΜΔ = ࣗલͰσίʔυॲཧΛॻ͘
ࣗલσίʔυͷํ • શϞʔυʹରԠ͠Α͏ͱࢥͬͨΒʢͨͿΜʣ݁ߏେม… • ͱ͍͏͔σϯιʔެࣜΞϓϦରԠͯ͠ͳ͍ • ࠷ݶಡΈऔΓ͍ͨQRίʔυͷσίʔυॲཧͰଥڠ • ಠࣗΤϯίʔυ͞ΕͨQRίʔυσίʔυͰ͖Δ͠ɺ ෯͕͕Δʢͱ͔ॻ͍ͯΔ͏ͪʹσϯιʔ͕Ԍ্͠·ͨ͠ʣ
=> https://srad.jp/submission/78134/
σίʔυͷҰྫ https://github.com/ monoqlo/QRCodeReader
࣌ؒ͋Ε গ͚ͩ͠ DEMO
·ͱΊ
0. iOS 10 ͷαϙʔτΛΔʢҰ൪େࣄʣ
·ͱΊʢiOS 11 Ҏ߱ͷੈքʣ 1. AVCaptureSession ͰಡΈऔΔ AVMetadata Machine ReadableCode Object
2. CIQRCodeDescriptor #errorCorrectedPayload ΛऔΓग़͢ ͕Μͬͯσίʔυ͢Δ 3.
Appendix • Speaker Info @monoqlo • This Slide URL https://speakerdeck.com/monoqlo/iosdc-2018