$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Swiftとメタデータ
Search
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
400
Spice up your notifications/try!Swift25
noppefoxwolf
3
780
iOSの隠されたAPIを解明し、開発効率を向上させる方法/iOSDC24
noppefoxwolf
2
1k
今から理解するApp Intentエコシステム/WWDC24Recap
noppefoxwolf
0
32
既存アプリをvisionOS対応してリリースした話/visionOS LT vol5
noppefoxwolf
0
210
UIのブラックボックスを探る/iOSDC23
noppefoxwolf
3
4.7k
CoreGraphicsでドット絵を描こう/iOSDC22
noppefoxwolf
0
2.9k
ランタイムデバッグのススメ/iOSDC21
noppefoxwolf
1
5.1k
google/mediapipe で始めるARアプリ開発/iOSDC2020
noppefoxwolf
1
1.6k
Other Decks in Technology
See All in Technology
7,000万ユーザーの信頼を守る「TimeTree」のオブザーバビリティ実践 ( Datadog Live Tokyo )
bell033
1
100
Strands Agents × インタリーブ思考 で変わるAIエージェント設計 / Strands Agents x Interleaved Thinking AI Agents
takanorig
5
2.1k
TED_modeki_共創ラボ_20251203.pdf
iotcomjpadmin
0
150
MySQLのSpatial(GIS)機能をもっと充実させたい ~ MyNA望年会2025LT
sakaik
0
130
オープンソースKeycloakのMCP認可サーバの仕様の対応状況 / 20251219 OpenID BizDay #18 LT Keycloak
oidfj
0
190
意外と知らない状態遷移テストの世界
nihonbuson
PRO
1
270
AI駆動開発の実践とその未来
eltociear
2
500
モダンデータスタックの理想と現実の間で~1.3億人Vポイントデータ基盤の現在地とこれから~
taromatsui_cccmkhd
2
270
通勤手当申請チェックエージェント開発のリアル
whisaiyo
3
480
テストセンター受験、オンライン受験、どっちなんだい?
yama3133
0
180
ESXi のAIOps だ!2025冬
unnowataru
0
390
[2025-12-12]あの日僕が見た胡蝶の夢 〜人の夢は終わらねェ AIによるパフォーマンスチューニングのすゝめ〜
tosite
0
190
Featured
See All Featured
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
1.7k
Getting science done with accelerated Python computing platforms
jacobtomlinson
0
79
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
286
14k
Utilizing Notion as your number one productivity tool
mfonobong
2
190
Optimising Largest Contentful Paint
csswizardry
37
3.5k
The Curse of the Amulet
leimatthew05
0
4.8k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3k
Navigating Team Friction
lara
191
16k
Art, The Web, and Tiny UX
lynnandtonic
304
21k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
0
46
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
My Coaching Mixtape
mlcsv
0
13
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