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
iOS18でQRコードが表示されなくなった🤷
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Ryomm
December 06, 2024
Programming
0
140
iOS18でQRコードが表示されなくなった🤷
2024.12.06 KTC×WED×フェンリル 3社合同イベント
Ryomm
December 06, 2024
Tweet
Share
More Decks by Ryomm
See All by Ryomm
なあ兄弟、 余白の意味を考えてから UI実装してくれ!
ktcryomm
11
11k
iOSでQRコード生成奮闘記
ktcryomm
2
310
リョムキャットのパーフェクトSwiftネーミング教室
ktcryomm
0
2.3k
Slackを使いこなせ!Slack効率3000倍
ktcryomm
0
1.3k
クソアプリ作って煙突詰めた♪
ktcryomm
0
98
Other Decks in Programming
See All in Programming
Vibe Coding - AI 驅動的軟體開發
mickyp100
0
180
24時間止められないシステムを守る-医療ITにおけるランサムウェア対策の実際
koukimiura
1
130
Smart Handoff/Pickup ガイド - Claude Code セッション管理
yukiigarashi
0
150
今こそ知るべき耐量子計算機暗号(PQC)入門 / PQC: What You Need to Know Now
mackey0225
3
380
今から始めるClaude Code超入門
448jp
8
9.1k
AIフル活用時代だからこそ学んでおきたい働き方の心得
shinoyu
0
140
CSC307 Lecture 05
javiergs
PRO
0
500
20260127_試行錯誤の結晶を1冊に。著者が解説 先輩データサイエンティストからの指南書 / author's_commentary_ds_instructions_guide
nash_efp
1
990
Fluid Templating in TYPO3 14
s2b
0
130
高速開発のためのコード整理術
sutetotanuki
1
410
CSC307 Lecture 03
javiergs
PRO
1
490
IFSによる形状設計/デモシーンの魅力 @ 慶應大学SFC
gam0022
1
310
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
4 Signs Your Business is Dying
shpigford
187
22k
We Are The Robots
honzajavorek
0
170
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
1
5.2k
sira's awesome portfolio website redesign presentation
elsirapls
0
150
Building an army of robots
kneath
306
46k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
230
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
350
A Soul's Torment
seathinner
5
2.3k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
1.8k
We Have a Design System, Now What?
morganepeng
54
8k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
60
42k
Transcript
None
None
None
None
調査の結果、どうやらこちらのコードでnilが返ってきているっぽい
このコードでは何をしているかというと、こちらの名前の通り…
文字列として渡されたバイナリからQRコードを作っています
ここで、QRコードの仕様について補足、、 QRコードに格納ができるデータはこちらの4種類です。 この中で、8ビットバイトモードを使うとバイナリを格納することが可能です。 バイナリを入れられるということは、日本語以外でもどんな文字列でも入れられるということです。
my routeでは文字列として受け取ったバイナリを16進数バイナリとしてQRコードで読み取れるようにする処理があります。 先ほどのコードでは、このへんで変換を行なっています。
わかりやすさのため、具体的にみていきます。 先ほどのコードを分解するとこのようになっています。
文字列として謎のバイナリXを受け取って、それを16進数バイナリ、つまりData型に変換します。
例えば謎のバイナリXを 6e79dc68 とします。
普通にutf8でData型にすると、元の値がただの文字列として扱われてしまいます。 Data型にした時に、受け取った文字列がカンマが取れるようにしたいので、コネコネします。
まずは文字列を16を基数として変換し、数字として扱えるようにします。 ここではBigNumberというライブラリを使って変換していますが、標準のIntでも似たようなことができます。10進数にすると 1853480040 となりました。 BIntというのは、8バイトの整数を格納できる型です。ここでは普通の整数だと思ってもらって大丈夫です。
続いて、UInt8の配列に変換します。 先ほどのBigNumberライブラリを使うと簡単に取得することができます。 ライブラリ上ではBytesという表記ですが、これはtypealiasで[UInt8]となっています UInt8とは2進数で8ビットまで格納できる型で、一個前の10進数を2進数に変換し、お尻から8桁ずつ切り取って配列にしたものです。頭の足りない分は0で埋めています。
そして、UInt8の配列をData型にするため、文字列とエンコード方式のセットを取得したいです。 そのため、エンコード方式を把握した状態で一旦String型に変換します。
最後に、先ほどエンコードした方法で、今度は文字列をData型にエンコードします
これで、受け取った文字列をData型に変換することができるようになりました! 値が同じままダブルクォートが取れていることがわかります
そう、iOS17までは…
iOS18において、UInt8の配列をStringに変換しようとしたとき、nilが返ってくるようになってしまいました!
Swift6の大きな変更のひとつに、Foundationの実装移行があります。 FoundationにはAppleプラットフォーム向けのと、LinuxなどApple以外のプラットフォーム向けのものがあります。 Swift5では、どちらもCoreFoundationというC言語で作られた内部実装に深く依存しています。 ただ、これはObjCとの親和性が高い実装なので、Swiftで実装し直されました
それが、swift-foundationです。 Swift6のタイミングで、この内部実装が切り替わりました。
そして、iOSにおいて、FoundationはOS内蔵のものが使われていると言われています つまり、iOS18になったタイミングでiOS18に内蔵されたFoundationの参照先がswift-foundationになったことで、iOS18でロジックが壊れる影響が出たと考えられます。 では、Foundationが変わったことで、Stringのinitでどんな差分が発生しているのか詳しく見てみます。 (discordでIcemanさんに教えてもらいました)
問題のコードではUTF-16BEでデコードしています。 UTF-16は0000からFFFFまで全部使う規格なので、基本的にサロゲートペア以外でデコードには失敗しません。 サロゲートペアとは、、 UTF-16においては基本的に2バイトで文字を表現しますが、それだと65535個の文字しか表現できないため、さらに拡張するために編み出されたものです。 D800〜DBFFの上位サロゲートと、DC00〜DFFFの下位サロゲートを組み合わせて表現します。 で、先ほどのUTF-16BEでデコードしようとしていた値を見てみます。 2つ目のdc68が下位サロゲートのコード範囲にあたっています! しかし、ペアとなる上位サロゲートがないためデコードは失敗します (discordでomochimetalさんに教えてもらいました)
前は何かしらの値を無理矢理返却していましたが、新しいfoundationではデコードに失敗した時にnilが返ってくるように仕様が変わっていたのです。
(回想) 100%再現するわけじゃない、という現象の理由は、 たまたまデコードできた時にはQRコードが表示されていたってことか…
変換処理を修正しようと思います。 まず、謎のバイナリXは、なにでエンコードされたものかわかりません。 なので、なんでもいいから一旦デコードして、Stringとそのエンコード方式のペアを取得したいです。
そう、、なんでもいいから一旦デコードしたい…!
名付けて総当たり大作戦!! なんでもいいから一旦デコードできるものを探します!!
ゲットしたStringとエンコード方式を使ってData型に変換します! やったー!変換に成功した!
None
なんか…違和感がある…
…これいる? [UInt8]からData型の変換もっとシンプルにできないの? 総当たりで探し回って一旦String型に変換するのって変じゃない??
[UInt8]からDataへ変換する他の方法を探していると、このような記載を発見しました
None
[UInt8]からStringへの変換処理、全然いらんかったー!
超シンプルにData(byte)でよかった
うわあああこれをQRコード生成メソッドに組み込んで完成!
foundationの内部実装の切り替えの煽りを受けた結果、遠回りした実装になってたことがわかったはなしでした〜
QRコードのデータのモードを判別するにはモード指示子を解読する必要があります。 そしてそれを解読する前にQRコードのマスクパターンを取得します。今回は000なので、こちらの計算式が得られました。
取得したマスクパターンとモード指示子の4ビットの排他論理和を取得します。 これは0100なので、8ビットバイトモードだ!とわかりました