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
Swiftとメタデータ
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
noppefoxwolf
June 20, 2018
Technology
3
850
Swiftとメタデータ
SwiftとObjective-Cのruntime APIの比較と`wickwirew/Runtime`のプロパティ名取得実装の読み解きです。
noppefoxwolf
June 20, 2018
Tweet
Share
More Decks by noppefoxwolf
See All by noppefoxwolf
High performance GIF playback/iOSDC25
noppefoxwolf
1
450
Spice up your notifications/try!Swift25
noppefoxwolf
3
790
iOSの隠されたAPIを解明し、開発効率を向上させる方法/iOSDC24
noppefoxwolf
2
1k
今から理解するApp Intentエコシステム/WWDC24Recap
noppefoxwolf
0
36
既存アプリをvisionOS対応してリリースした話/visionOS LT vol5
noppefoxwolf
0
210
UIのブラックボックスを探る/iOSDC23
noppefoxwolf
3
4.8k
CoreGraphicsでドット絵を描こう/iOSDC22
noppefoxwolf
0
3k
ランタイムデバッグのススメ/iOSDC21
noppefoxwolf
1
5.2k
google/mediapipe で始めるARアプリ開発/iOSDC2020
noppefoxwolf
1
1.6k
Other Decks in Technology
See All in Technology
~Everything as Codeを諦めない~ 後からCDK
mu7889yoon
3
330
Greatest Disaster Hits in Web Performance
guaca
0
210
SREチームをどう作り、どう育てるか ― Findy横断SREのマネジメント
rvirus0817
0
200
AWS Network Firewall Proxyを触ってみた
nagisa53
1
220
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.8k
Tebiki Engineering Team Deck
tebiki
0
24k
日本の85%が使う公共SaaSは、どう育ったのか
taketakekaho
1
150
プロダクト成長を支える開発基盤とスケールに伴う課題
yuu26
4
1.3k
SREが向き合う大規模リアーキテクチャ 〜信頼性とアジリティの両立〜
zepprix
0
440
広告の効果検証を題材にした因果推論の精度検証について
zozotech
PRO
0
170
Amazon S3 Vectorsを使って資格勉強用AIエージェントを構築してみた
usanchuu
3
450
2026年、サーバーレスの現在地 -「制約と戦う技術」から「当たり前の実行基盤」へ- /serverless2026
slsops
2
240
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
1.8k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
250
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
350
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.3k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
1.9k
Principles of Awesome APIs and How to Build Them.
keavy
128
17k
Embracing the Ebb and Flow
colly
88
5k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.6k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
57
50k
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
61
52k
Transcript
4XJGUͱϝλσʔλ 4XJGUѪձWPM ! !OPQQFGPYXPMG
OPQQF ! ͖ͭͶ͕͖ʂʂ " J04ΞϓϦ։ൃ 4XJGUѪձॳࢀઓ ! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
ϝλσʔλͱ ϝλใͱɺ͢ͳΘͪσʔλʹ͍ͭͯͷσʔλͱ͍͏ ҙຯͰɺ͋Δσʔλ͕ਵͯ࣋ͭͦ͠ͷσʔλࣗʹͭ ͍ͯͷՃతͳσʔλΛࢦ͢ɻʢ8JLJௐʣ ! IUUQTKBXJLJQFEJBPSHXJLJϝλσʔλ ! !OPQQFGPYXPMG
ϝλσʔλͱ ‣ Ϋϥε໊ ‣ ΫϥεͷϓϩύςΟ໊ ‣ ܧঝݩ ‣ ४ڌ͍ͯ͠Δϓϩτίϧ FUD
! !OPQQFGPYXPMG
ϝλσʔλ͕ඞཁͳ࣌ ‣ ࠓݟ͍ͯΔϏϡʔίϯτϩʔϥΛϩάʹు͖͍ͨ ‣ ΠϯελϯεΛμϯϓͯ͠อଘ͍ͨ͠ ‣ ৄࡉͰ͔Γ͍͢ΤϥʔΛද͍ࣔͨ͠ ‣ ͍͍ײ͡ͷ03.࡞Γ͍ͨͱ͔ FUD
! !OPQQFGPYXPMG
4XJGUͰϝλσʔλΛऔಘ͢ΔʹͲ͏͢Ε͍͍ʁ ! !OPQQFGPYXPMG
ͦ͏͍͑0CKFDUJWF$ͰͲ͏͍ͯͨ͠ͷ͔ʁ ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ 0CKFDUJWF$SVOUJNF"1* class_copyPropertyList(_:_:) IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPO PCKFDUJWFDDMBTT@DPQZQSPQFSUZMJTU ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ unsigned int propertyCount = 0; objc_property_t * properties =
class_copyPropertyList([self class], &propertyCount); NSMutableArray * propertyNames = [NSMutableArray array]; for (unsigned int i = 0; i < propertyCount; ++i) { objc_property_t property = properties[i]; const char * name = property_getName(property); [propertyNames addObject:[NSString stringWithUTF8String:name]]; } free(properties); NSLog(@"Names: %@", propertyNames); ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ 0CK$SVOUJNF"1*4XJGUͰ͏͜ͱ͕Ͱ͖Δɻ import ObjectiveC ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ var count: UInt32 = 0 let properties = class_copyPropertyList(MyClass.self,
&count) for i in 0..<Int(count) { let prop = properties![i] let propName = String(cString: property_getName(prop)) print(propName) } ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ 4XJGUͰDMBTT@DPQZ1SPQFSUZ-JTUΛ͏ʹ੍ݶ͕͋Δ class MyClass: NSObject { @objc var prop1 =
"" @objc var prop2 = "" } ϓϩύςΟʹ@objcΛ͚ͭΔ͜ͱʂ˞ ˞!PCKD͕ඞཁͰ͋Γɺ/40CKFDUΛܧঝ͢Δඞཁͳ͍ɻ·ͨ!PCKDΛ͚ͭΔʹDMBTTͰ͋Δඞཁ͕͋Δ ! !OPQQFGPYXPMG
!PCKDΛ͚ͣʹϓϩύ ςΟҰཡΛऔಘ͢Δํ๏ ͳ͍Ͱ͠ΐ͏͔ʜʁ ! !OPQQFGPYXPMG
ϓϩύςΟҰཡΛऔಘ͢Δ &ODPEBCMF class MyClass: Encodable { var prop1 = ""
var prop2 = "" } let data = try! JSONEncoder().encode(MyClass()) let json = try! JSONSerialization.jsonObject(with: data, options: .allowFragments) print((json as! [String : Any]).keys) ‣ <QSPQ QSPQ> ! !OPQQFGPYXPMG
SFqFDUJPO let mirror = Mirror(reflecting: MyClass()) let propNames = mirror.children.compactMap({
$0.label }) ! !OPQQFGPYXPMG
0CKFDUJWF$SVOUJNF "1*ʹ૬͢Δ GSBNFXPSLແ͍ͷ͔ʜ ! !OPQQFGPYXPMG
TXJGUEPDT3VOUJNFNE 5IFpOBMSVOUJNFJOUFSGBDFJTDVSSFOUMZ BXPSLJOQSPHSFTT ͳͦ͞͏ IUUQTHJUIVCDPNBQQMFTXJGUCMPCNBTUFSEPDT3VOUJNFNE ! !OPQQFGPYXPMG
5IJSEQBSUZSVOUJNF"1* IUUQTHJUIVCDPNXJDLXJSFX3VOUJNF IUUQTHJUIVCDPN;FXP3FqFDUJPO ! !OPQQFGPYXPMG
XJDLXJSFX3VOUJNF var md = ClassMetadata(type: MyClass<Int>.self) let info = md.toTypeInfo()
info.properties.compactMap { $0.name } ! !OPQQFGPYXPMG
1SPT$POT !PCKD JOTUBODF NFUBEBUB 0CK$SVOUJNF Y P P &ODPEBCMF P
Y Y SFqFDUJPO P Y ˚ UIJSEQBSUZBQJ P P P ! !OPQQFGPYXPMG
☺ ͡Ό͋5IJSEQBSUZͷ͓͏ʙʙ ! !OPQQFGPYXPMG
3VOUJNF3FqFDUJPO Ͳ͏ͬͯϝλσʔλΛऔ ಘ͍ͯ͠Δͷ͔ʁ ! !OPQQFGPYXPMG
3VOUJNFͷॲཧ 5ZQF͕อ࣋͞Ε͍ͯΔϝϞϦΛࢀরͯ͠ϝλσʔ λΛऔಘ͍ͯ͠Δɻ ͜ΕΒΛߏମʹͯቕΊ͍͍ͯ͢Α͏ʹͨ͠ϥΠ ϒϥϦ ϝϞϦͷϨΠΞτߏυΩϡϝϯτ͕͋Δ ! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
45&1 var type: Any.Type = Kind.self let typeAsPointer = unsafeBitCast(type,
to: UnsafeMutablePointer<Int64>.self) let metadataPointer = typeAsPointer.advanced(by: -1) let metadataRawPointer = UnsafeMutableRawPointer(metadataPointer) UZQFࣗମͷϙΠϯλ͔ΒੜϙΠϯλΛऔಘ͢Δ ! !OPQQFGPYXPMG
! !OPQQFGPYXPMG
<ิ>WBMVFXJUOFTTUBCMF ؔΛݺͼग़࣌͢ʹܦ༝͢Δςʔϒϧ 3VOUJNFͰ͜ͷαΠζॱংΛݩʹΠϯελϯεͷϝ ϞϦߏΛ࡞Γग़ͯ͠ແཧΓੜ͢Δػೳ͕͋Δ ! !OPQQFGPYXPMG
45&1 let layout = metadataRawPointer.assumingMemoryBound(to: StructMetadataLayout.self) assumingMemoryBoundͰϙΠϯλΛ .FUBEBUB-BZPVUͷߏͷϙΠϯλͱղऍ͠·͢ɻ ! !OPQQFGPYXPMG
45&1 4USVDU.FUBEBUB-BZPVUTXJGU struct StructMetadataLayout: NominalMetadataLayoutType { var valueWitnessTable: UnsafePointer<ValueWitnessTable> var
kind: Int var nominalTypeDescriptor: UnsafeMutablePointer<NominalTypeDescriptor> } ! !OPQQFGPYXPMG
45&1 structLayout.kind //1 enumLayout.kind //2 protocolLayout.kind //12 ͜ΕͰϝϞϦͷߏΛTUSVDUʹϚοϐϯά͢Δࣄ͕ग़དྷ ͨ !
!OPQQFGPYXPMG
45&1 Nominal Type Descriptorͷoffset: ͕̐field namesͳͷͰͦ͜ͷ࣮ମΛࢀর͢ΔͱɺϓϩύςΟ໊ͷ $4USJOHͷྻ͕औಘͰ͖Δɻ ! !OPQQFGPYXPMG
45&1 struct Animal { var name: String } let cString
= metadata.pointee.nominalTypeDescriptor.pointee.fieldNames.advanced() String(cString: cString) → name $4USJOHͷࢀরΛ4USJOHʹม͢ΔͱɺϓϩύςΟ໊͕ औಘͰ͖Δɻ ! !OPQQFGPYXPMG
45&1 ͋ͱ͜ͷ$4USJOHͷࢀরΛϓϩύςΟζϥͯ͠औಘ ͍͚ͯ͠ɺશͯͷϓϩύςΟ໊͕औಘͰ͖Δɻ ࣮ࡍଞͷϙΠϯλ͔ΒϓϩύςΟͷΛऔಘͯͦ͠ͷΛऔಘ͍ͯ͠Δ ! !OPQQFGPYXPMG
8BSOJOH ͜ͷํ๏વ4XJGUͷ༷มߋͰϝϞϦͷϨΠΞτ ͕มΘΔͱ͑ͳ͘ͳΔɻ 4XJGU"#*4UBCJMJUZ.BOJGFTUP IUUQTHJUIVCDPNBQQMFTXJGUCMPCNBTUFSEPDT"#*4UBCJMJUZ.BOJGFTUPNE ! !OPQQFGPYXPMG
&YBNQMFQSPKFDU IUUQTHJUIVCDPNOPQQFGPYXPMG.FUBEBUB&YBNQMF ! !OPQQFGPYXPMG
·ͱΊ ‣ ϝλσʔλʹΞΫηε͢Δํ๏ෳ͋ΓҰҰ Ͱ͋Δ ‣ ७4XJGUͳߏମͷ.FUBEBUBΛ҆શʹಘΔํ๏· ͩແ͍ɻ ‣ ϝϞϦΛࢀর͢ΔࣄͰɺ௨ৗऔಘग़དྷͳ͍ଟ͘ͷ ใʹΞΫηεͰ͖Δ
! !OPQQFGPYXPMG